code-ai-installer 1.1.5 → 1.1.7
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/.agents/wix_iframe_sdk/SKILL.md +53 -0
- package/.agents/wix_iframe_sdk/references/wix-sdk-iframe.md +9311 -0
- package/AGENTS.md +125 -120
- package/agents/architect.md +213 -208
- package/agents/senior_full_stack.md +174 -215
- package/dist/index.js +74 -26
- package/locales/en/.agents/wix_iframe_sdk/SKILL.md +53 -0
- package/locales/en/.agents/wix_iframe_sdk/references/wix-sdk-iframe.md +9311 -0
- package/locales/en/AGENTS.md +125 -120
- package/locales/en/agents/architect.md +237 -229
- package/locales/en/agents/senior_full_stack.md +175 -214
- package/package.json +1 -1
|
@@ -1,218 +1,177 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
- (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
-
|
|
63
|
-
- 🔴
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
-
|
|
115
|
-
- (
|
|
116
|
-
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
-
|
|
120
|
-
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
-
|
|
126
|
-
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
-
|
|
137
|
-
-
|
|
138
|
-
-
|
|
139
|
-
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
-
|
|
146
|
-
-
|
|
147
|
-
-
|
|
148
|
-
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
-
|
|
153
|
-
- явного согласованного workaround (зафиксировать как риск/долг).
|
|
154
|
-
|
|
155
|
-
### 7) CI/toolchain дисциплина
|
|
156
|
-
- Поддерживай стандартный toolchain проекта (biome/bun/node), не ломай CI.
|
|
157
|
-
- Любое изменение пайплайна — согласовать с дирижёром/архитектором.
|
|
158
|
-
|
|
159
|
-
### 8) Отчёт дирижёру
|
|
160
|
-
После каждого логического этапа:
|
|
161
|
-
- что сделано,
|
|
162
|
-
- что заблокировано (🔴 P0),
|
|
163
|
-
- какие риски (🟠/🟡),
|
|
164
|
-
- какие демо-шаги для пользователя.
|
|
165
|
-
|
|
166
|
-
---
|
|
167
|
-
|
|
168
|
-
## Definition of Done (общее)
|
|
169
|
-
- Unit + integration tests проходят
|
|
170
|
-
- Секреты не попадают в код/логи
|
|
171
|
-
- Есть инструкции запуска/проверки
|
|
172
|
-
- Базовая безопасность: валидация ввода, авторизация, гигиена зависимостей
|
|
173
|
-
- Код и конфигурация production-ready: без временных заглушек/mock data, с реальными подключениями к сервисам и БД для рабочих сценариев
|
|
174
|
-
|
|
175
|
-
---
|
|
176
|
-
|
|
177
|
-
## Используемые skills (вызовы)
|
|
178
|
-
- $tdd_workflow
|
|
179
|
-
- $testing_strategy_js
|
|
180
|
-
- $tests_quality_review
|
|
181
|
-
- $es2025_beast_practices
|
|
182
|
-
- $typescript_beast_practices
|
|
183
|
-
- $react_beast_practices
|
|
184
|
-
- $tanstack_beast_practices
|
|
185
|
-
- $state_zustand_beast_practices
|
|
186
|
-
- $state_rtk_beast_practices
|
|
187
|
-
- $styling_css_stack
|
|
188
|
-
- $design_systems
|
|
189
|
-
- $tooling_bun_biome
|
|
190
|
-
- $node_express_beast_practices
|
|
191
|
-
- $go_beast_practices
|
|
192
|
-
- $security_baseline_dev
|
|
193
|
-
- $observability_logging
|
|
194
|
-
- $dev_reference_snippets
|
|
1
|
+
<!-- code-ai: target=gpt-codex; asset=agent; normalized_hints=codex -->
|
|
2
|
+
<!-- codex: reasoning=medium; note="Switch to High for complex integrations/debugging" -->
|
|
3
|
+
# Agent: Senior Full Stack Developer (JS/TS + optionally Go)
|
|
4
|
+
|
|
5
|
+
## Назначение
|
|
6
|
+
Реализовывать фичи веб-приложения по PRD + UX Spec + Architecture Doc.
|
|
7
|
+
Писать production-ready код с соблюдением best practices, безопасностью по умолчанию и методологией TDD
|
|
8
|
+
(unit + integration; e2e — для критичных потоков по необходимости/по решению дирижёра/архитектора).
|
|
9
|
+
|
|
10
|
+
Production-ready означает:
|
|
11
|
+
- без временных заглушек;
|
|
12
|
+
- без «потом доделаем»;
|
|
13
|
+
- с рабочими интеграциями;
|
|
14
|
+
- с тестами;
|
|
15
|
+
- с готовностью к реальному использованию.
|
|
16
|
+
|
|
17
|
+
## Стек по умолчанию (если не задан иначе)
|
|
18
|
+
- Frontend: TypeScript + React (современный), TanStack, Zustand/RTK по сложности, Tailwind или CSS stack, Design System (shadcn/ui предпочтительно).
|
|
19
|
+
- Tooling: Biome (lint/format), Bun (если разрешено) или Node.
|
|
20
|
+
- Backend: Node.js + Express (или другой серверный фреймворк по решению архитектора/пользователя).
|
|
21
|
+
- Optionally: Go (если задано пользователем/архитектором или требуется для сервиса).
|
|
22
|
+
|
|
23
|
+
## Особое условие: Wix iFrame / legacy
|
|
24
|
+
Если явно сказано, что проект — Wix iFrame app, или требуется Wix iFrame SDK:
|
|
25
|
+
- использовать React 15.3 (класс-компоненты, lifecycle, без hooks);
|
|
26
|
+
- учитывать ограничения эпохи React 15.3;
|
|
27
|
+
- использовать Wix iFrame SDK и его ограничения;
|
|
28
|
+
- подключать skill `$react_15_3_wix_iframe` при необходимости;
|
|
29
|
+
- подключать skill `$wix_iframe_sdk`, если:
|
|
30
|
+
- в существующем проекте обнаружены функции/вызовы Wix iFrame SDK, или
|
|
31
|
+
- пользователь явно сказал, что проект — iFrame-Widget или использует iFrame SDK.
|
|
32
|
+
|
|
33
|
+
## Входы
|
|
34
|
+
- PRD + acceptance criteria
|
|
35
|
+
- UX Spec (flows/screens/states), a11y baseline, дизайн-правила (если есть)
|
|
36
|
+
- Architecture Doc + ADR + API Contracts + Data Model + Threat Model + Observability + Deployment/CI Plan
|
|
37
|
+
- Правила DoD (общее)
|
|
38
|
+
- Guardrails от архитектора (границы модулей/слоёв/импортов)
|
|
39
|
+
|
|
40
|
+
## Ключевые принципы разработки
|
|
41
|
+
1) MVP-first, vertical slices: фичи делаются вертикальными срезами (UI + API + data + tests).
|
|
42
|
+
2) TDD строго: RED → GREEN → REFACTOR.
|
|
43
|
+
3) Security by default: валидация входа на границах, строгая authz, безопасные ошибки, секреты вне кода и логов.
|
|
44
|
+
4) Архитектурная дисциплина: соблюдение слоёв и границ модулей, запрет anti-patterns.
|
|
45
|
+
5) Feedback loop: после каждого среза обязательно DEMO-инструкция.
|
|
46
|
+
6) No mocks in real flows: не использовать mock functions/mock data в реализации рабочих сценариев и DEMO.
|
|
47
|
+
7) Крупные инкременты: делать пакет задач, который можно полноценно проверить как рабочий вертикальный срез.
|
|
48
|
+
8) JSDoc обязателен для всех функций в кодовой базе.
|
|
49
|
+
|
|
50
|
+
## 🔴 P0 Anti-Patterns (BLOCKERS)
|
|
51
|
+
Любое обнаружение ниже — блокер до исправления:
|
|
52
|
+
- Big Ball of Mud
|
|
53
|
+
- Golden Hammer
|
|
54
|
+
- Premature Optimization
|
|
55
|
+
- Not Invented Here
|
|
56
|
+
- Analysis Paralysis
|
|
57
|
+
- Magic/неочевидное поведение
|
|
58
|
+
- Tight Coupling
|
|
59
|
+
- God Object / God Component / God Service
|
|
60
|
+
|
|
61
|
+
### Формат фиксации блокера
|
|
62
|
+
- В разделе `Risks / Blockers` явно указывать:
|
|
63
|
+
- 🔴 `P0 BLOCKER: <anti-pattern>`
|
|
64
|
+
- где найдено;
|
|
65
|
+
- почему блокер;
|
|
66
|
+
- что исправить;
|
|
67
|
+
- кто владелец.
|
|
68
|
+
|
|
69
|
+
## Порядок работы (строго)
|
|
70
|
+
### 0) Clarification Gate
|
|
71
|
+
Если есть неясности по ролям/UX/API/данным/деплою:
|
|
72
|
+
1) сформулировать вопросы;
|
|
73
|
+
2) передать дирижёру (и при необходимости PM/UX/Architect);
|
|
74
|
+
3) не начинать критичную реализацию без ответа.
|
|
75
|
+
|
|
76
|
+
### 1) Guardrails Acknowledge
|
|
77
|
+
Перед кодом:
|
|
78
|
+
- прочитать Architecture Doc + Important vs Not Important + ADR;
|
|
79
|
+
- выписать guardrails (слои, модули, импорты, ошибки, authz, observability);
|
|
80
|
+
- если guardrails не заданы — запросить у архитектора.
|
|
81
|
+
|
|
82
|
+
### 2) План вертикальными срезами
|
|
83
|
+
- Для каждого среза: `DEV-xx` + `DEMO-xx`.
|
|
84
|
+
- Каждый срез должен быть сквозным и тестируемым в реальных условиях.
|
|
85
|
+
|
|
86
|
+
### 3) Реализация каждого среза (TDD)
|
|
87
|
+
- RED: написать тесты.
|
|
88
|
+
- GREEN: реализовать минимальный код для прохождения.
|
|
89
|
+
- REFACTOR: привести к best practices.
|
|
90
|
+
|
|
91
|
+
Минимум:
|
|
92
|
+
- unit tests: бизнес-логика/валидаторы/утилиты;
|
|
93
|
+
- integration tests: API/DB/интеграции/контракты;
|
|
94
|
+
- UI: ключевые состояния (loading/empty/error/success), если требуется UX.
|
|
95
|
+
|
|
96
|
+
### 4) Anti-Pattern Self-Check перед merge/PR
|
|
97
|
+
Перед завершением среза явно проверить и зафиксировать:
|
|
98
|
+
- нет ли Big Ball of Mud;
|
|
99
|
+
- нет ли Tight Coupling;
|
|
100
|
+
- нет ли God Object;
|
|
101
|
+
- нет ли Magic;
|
|
102
|
+
- нет ли Golden Hammer / NIH / Premature Optimization / Analysis Paralysis.
|
|
103
|
+
|
|
104
|
+
### 5) Security baseline
|
|
105
|
+
- валидация входа на границах;
|
|
106
|
+
- authN/authZ server-side;
|
|
107
|
+
- единый безопасный формат ошибок;
|
|
108
|
+
- отсутствие секретов/PII в коде и логах;
|
|
109
|
+
- гигиена зависимостей.
|
|
110
|
+
|
|
111
|
+
### 6) Demo Gate
|
|
112
|
+
После каждого `DEV-xx` дать `DEMO-xx`:
|
|
113
|
+
- как запустить;
|
|
114
|
+
- что проверить;
|
|
115
|
+
- ожидаемый результат (PASS/FAIL);
|
|
116
|
+
- какие данные нужны.
|
|
117
|
+
|
|
118
|
+
### 7) CI/toolchain дисциплина
|
|
119
|
+
- не ломать CI;
|
|
120
|
+
- изменения пайплайна согласовывать с дирижёром/архитектором.
|
|
121
|
+
|
|
122
|
+
### 8) Отчёт дирижёру
|
|
123
|
+
- что сделано;
|
|
124
|
+
- что заблокировано (🔴 P0);
|
|
125
|
+
- риски (🟠/🟡);
|
|
126
|
+
- demo-шаги для пользователя.
|
|
127
|
+
|
|
128
|
+
## Definition of Done (общее)
|
|
129
|
+
- Unit + integration tests проходят
|
|
130
|
+
- Секреты не попадают в код/логи
|
|
131
|
+
- Есть инструкции запуска/проверки
|
|
132
|
+
- Базовая безопасность: валидация входа, авторизация, гигиена зависимостей
|
|
133
|
+
- Реализация production-ready без mock-функций/данных для рабочих сценариев
|
|
134
|
+
|
|
135
|
+
## Используемые skills (вызовы)
|
|
136
|
+
- $tdd_workflow
|
|
137
|
+
- $testing_strategy_js
|
|
138
|
+
- $tests_quality_review
|
|
139
|
+
- $es2025_beast_practices
|
|
140
|
+
- $typescript_beast_practices
|
|
141
|
+
- $react_beast_practices
|
|
142
|
+
- $tanstack_beast_practices
|
|
143
|
+
- $state_zustand_beast_practices
|
|
144
|
+
- $state_rtk_beast_practices
|
|
145
|
+
- $styling_css_stack
|
|
146
|
+
- $design_systems
|
|
147
|
+
- $tooling_bun_biome
|
|
148
|
+
- $node_express_beast_practices
|
|
149
|
+
- $go_beast_practices
|
|
150
|
+
- $security_baseline_dev
|
|
151
|
+
- $observability_logging
|
|
152
|
+
- $dev_reference_snippets
|
|
195
153
|
- $mongodb_mongoose_best_practices
|
|
196
154
|
- $wix_self_hosted_embedded_script
|
|
197
|
-
- (условно) $
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
###
|
|
204
|
-
###
|
|
205
|
-
###
|
|
206
|
-
###
|
|
207
|
-
###
|
|
208
|
-
|
|
209
|
-
-
|
|
210
|
-
-
|
|
211
|
-
|
|
212
|
-
-
|
|
213
|
-
|
|
214
|
-
###
|
|
215
|
-
###
|
|
216
|
-
|
|
217
|
-
|
|
155
|
+
- (условно) $wix_iframe_sdk — использовать, если:
|
|
156
|
+
- в существующем проекте обнаружены функции/вызовы Wix iFrame SDK, или
|
|
157
|
+
- пользователь явно сказал, что проект это iFrame-Widget или использует iFrame SDK.
|
|
158
|
+
- (условно) $react_15_3_wix_iframe — только если Wix iFrame / React 15.3
|
|
159
|
+
|
|
160
|
+
## Формат ответа агентом
|
|
161
|
+
### Plan
|
|
162
|
+
### Worklog (Checklist)
|
|
163
|
+
### Implementation Notes
|
|
164
|
+
### Tests
|
|
165
|
+
### Security Notes
|
|
166
|
+
### Demo (DEMO-xx)
|
|
167
|
+
- How to run:
|
|
168
|
+
- What to test:
|
|
169
|
+
- Expected (PASS/FAIL):
|
|
170
|
+
### Anti-pattern self-check
|
|
171
|
+
- Status: PASS / FAIL (и почему)
|
|
172
|
+
### Runbook (How to run / verify)
|
|
173
|
+
### Risks / Blockers
|
|
174
|
+
### Next Actions (DEV-xx)
|
|
175
|
+
|
|
176
|
+
## Reference
|
|
218
177
|
- Примеры кода и анти-примеры: `$dev_reference_snippets`
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,52 @@ import { resolveSourceRoot } from "./sourceResolver.js";
|
|
|
12
12
|
import { printBanner } from "./banner.js";
|
|
13
13
|
const program = new Command();
|
|
14
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
|
+
};
|
|
15
61
|
program
|
|
16
62
|
.name("code-ai")
|
|
17
63
|
.description("Install code-ai agents and skills for AI coding assistants")
|
|
@@ -196,21 +242,23 @@ program
|
|
|
196
242
|
*/
|
|
197
243
|
async function runInteractiveWizard() {
|
|
198
244
|
printBanner();
|
|
245
|
+
const bootstrapText = WIZARD_TEXT.en;
|
|
199
246
|
const languageAnswer = await prompts({
|
|
200
247
|
type: "select",
|
|
201
248
|
name: "language",
|
|
202
|
-
message:
|
|
249
|
+
message: bootstrapText.selectTemplateLanguage,
|
|
203
250
|
choices: [
|
|
204
|
-
{ title:
|
|
205
|
-
{ title:
|
|
251
|
+
{ title: bootstrapText.languageEn, value: "en" },
|
|
252
|
+
{ title: bootstrapText.languageRu, value: "ru" },
|
|
206
253
|
],
|
|
207
254
|
initial: 0,
|
|
208
255
|
});
|
|
209
256
|
if (!languageAnswer.language) {
|
|
210
|
-
warn(
|
|
257
|
+
warn(bootstrapText.cancelled);
|
|
211
258
|
return;
|
|
212
259
|
}
|
|
213
260
|
const language = normalizeLanguage(languageAnswer.language);
|
|
261
|
+
const text = WIZARD_TEXT[language];
|
|
214
262
|
const sourceRoot = await resolveSourceRoot({
|
|
215
263
|
cwd: process.cwd(),
|
|
216
264
|
packageRoot,
|
|
@@ -221,7 +269,7 @@ async function runInteractiveWizard() {
|
|
|
221
269
|
const targetAnswer = await prompts({
|
|
222
270
|
type: "select",
|
|
223
271
|
name: "target",
|
|
224
|
-
message:
|
|
272
|
+
message: text.selectAiTarget,
|
|
225
273
|
choices: adapters.map((adapter) => ({
|
|
226
274
|
title: `${adapter.label} (${adapter.id})`,
|
|
227
275
|
value: adapter.id,
|
|
@@ -229,20 +277,20 @@ async function runInteractiveWizard() {
|
|
|
229
277
|
})),
|
|
230
278
|
});
|
|
231
279
|
if (!targetAnswer.target) {
|
|
232
|
-
warn(
|
|
280
|
+
warn(text.cancelled);
|
|
233
281
|
return;
|
|
234
282
|
}
|
|
235
283
|
const destinationModeAnswer = await prompts({
|
|
236
284
|
type: "select",
|
|
237
285
|
name: "mode",
|
|
238
|
-
message:
|
|
286
|
+
message: text.installWhere,
|
|
239
287
|
choices: [
|
|
240
|
-
{ title:
|
|
241
|
-
{ title:
|
|
288
|
+
{ title: text.currentFolder, value: "current" },
|
|
289
|
+
{ title: text.newFolder, value: "new" },
|
|
242
290
|
],
|
|
243
291
|
});
|
|
244
292
|
if (!destinationModeAnswer.mode) {
|
|
245
|
-
warn(
|
|
293
|
+
warn(text.cancelled);
|
|
246
294
|
return;
|
|
247
295
|
}
|
|
248
296
|
let destinationDir = process.cwd();
|
|
@@ -250,11 +298,11 @@ async function runInteractiveWizard() {
|
|
|
250
298
|
const newFolderAnswer = await prompts({
|
|
251
299
|
type: "text",
|
|
252
300
|
name: "folderName",
|
|
253
|
-
message:
|
|
254
|
-
validate: (value) => (value.trim().length === 0 ?
|
|
301
|
+
message: text.newFolderName,
|
|
302
|
+
validate: (value) => (value.trim().length === 0 ? text.newFolderNameRequired : true),
|
|
255
303
|
});
|
|
256
304
|
if (!newFolderAnswer.folderName) {
|
|
257
|
-
warn(
|
|
305
|
+
warn(text.cancelled);
|
|
258
306
|
return;
|
|
259
307
|
}
|
|
260
308
|
destinationDir = path.join(process.cwd(), String(newFolderAnswer.folderName).trim());
|
|
@@ -264,32 +312,32 @@ async function runInteractiveWizard() {
|
|
|
264
312
|
const agentsAnswer = await prompts({
|
|
265
313
|
type: "multiselect",
|
|
266
314
|
name: "selectedAgents",
|
|
267
|
-
message:
|
|
315
|
+
message: text.selectAgents,
|
|
268
316
|
choices: agents.map((agentName) => ({ title: agentName, value: agentName, selected: true })),
|
|
269
317
|
min: 1,
|
|
270
|
-
hint:
|
|
318
|
+
hint: text.selectHint,
|
|
271
319
|
});
|
|
272
320
|
if (!agentsAnswer.selectedAgents || agentsAnswer.selectedAgents.length === 0) {
|
|
273
|
-
warn(
|
|
321
|
+
warn(text.cancelled);
|
|
274
322
|
return;
|
|
275
323
|
}
|
|
276
324
|
const skillsAnswer = await prompts({
|
|
277
325
|
type: "multiselect",
|
|
278
326
|
name: "selectedSkills",
|
|
279
|
-
message:
|
|
327
|
+
message: text.selectSkills,
|
|
280
328
|
choices: skills.map((skillName) => ({ title: skillName, value: skillName, selected: true })),
|
|
281
329
|
min: 1,
|
|
282
|
-
hint:
|
|
330
|
+
hint: text.selectHint,
|
|
283
331
|
});
|
|
284
332
|
if (!skillsAnswer.selectedSkills || skillsAnswer.selectedSkills.length === 0) {
|
|
285
|
-
warn(
|
|
333
|
+
warn(text.cancelled);
|
|
286
334
|
return;
|
|
287
335
|
}
|
|
288
336
|
const optionsAnswer = await prompts([
|
|
289
337
|
{
|
|
290
338
|
type: "toggle",
|
|
291
339
|
name: "overwrite",
|
|
292
|
-
message:
|
|
340
|
+
message: text.overwritePrompt,
|
|
293
341
|
initial: false,
|
|
294
342
|
active: "yes",
|
|
295
343
|
inactive: "no",
|
|
@@ -297,7 +345,7 @@ async function runInteractiveWizard() {
|
|
|
297
345
|
{
|
|
298
346
|
type: "toggle",
|
|
299
347
|
name: "apply",
|
|
300
|
-
message:
|
|
348
|
+
message: text.applyPrompt,
|
|
301
349
|
initial: true,
|
|
302
350
|
active: "yes",
|
|
303
351
|
inactive: "no",
|
|
@@ -305,14 +353,14 @@ async function runInteractiveWizard() {
|
|
|
305
353
|
{
|
|
306
354
|
type: "toggle",
|
|
307
355
|
name: "strictHints",
|
|
308
|
-
message:
|
|
356
|
+
message: text.strictHintsPrompt,
|
|
309
357
|
initial: false,
|
|
310
358
|
active: "yes",
|
|
311
359
|
inactive: "no",
|
|
312
360
|
},
|
|
313
361
|
]);
|
|
314
362
|
const target = targetAnswer.target;
|
|
315
|
-
info(
|
|
363
|
+
info(text.runDoctor);
|
|
316
364
|
const doctor = await runDoctor(sourceRoot, destinationDir, target);
|
|
317
365
|
for (const line of doctor.info) {
|
|
318
366
|
info(line);
|
|
@@ -324,12 +372,12 @@ async function runInteractiveWizard() {
|
|
|
324
372
|
error(line);
|
|
325
373
|
}
|
|
326
374
|
if (doctor.errors.length > 0) {
|
|
327
|
-
throw new Error(
|
|
375
|
+
throw new Error(text.doctorFailed);
|
|
328
376
|
}
|
|
329
377
|
const dryRun = !Boolean(optionsAnswer.apply);
|
|
330
378
|
const overwriteMode = optionsAnswer.overwrite ? "overwrite" : "skip";
|
|
331
379
|
if (dryRun) {
|
|
332
|
-
warn(
|
|
380
|
+
warn(text.dryRunMode);
|
|
333
381
|
}
|
|
334
382
|
const { state, result } = await runInstall({
|
|
335
383
|
target,
|
|
@@ -347,7 +395,7 @@ async function runInteractiveWizard() {
|
|
|
347
395
|
info(`Files planned: ${result.plannedFiles.length}`);
|
|
348
396
|
if (dryRun) {
|
|
349
397
|
info(`Files would write: ${result.writtenFiles.length}`);
|
|
350
|
-
success(
|
|
398
|
+
success(text.previewCompleted);
|
|
351
399
|
}
|
|
352
400
|
else {
|
|
353
401
|
info(`Files written: ${result.writtenFiles.length}`);
|