code-ai-installer 1.1.4 → 1.1.6
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/README.md +4 -0
- package/dist/banner.d.ts +4 -0
- package/dist/banner.js +35 -0
- package/dist/index.js +109 -22
- package/dist/sourceResolver.d.ts +2 -0
- package/dist/sourceResolver.js +27 -5
- package/dist/types.d.ts +1 -0
- package/locales/en/.agents/a11y_baseline/SKILL.md +41 -0
- package/locales/en/.agents/adr_log/SKILL.md +69 -0
- package/locales/en/.agents/api_contract_compliance_review/SKILL.md +18 -0
- package/locales/en/.agents/api_contracts/SKILL.md +42 -0
- package/locales/en/.agents/architecture_compliance_review/SKILL.md +17 -0
- package/locales/en/.agents/architecture_doc/SKILL.md +92 -0
- package/locales/en/.agents/board/SKILL.md +43 -0
- package/locales/en/.agents/cloud_infrastructure_security/SKILL.md +68 -0
- package/locales/en/.agents/code_review_checklist/SKILL.md +47 -0
- package/locales/en/.agents/current_state_analysis/SKILL.md +44 -0
- package/locales/en/.agents/data_model/SKILL.md +40 -0
- package/locales/en/.agents/dependency_supply_chain_review/SKILL.md +20 -0
- package/locales/en/.agents/deployment_ci_plan/SKILL.md +51 -0
- package/locales/en/.agents/design_intake/SKILL.md +71 -0
- package/locales/en/.agents/design_parity_review/SKILL.md +73 -0
- package/locales/en/.agents/design_systems/SKILL.md +15 -0
- package/locales/en/.agents/dev_reference_snippets/SKILL.md +397 -0
- package/locales/en/.agents/docker_kubernetes_architecture/SKILL.md +144 -0
- package/locales/en/.agents/es2025_beast_practices/SKILL.md +15 -0
- package/locales/en/.agents/gates/SKILL.md +35 -0
- package/locales/en/.agents/go_beast_practices/SKILL.md +23 -0
- package/locales/en/.agents/handoff/SKILL.md +52 -0
- package/locales/en/.agents/k8s_manifests_conventions/SKILL.md +175 -0
- package/locales/en/.agents/memory/SKILL.md +29 -0
- package/locales/en/.agents/mongodb_mongoose_best_practices/SKILL.md +233 -0
- package/locales/en/.agents/node_express_beast_practices/SKILL.md +30 -0
- package/locales/en/.agents/observability_logging/SKILL.md +16 -0
- package/locales/en/.agents/observability_plan/SKILL.md +38 -0
- package/locales/en/.agents/observability_review/SKILL.md +20 -0
- package/locales/en/.agents/performance_review_baseline/SKILL.md +17 -0
- package/locales/en/.agents/pm_backlog/SKILL.md +32 -0
- package/locales/en/.agents/pm_interview/SKILL.md +56 -0
- package/locales/en/.agents/pm_prd/SKILL.md +56 -0
- package/locales/en/.agents/qa_api_contract_tests/SKILL.md +16 -0
- package/locales/en/.agents/qa_e2e_playwright/SKILL.md +0 -0
- package/locales/en/.agents/qa_manual_run/SKILL.md +16 -0
- package/locales/en/.agents/qa_security_smoke_tests/SKILL.md +14 -0
- package/locales/en/.agents/qa_test_plan/SKILL.md +20 -0
- package/locales/en/.agents/qa_ui_a11y_smoke/SKILL.md +12 -0
- package/locales/en/.agents/react_15_3_wix_iframe/SKILL.md +20 -0
- package/locales/en/.agents/react_beast_practices/SKILL.md +29 -0
- package/locales/en/.agents/release_gate/SKILL.md +77 -0
- package/locales/en/.agents/release_gate_checklist_template/SKILL.md +68 -0
- package/locales/en/.agents/review_reference_snippets/SKILL.md +436 -0
- package/locales/en/.agents/security_baseline_dev/SKILL.md +16 -0
- package/locales/en/.agents/security_review/SKILL.md +55 -0
- package/locales/en/.agents/security_review_baseline/SKILL.md +25 -0
- package/locales/en/.agents/state_rtk_beast_practices/SKILL.md +15 -0
- package/locales/en/.agents/state_zustand_beast_practices/SKILL.md +11 -0
- package/locales/en/.agents/styling_css_stack/SKILL.md +12 -0
- package/locales/en/.agents/system_design_checklist/SKILL.md +48 -0
- package/locales/en/.agents/tanstack_beast_practices/SKILL.md +19 -0
- package/locales/en/.agents/tdd_workflow/SKILL.md +34 -0
- package/locales/en/.agents/testing_strategy_js/SKILL.md +30 -0
- package/locales/en/.agents/tests_quality_review/SKILL.md +18 -0
- package/locales/en/.agents/threat_model_baseline/SKILL.md +57 -0
- package/locales/en/.agents/tooling_bun_biome/SKILL.md +17 -0
- package/locales/en/.agents/typescript_beast_practices/SKILL.md +15 -0
- package/locales/en/.agents/ui_a11y_smoke_review/SKILL.md +15 -0
- package/locales/en/.agents/ui_inventory/SKILL.md +50 -0
- package/locales/en/.agents/ux_discovery/SKILL.md +48 -0
- package/locales/en/.agents/ux_spec/SKILL.md +56 -0
- package/locales/en/.agents/wix_self_hosted_embedded_script/SKILL.md +88 -0
- package/locales/en/AGENTS.md +120 -0
- package/locales/en/agents/architect.md +239 -0
- package/locales/en/agents/conductor.md +205 -0
- package/locales/en/agents/product_manager.md +119 -0
- package/locales/en/agents/reviewer.md +200 -0
- package/locales/en/agents/senior_full_stack.md +216 -0
- package/locales/en/agents/tester.md +186 -0
- package/locales/en/agents/ux_ui_designer.md +144 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -47,12 +47,15 @@ code-ai targets
|
|
|
47
47
|
|
|
48
48
|
# list available agents and skills from current repository
|
|
49
49
|
code-ai list
|
|
50
|
+
code-ai list --lang en
|
|
50
51
|
|
|
51
52
|
# health checks
|
|
52
53
|
code-ai doctor --target claude
|
|
54
|
+
code-ai doctor --target claude --lang en
|
|
53
55
|
|
|
54
56
|
# dry-run install (default)
|
|
55
57
|
code-ai install --target claude --agents conductor,reviewer --skills board,security_review
|
|
58
|
+
code-ai install --target claude --lang en --agents conductor,reviewer --skills board,security_review
|
|
56
59
|
|
|
57
60
|
# install into a newly created folder under current directory
|
|
58
61
|
code-ai install --target gpt-codex --create-dir my-new-project --agents all --skills all --apply
|
|
@@ -99,3 +102,4 @@ code-ai uninstall --target claude --apply
|
|
|
99
102
|
- Target aliases are accepted: `copilot`, `codex`, `claude`, `qwen`, `google`, `antigravity`.
|
|
100
103
|
- If your AI tool requires a custom location, pass `--destination <path>`.
|
|
101
104
|
- Source templates are resolved automatically: current directory first, bundled package templates second.
|
|
105
|
+
- Template language is selectable via `--lang ru|en` (default: `ru`).
|
package/dist/banner.d.ts
ADDED
package/dist/banner.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
const CODE_AI_ASCII = [
|
|
3
|
+
" ██████╗ ██████╗ ██████╗ ███████╗ █████╗ ██╗",
|
|
4
|
+
" ██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██╔══██╗██║",
|
|
5
|
+
" ██║ ██║ ██║██║ ██║█████╗ ███████║██║",
|
|
6
|
+
" ██║ ██║ ██║██║ ██║██╔══╝ ██╔══██║██║",
|
|
7
|
+
" ╚██████╗╚██████╔╝██████╔╝███████╗ ██║ ██║██║",
|
|
8
|
+
" ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝╚═╝",
|
|
9
|
+
];
|
|
10
|
+
/**
|
|
11
|
+
* Prints CODE-AI startup banner with green gradient.
|
|
12
|
+
*/
|
|
13
|
+
export function printBanner() {
|
|
14
|
+
const width = Math.max(...CODE_AI_ASCII.map((line) => line.length));
|
|
15
|
+
const start = { r: 64, g: 224, b: 128 };
|
|
16
|
+
const end = { r: 16, g: 120, b: 72 };
|
|
17
|
+
for (let row = 0; row < CODE_AI_ASCII.length; row += 1) {
|
|
18
|
+
const line = CODE_AI_ASCII[row];
|
|
19
|
+
let out = "";
|
|
20
|
+
for (let i = 0; i < line.length; i += 1) {
|
|
21
|
+
const ch = line[i];
|
|
22
|
+
if (ch === " ") {
|
|
23
|
+
out += ch;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const t = width <= 1 ? 0 : i / (width - 1);
|
|
27
|
+
const r = Math.round(start.r + (end.r - start.r) * t);
|
|
28
|
+
const g = Math.round(start.g + (end.g - start.g) * t);
|
|
29
|
+
const b = Math.round(start.b + (end.b - start.b) * t);
|
|
30
|
+
out += chalk.rgb(r, g, b)(ch);
|
|
31
|
+
}
|
|
32
|
+
process.stdout.write(`${out}\n`);
|
|
33
|
+
}
|
|
34
|
+
process.stdout.write(`${chalk.green("Code-AI installer wizard")}\n\n`);
|
|
35
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -9,8 +9,55 @@ import { runInstall, runUninstall } from "./installer.js";
|
|
|
9
9
|
import { error, info, success, warn } from "./logger.js";
|
|
10
10
|
import { getPlatformAdapters } from "./platforms/adapters.js";
|
|
11
11
|
import { resolveSourceRoot } from "./sourceResolver.js";
|
|
12
|
+
import { printBanner } from "./banner.js";
|
|
12
13
|
const program = new Command();
|
|
13
14
|
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
15
|
+
const WIZARD_TEXT = {
|
|
16
|
+
en: {
|
|
17
|
+
cancelled: "Installation cancelled.",
|
|
18
|
+
selectTemplateLanguage: "Select template language:",
|
|
19
|
+
languageRu: "Russian (ru)",
|
|
20
|
+
languageEn: "English (en)",
|
|
21
|
+
selectAiTarget: "Select AI target:",
|
|
22
|
+
installWhere: "Where should files be installed?",
|
|
23
|
+
currentFolder: "Current folder",
|
|
24
|
+
newFolder: "New folder",
|
|
25
|
+
newFolderName: "New folder name:",
|
|
26
|
+
newFolderNameRequired: "Please provide folder name",
|
|
27
|
+
selectAgents: "Select agents:",
|
|
28
|
+
selectSkills: "Select skills:",
|
|
29
|
+
selectHint: "space: toggle, enter: submit",
|
|
30
|
+
overwritePrompt: "Overwrite existing files?",
|
|
31
|
+
applyPrompt: "Run installation now?",
|
|
32
|
+
strictHintsPrompt: "Enforce strict target-hint adaptation?",
|
|
33
|
+
runDoctor: "Running doctor before install...",
|
|
34
|
+
doctorFailed: "Doctor checks failed. Fix issues and run again.",
|
|
35
|
+
dryRunMode: "Preview mode selected (no file writes).",
|
|
36
|
+
previewCompleted: "Preview completed.",
|
|
37
|
+
},
|
|
38
|
+
ru: {
|
|
39
|
+
cancelled: "Установка отменена.",
|
|
40
|
+
selectTemplateLanguage: "Выбери язык шаблонов:",
|
|
41
|
+
languageRu: "Русский (ru)",
|
|
42
|
+
languageEn: "English (en)",
|
|
43
|
+
selectAiTarget: "Выбери AI для установки:",
|
|
44
|
+
installWhere: "Куда устанавливать?",
|
|
45
|
+
currentFolder: "Текущая папка",
|
|
46
|
+
newFolder: "Новая папка",
|
|
47
|
+
newFolderName: "Название новой папки:",
|
|
48
|
+
newFolderNameRequired: "Укажи название папки",
|
|
49
|
+
selectAgents: "Выбери агентов:",
|
|
50
|
+
selectSkills: "Выбери skills:",
|
|
51
|
+
selectHint: "space: выбрать, enter: подтвердить",
|
|
52
|
+
overwritePrompt: "Перезаписывать существующие файлы?",
|
|
53
|
+
applyPrompt: "Сразу выполнить установку?",
|
|
54
|
+
strictHintsPrompt: "Требовать явные target-hints в agent/skill файлах?",
|
|
55
|
+
runDoctor: "Запускаю doctor перед установкой...",
|
|
56
|
+
doctorFailed: "Doctor не пройден. Исправь ошибки и запусти снова.",
|
|
57
|
+
dryRunMode: "Выбран preview-режим без записи файлов.",
|
|
58
|
+
previewCompleted: "Preview completed.",
|
|
59
|
+
},
|
|
60
|
+
};
|
|
14
61
|
program
|
|
15
62
|
.name("code-ai")
|
|
16
63
|
.description("Install code-ai agents and skills for AI coding assistants")
|
|
@@ -29,12 +76,15 @@ program
|
|
|
29
76
|
.command("list")
|
|
30
77
|
.description("List available bundled agents and skills")
|
|
31
78
|
.option("--project-dir <path>", "Optional custom source root path")
|
|
79
|
+
.option("--lang <lang>", "Template language: ru | en", "ru")
|
|
32
80
|
.action(async (options) => {
|
|
33
81
|
try {
|
|
82
|
+
const language = normalizeLanguage(options.lang);
|
|
34
83
|
const projectDir = await resolveSourceRoot({
|
|
35
84
|
projectDirOption: options.projectDir,
|
|
36
85
|
cwd: process.cwd(),
|
|
37
86
|
packageRoot,
|
|
87
|
+
language,
|
|
38
88
|
});
|
|
39
89
|
const catalog = await loadSourceCatalog(projectDir);
|
|
40
90
|
const agents = listAgentNames(catalog);
|
|
@@ -54,13 +104,16 @@ program
|
|
|
54
104
|
.requiredOption("--target <id>", "Target AI id")
|
|
55
105
|
.option("--project-dir <path>", "Optional custom source root path")
|
|
56
106
|
.option("--destination <path>", "Destination root (default: current directory)")
|
|
107
|
+
.option("--lang <lang>", "Template language: ru | en", "ru")
|
|
57
108
|
.action(async (options) => {
|
|
58
109
|
try {
|
|
59
110
|
const target = normalizeTarget(options.target);
|
|
111
|
+
const language = normalizeLanguage(options.lang);
|
|
60
112
|
const projectDir = await resolveSourceRoot({
|
|
61
113
|
projectDirOption: options.projectDir,
|
|
62
114
|
cwd: process.cwd(),
|
|
63
115
|
packageRoot,
|
|
116
|
+
language,
|
|
64
117
|
});
|
|
65
118
|
const destinationDir = path.resolve(options.destination ?? process.cwd());
|
|
66
119
|
const report = await runDoctor(projectDir, destinationDir, target);
|
|
@@ -93,6 +146,7 @@ program
|
|
|
93
146
|
.option("--project-dir <path>", "Optional custom source root path")
|
|
94
147
|
.option("--destination <path>", "Destination root (default: current directory)")
|
|
95
148
|
.option("--create-dir <name>", "Create child folder in current directory and install there")
|
|
149
|
+
.option("--lang <lang>", "Template language: ru | en", "ru")
|
|
96
150
|
.option("--agents <list>", "Comma list of agents or 'all'", "all")
|
|
97
151
|
.option("--skills <list>", "Comma list of skills or 'all'", "all")
|
|
98
152
|
.option("--overwrite", "Overwrite existing files", false)
|
|
@@ -101,10 +155,12 @@ program
|
|
|
101
155
|
.action(async (options) => {
|
|
102
156
|
try {
|
|
103
157
|
const target = normalizeTarget(options.target);
|
|
158
|
+
const language = normalizeLanguage(options.lang);
|
|
104
159
|
const projectDir = await resolveSourceRoot({
|
|
105
160
|
projectDirOption: options.projectDir,
|
|
106
161
|
cwd: process.cwd(),
|
|
107
162
|
packageRoot,
|
|
163
|
+
language,
|
|
108
164
|
});
|
|
109
165
|
const baseDestination = path.resolve(options.destination ?? process.cwd());
|
|
110
166
|
const destinationDir = options.createDir ? path.join(baseDestination, options.createDir) : baseDestination;
|
|
@@ -185,16 +241,35 @@ program
|
|
|
185
241
|
* Runs interactive installer workflow when no subcommand is provided.
|
|
186
242
|
*/
|
|
187
243
|
async function runInteractiveWizard() {
|
|
244
|
+
printBanner();
|
|
245
|
+
const bootstrapText = WIZARD_TEXT.en;
|
|
246
|
+
const languageAnswer = await prompts({
|
|
247
|
+
type: "select",
|
|
248
|
+
name: "language",
|
|
249
|
+
message: bootstrapText.selectTemplateLanguage,
|
|
250
|
+
choices: [
|
|
251
|
+
{ title: bootstrapText.languageEn, value: "en" },
|
|
252
|
+
{ title: bootstrapText.languageRu, value: "ru" },
|
|
253
|
+
],
|
|
254
|
+
initial: 0,
|
|
255
|
+
});
|
|
256
|
+
if (!languageAnswer.language) {
|
|
257
|
+
warn(bootstrapText.cancelled);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const language = normalizeLanguage(languageAnswer.language);
|
|
261
|
+
const text = WIZARD_TEXT[language];
|
|
188
262
|
const sourceRoot = await resolveSourceRoot({
|
|
189
263
|
cwd: process.cwd(),
|
|
190
264
|
packageRoot,
|
|
265
|
+
language,
|
|
191
266
|
});
|
|
192
267
|
const catalog = await loadSourceCatalog(sourceRoot);
|
|
193
268
|
const adapters = getPlatformAdapters();
|
|
194
269
|
const targetAnswer = await prompts({
|
|
195
270
|
type: "select",
|
|
196
271
|
name: "target",
|
|
197
|
-
message:
|
|
272
|
+
message: text.selectAiTarget,
|
|
198
273
|
choices: adapters.map((adapter) => ({
|
|
199
274
|
title: `${adapter.label} (${adapter.id})`,
|
|
200
275
|
value: adapter.id,
|
|
@@ -202,20 +277,20 @@ async function runInteractiveWizard() {
|
|
|
202
277
|
})),
|
|
203
278
|
});
|
|
204
279
|
if (!targetAnswer.target) {
|
|
205
|
-
warn(
|
|
280
|
+
warn(text.cancelled);
|
|
206
281
|
return;
|
|
207
282
|
}
|
|
208
283
|
const destinationModeAnswer = await prompts({
|
|
209
284
|
type: "select",
|
|
210
285
|
name: "mode",
|
|
211
|
-
message:
|
|
286
|
+
message: text.installWhere,
|
|
212
287
|
choices: [
|
|
213
|
-
{ title:
|
|
214
|
-
{ title:
|
|
288
|
+
{ title: text.currentFolder, value: "current" },
|
|
289
|
+
{ title: text.newFolder, value: "new" },
|
|
215
290
|
],
|
|
216
291
|
});
|
|
217
292
|
if (!destinationModeAnswer.mode) {
|
|
218
|
-
warn(
|
|
293
|
+
warn(text.cancelled);
|
|
219
294
|
return;
|
|
220
295
|
}
|
|
221
296
|
let destinationDir = process.cwd();
|
|
@@ -223,11 +298,11 @@ async function runInteractiveWizard() {
|
|
|
223
298
|
const newFolderAnswer = await prompts({
|
|
224
299
|
type: "text",
|
|
225
300
|
name: "folderName",
|
|
226
|
-
message:
|
|
227
|
-
validate: (value) => (value.trim().length === 0 ?
|
|
301
|
+
message: text.newFolderName,
|
|
302
|
+
validate: (value) => (value.trim().length === 0 ? text.newFolderNameRequired : true),
|
|
228
303
|
});
|
|
229
304
|
if (!newFolderAnswer.folderName) {
|
|
230
|
-
warn(
|
|
305
|
+
warn(text.cancelled);
|
|
231
306
|
return;
|
|
232
307
|
}
|
|
233
308
|
destinationDir = path.join(process.cwd(), String(newFolderAnswer.folderName).trim());
|
|
@@ -237,32 +312,32 @@ async function runInteractiveWizard() {
|
|
|
237
312
|
const agentsAnswer = await prompts({
|
|
238
313
|
type: "multiselect",
|
|
239
314
|
name: "selectedAgents",
|
|
240
|
-
message:
|
|
315
|
+
message: text.selectAgents,
|
|
241
316
|
choices: agents.map((agentName) => ({ title: agentName, value: agentName, selected: true })),
|
|
242
317
|
min: 1,
|
|
243
|
-
hint:
|
|
318
|
+
hint: text.selectHint,
|
|
244
319
|
});
|
|
245
320
|
if (!agentsAnswer.selectedAgents || agentsAnswer.selectedAgents.length === 0) {
|
|
246
|
-
warn(
|
|
321
|
+
warn(text.cancelled);
|
|
247
322
|
return;
|
|
248
323
|
}
|
|
249
324
|
const skillsAnswer = await prompts({
|
|
250
325
|
type: "multiselect",
|
|
251
326
|
name: "selectedSkills",
|
|
252
|
-
message:
|
|
327
|
+
message: text.selectSkills,
|
|
253
328
|
choices: skills.map((skillName) => ({ title: skillName, value: skillName, selected: true })),
|
|
254
329
|
min: 1,
|
|
255
|
-
hint:
|
|
330
|
+
hint: text.selectHint,
|
|
256
331
|
});
|
|
257
332
|
if (!skillsAnswer.selectedSkills || skillsAnswer.selectedSkills.length === 0) {
|
|
258
|
-
warn(
|
|
333
|
+
warn(text.cancelled);
|
|
259
334
|
return;
|
|
260
335
|
}
|
|
261
336
|
const optionsAnswer = await prompts([
|
|
262
337
|
{
|
|
263
338
|
type: "toggle",
|
|
264
339
|
name: "overwrite",
|
|
265
|
-
message:
|
|
340
|
+
message: text.overwritePrompt,
|
|
266
341
|
initial: false,
|
|
267
342
|
active: "yes",
|
|
268
343
|
inactive: "no",
|
|
@@ -270,7 +345,7 @@ async function runInteractiveWizard() {
|
|
|
270
345
|
{
|
|
271
346
|
type: "toggle",
|
|
272
347
|
name: "apply",
|
|
273
|
-
message:
|
|
348
|
+
message: text.applyPrompt,
|
|
274
349
|
initial: true,
|
|
275
350
|
active: "yes",
|
|
276
351
|
inactive: "no",
|
|
@@ -278,14 +353,14 @@ async function runInteractiveWizard() {
|
|
|
278
353
|
{
|
|
279
354
|
type: "toggle",
|
|
280
355
|
name: "strictHints",
|
|
281
|
-
message:
|
|
356
|
+
message: text.strictHintsPrompt,
|
|
282
357
|
initial: false,
|
|
283
358
|
active: "yes",
|
|
284
359
|
inactive: "no",
|
|
285
360
|
},
|
|
286
361
|
]);
|
|
287
362
|
const target = targetAnswer.target;
|
|
288
|
-
info(
|
|
363
|
+
info(text.runDoctor);
|
|
289
364
|
const doctor = await runDoctor(sourceRoot, destinationDir, target);
|
|
290
365
|
for (const line of doctor.info) {
|
|
291
366
|
info(line);
|
|
@@ -297,12 +372,12 @@ async function runInteractiveWizard() {
|
|
|
297
372
|
error(line);
|
|
298
373
|
}
|
|
299
374
|
if (doctor.errors.length > 0) {
|
|
300
|
-
throw new Error(
|
|
375
|
+
throw new Error(text.doctorFailed);
|
|
301
376
|
}
|
|
302
377
|
const dryRun = !Boolean(optionsAnswer.apply);
|
|
303
378
|
const overwriteMode = optionsAnswer.overwrite ? "overwrite" : "skip";
|
|
304
379
|
if (dryRun) {
|
|
305
|
-
warn(
|
|
380
|
+
warn(text.dryRunMode);
|
|
306
381
|
}
|
|
307
382
|
const { state, result } = await runInstall({
|
|
308
383
|
target,
|
|
@@ -320,7 +395,7 @@ async function runInteractiveWizard() {
|
|
|
320
395
|
info(`Files planned: ${result.plannedFiles.length}`);
|
|
321
396
|
if (dryRun) {
|
|
322
397
|
info(`Files would write: ${result.writtenFiles.length}`);
|
|
323
|
-
success(
|
|
398
|
+
success(text.previewCompleted);
|
|
324
399
|
}
|
|
325
400
|
else {
|
|
326
401
|
info(`Files written: ${result.writtenFiles.length}`);
|
|
@@ -358,6 +433,18 @@ function normalizeTarget(rawTarget) {
|
|
|
358
433
|
}
|
|
359
434
|
return normalized;
|
|
360
435
|
}
|
|
436
|
+
/**
|
|
437
|
+
* Normalizes template language code.
|
|
438
|
+
* @param rawLanguage Raw language value.
|
|
439
|
+
* @returns Normalized template language.
|
|
440
|
+
*/
|
|
441
|
+
function normalizeLanguage(rawLanguage) {
|
|
442
|
+
const value = rawLanguage.trim().toLowerCase();
|
|
443
|
+
if (value === "ru" || value === "en") {
|
|
444
|
+
return value;
|
|
445
|
+
}
|
|
446
|
+
throw new Error(`Unsupported language '${rawLanguage}'. Use 'ru' or 'en'.`);
|
|
447
|
+
}
|
|
361
448
|
if (process.argv.length <= 2) {
|
|
362
449
|
runInteractiveWizard().catch((err) => {
|
|
363
450
|
error(err.message);
|
package/dist/sourceResolver.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TemplateLanguage } from "./types.js";
|
|
1
2
|
/**
|
|
2
3
|
* Resolves source root with agent templates.
|
|
3
4
|
* @param args Resolution arguments.
|
|
@@ -7,4 +8,5 @@ export declare function resolveSourceRoot(args: {
|
|
|
7
8
|
projectDirOption?: string;
|
|
8
9
|
cwd: string;
|
|
9
10
|
packageRoot: string;
|
|
11
|
+
language: TemplateLanguage;
|
|
10
12
|
}): Promise<string>;
|
package/dist/sourceResolver.js
CHANGED
|
@@ -13,13 +13,23 @@ export async function resolveSourceRoot(args) {
|
|
|
13
13
|
}
|
|
14
14
|
throw new Error(`Invalid --project-dir: ${explicitPath}. Required: AGENTS.md, agents/, and .agents/.`);
|
|
15
15
|
}
|
|
16
|
+
const bundledPath = getBundledPath(args.packageRoot, args.language);
|
|
16
17
|
const cwdPath = path.resolve(args.cwd);
|
|
17
|
-
if (
|
|
18
|
-
|
|
18
|
+
if (args.language === "en") {
|
|
19
|
+
if (await isValidSourceRoot(bundledPath)) {
|
|
20
|
+
return bundledPath;
|
|
21
|
+
}
|
|
22
|
+
if (await isValidSourceRoot(cwdPath)) {
|
|
23
|
+
return cwdPath;
|
|
24
|
+
}
|
|
19
25
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
else {
|
|
27
|
+
if (await isValidSourceRoot(cwdPath)) {
|
|
28
|
+
return cwdPath;
|
|
29
|
+
}
|
|
30
|
+
if (await isValidSourceRoot(bundledPath)) {
|
|
31
|
+
return bundledPath;
|
|
32
|
+
}
|
|
23
33
|
}
|
|
24
34
|
throw new Error(`Could not find source templates in current directory or bundled package. Checked: ${cwdPath} and ${bundledPath}`);
|
|
25
35
|
}
|
|
@@ -34,3 +44,15 @@ async function isValidSourceRoot(rootDir) {
|
|
|
34
44
|
const dotAgentsDir = path.join(rootDir, ".agents");
|
|
35
45
|
return (await fs.pathExists(orchestratorPath)) && (await fs.pathExists(agentsDir)) && (await fs.pathExists(dotAgentsDir));
|
|
36
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Returns bundled templates root for selected language.
|
|
49
|
+
* @param packageRoot Installed package root.
|
|
50
|
+
* @param language Template language.
|
|
51
|
+
* @returns Absolute bundled source path.
|
|
52
|
+
*/
|
|
53
|
+
function getBundledPath(packageRoot, language) {
|
|
54
|
+
if (language === "en") {
|
|
55
|
+
return path.resolve(packageRoot, "locales", "en");
|
|
56
|
+
}
|
|
57
|
+
return path.resolve(packageRoot);
|
|
58
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: a11y_baseline
|
|
3
|
+
description: Minimum baseline accessibility for web UI: keyboard navigation, focus management, form labels, ARIA for interactive components, error messages.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
#Skill: A11y Baseline (minimum)
|
|
7
|
+
|
|
8
|
+
## Goal
|
|
9
|
+
Set minimum accessibility requirements that can be tested and implemented in the MVP.
|
|
10
|
+
|
|
11
|
+
## Exit
|
|
12
|
+
List of a11y requirements for the project + notes on key components.
|
|
13
|
+
|
|
14
|
+
## Minimum Requirements (MVP)
|
|
15
|
+
1) **Keyboard navigation**
|
|
16
|
+
- All interactive elements are accessible from the keyboard
|
|
17
|
+
- Tab order is logical
|
|
18
|
+
- No trick traps
|
|
19
|
+
|
|
20
|
+
2) **Focus states**
|
|
21
|
+
- Visible focus for all interactive elements
|
|
22
|
+
- In modals: focus moves inside and returns back when closed
|
|
23
|
+
|
|
24
|
+
3) **Forms**
|
|
25
|
+
- Each field has a label (visible or aria-label)
|
|
26
|
+
- Errors are assigned to a field (the error description is read by assistive technologies)
|
|
27
|
+
- Required fields are marked and clear
|
|
28
|
+
|
|
29
|
+
4) **ARIA (where needed)**
|
|
30
|
+
- Dialog: role="dialog" + aria-modal
|
|
31
|
+
- Tabs, dropdowns, comboboxes - correct roles/attributes (if we use custom ones)
|
|
32
|
+
|
|
33
|
+
5) **Error messaging**
|
|
34
|
+
- Errors are clear, without “unknown error”
|
|
35
|
+
- There are actions: retry/close/fix
|
|
36
|
+
|
|
37
|
+
## Receipt for tester
|
|
38
|
+
- You can go through key flows without a mouse
|
|
39
|
+
- In modal, focus does not leak
|
|
40
|
+
- Forms announce label/errors
|
|
41
|
+
- Custom components have ARIA and work with assistive technologies
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name:adr_log
|
|
3
|
+
description: Record key architectural decisions (ADR) with trade-offs: Pros/Cons/Alternatives/Decision, status and date.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
#Skill: ADR Log
|
|
7
|
+
|
|
8
|
+
## Goal
|
|
9
|
+
Don’t lose track of “why we did this” and simplify review/support.
|
|
10
|
+
|
|
11
|
+
## When to use
|
|
12
|
+
- For every non-trivial choice: database, auth, cache, module structure, API format, error strategy, queues, search, deployment, integrations, etc.
|
|
13
|
+
|
|
14
|
+
## ADR format (required)
|
|
15
|
+
# ADR-XXX: <Name>
|
|
16
|
+
|
|
17
|
+
## Context
|
|
18
|
+
<why is this necessary, what are the limitations, what hurts>
|
|
19
|
+
|
|
20
|
+
##Decision
|
|
21
|
+
<what you chose and how exactly>
|
|
22
|
+
|
|
23
|
+
## Consequences
|
|
24
|
+
### Positive
|
|
25
|
+
- ...
|
|
26
|
+
###Negative
|
|
27
|
+
- ...
|
|
28
|
+
|
|
29
|
+
## Alternatives Considered
|
|
30
|
+
- **A**: ...
|
|
31
|
+
- **B**: ...
|
|
32
|
+
|
|
33
|
+
##Status
|
|
34
|
+
Proposed / Accepted / Deprecated
|
|
35
|
+
|
|
36
|
+
##Date
|
|
37
|
+
YYYY-MM-DD
|
|
38
|
+
|
|
39
|
+
## Requirements (strict)
|
|
40
|
+
- For each ADR there must be explicit Pros/Cons/Alternatives and rationale of choice.
|
|
41
|
+
- If the decision affects security/data/cost, be sure to describe the consequences.
|
|
42
|
+
- ADR should be short and specific: without water, but with key arguments.
|
|
43
|
+
|
|
44
|
+
## Example (short)
|
|
45
|
+
# ADR-001: Selecting the main database
|
|
46
|
+
|
|
47
|
+
##Context
|
|
48
|
+
You need to store users/sessions/orders. Transactions and complex queries are needed. Expected growth to 100K users.
|
|
49
|
+
|
|
50
|
+
##Decision
|
|
51
|
+
We use PostgreSQL as the main database.
|
|
52
|
+
|
|
53
|
+
## Consequences
|
|
54
|
+
### Positive
|
|
55
|
+
- ACID transactions
|
|
56
|
+
- Rich queries and indexing
|
|
57
|
+
###Negative
|
|
58
|
+
- Possible need for scaling during growth
|
|
59
|
+
- Operational costs for administration
|
|
60
|
+
|
|
61
|
+
## Alternatives Considered
|
|
62
|
+
- **MongoDB**: weaker in transactional/complex join scenarios
|
|
63
|
+
- **DynamoDB**: vendor lock-in, more difficult to test locally
|
|
64
|
+
|
|
65
|
+
##Status
|
|
66
|
+
Accepted
|
|
67
|
+
|
|
68
|
+
##Date
|
|
69
|
+
2025-01-15
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api_contract_compliance_review
|
|
3
|
+
description: Checking the compliance of the API implementation with contracts: schemes, error codes, validation, authorization, idempotency, pagination.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Skill: API Contract Compliance Review
|
|
7
|
+
|
|
8
|
+
## Check
|
|
9
|
+
- Endpoints correspond to API Contracts (method/path/request/response)
|
|
10
|
+
- Errors: status + error_code + safe message
|
|
11
|
+
- Border Validation (422 or accepted policy)
|
|
12
|
+
- 401 vs 403 correct
|
|
13
|
+
- Pagination/filters/sorting are implemented if UX is required
|
|
14
|
+
- Idempotency for risky operations (if it was in the contract/ADR)
|
|
15
|
+
|
|
16
|
+
## Exit
|
|
17
|
+
- Inconsistencies for each endpoint
|
|
18
|
+
- Recommendations (pointwise)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api_contracts
|
|
3
|
+
description: API contracts for UX flows: endpoints, schemas, errors, validation, authorization, perf/scalability considerations, idempotency and integration patterns.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Skill: API Contracts
|
|
7
|
+
|
|
8
|
+
## Goal
|
|
9
|
+
Make the API predictable, safe and efficient for the client and tests.
|
|
10
|
+
|
|
11
|
+
## Inputs
|
|
12
|
+
- UX Spec (screens/actions/states)
|
|
13
|
+
- PRD (acceptance criteria)
|
|
14
|
+
- Roles/permissions
|
|
15
|
+
|
|
16
|
+
## Exit
|
|
17
|
+
### General rules
|
|
18
|
+
- Unified error format (error_code, message, details)
|
|
19
|
+
- 401 vs 403 distinguish
|
|
20
|
+
- Validation at boundaries
|
|
21
|
+
- Pagination/filters/sorting - if the UI requires
|
|
22
|
+
- Idempotency for create/risk operations (where needed)
|
|
23
|
+
- Versioning (if the public API is expected to grow)
|
|
24
|
+
|
|
25
|
+
### For each endpoint
|
|
26
|
+
- Method + Path
|
|
27
|
+
- AuthN/AuthZ: required? roles?
|
|
28
|
+
- Request schema (types + restrictions)
|
|
29
|
+
- Response schema
|
|
30
|
+
- Errors:
|
|
31
|
+
- status
|
|
32
|
+
- error_code
|
|
33
|
+
- safe message
|
|
34
|
+
- Perf/scalability notes:
|
|
35
|
+
- limits, pagination, batch, round-trips minimization
|
|
36
|
+
|
|
37
|
+
### Integrations
|
|
38
|
+
- Webhooks/external APIs: retry/backoff, signature/verification, idempotency
|
|
39
|
+
- Async if justified (event-driven)
|
|
40
|
+
|
|
41
|
+
## Trade-offs
|
|
42
|
+
If there are controversial areas (for example, CQRS/async), record them as ADR.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: architecture_compliance_review
|
|
3
|
+
description: Checking code compliance with architecture/ADR: module boundaries, layers, dependencies, conventions, red flags.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
#Skill: Architecture Compliance Review
|
|
7
|
+
|
|
8
|
+
## Check
|
|
9
|
+
- Compliance with modular boundaries (controller/service/repo or similar)
|
|
10
|
+
- Direction of dependencies (UI does not pull data directly, etc.)
|
|
11
|
+
- Lack of red flags: Big Ball of Mud, God Object, Tight Coupling, Magic
|
|
12
|
+
- New “solutions” are issued ADR (if they affect the database/cache/auth/contracts/integrations)
|
|
13
|
+
|
|
14
|
+
## Exit
|
|
15
|
+
- Findings (P0/P1/P2)
|
|
16
|
+
- Recommendations for refactoring (pointwise)
|
|
17
|
+
- Is ADR required? (yes/no what to describe)
|