chati-dev 4.5.9 → 4.5.11
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/framework/agents/discover/brownfield-wu.md +1 -1
- package/framework/agents/plan/tasks.md +2 -2
- package/framework/config.yaml +2 -2
- package/framework/context/governance.md +10 -10
- package/framework/context/quality.md +6 -6
- package/framework/context/root.md +1 -1
- package/framework/data/entity-registry.yaml +1 -1
- package/framework/hooks/git-push-authority.js +8 -4
- package/framework/i18n/en.yaml +51 -0
- package/framework/i18n/es.yaml +51 -0
- package/framework/i18n/fr.yaml +51 -0
- package/framework/i18n/pt.yaml +51 -0
- package/framework/manifest.json +30 -30
- package/framework/manifest.sig +1 -1
- package/framework/orchestrator/chati.md +29 -20
- package/framework/schemas/session.schema.json +4 -4
- package/package.json +1 -1
- package/src/config/framework-adapter.js +10 -2
- package/src/context/layers/l1-global.js +2 -0
- package/src/installer/core.js +5 -5
- package/src/installer/templates.js +3 -2
- package/src/orchestrator/cli.js +104 -14
- package/src/orchestrator/pipeline-manager.js +2 -0
- package/src/orchestrator/runtime-installation-v2.js +38 -0
- package/src/orchestrator/session-manager.js +1 -1
- package/src/wizard/feedback.js +3 -2
- package/src/wizard/i18n.js +42 -0
- package/src/wizard/index.js +29 -28
- package/src/wizard/questions.js +28 -26
|
@@ -10,6 +10,44 @@ const AGENT_ACTIONS = Object.freeze({
|
|
|
10
10
|
devops: 'build',
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
+
export const V2_PLANNING_AGENTS = Object.freeze([
|
|
14
|
+
'greenfield-wu', 'brownfield-wu', 'brief',
|
|
15
|
+
'detail', 'architect', 'ux', 'qa-planning', 'phases', 'tasks',
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
const RAIL_ACTIONS = new Set(['build', 'review']);
|
|
19
|
+
|
|
20
|
+
export function describeRuntimeInstallationV2(artifact) {
|
|
21
|
+
const railExecutionPool = artifact.installation.enabled_providers.map((binding) => {
|
|
22
|
+
const capabilities = binding.allowed_models.flatMap((modelId) => {
|
|
23
|
+
const model = artifact.capability_snapshot.models.find((candidate) =>
|
|
24
|
+
candidate.provider_id === binding.provider_id && candidate.model_id === modelId
|
|
25
|
+
);
|
|
26
|
+
if (!model) return [];
|
|
27
|
+
const actions = model.actions.filter((action) => RAIL_ACTIONS.has(action));
|
|
28
|
+
if (actions.length === 0) return [];
|
|
29
|
+
return [{ model_id: modelId, actions, tier: model.tier || null }];
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
provider_id: binding.provider_id,
|
|
33
|
+
harness_id: binding.harness_id,
|
|
34
|
+
models: capabilities.map(({ model_id }) => model_id),
|
|
35
|
+
capabilities,
|
|
36
|
+
};
|
|
37
|
+
}).filter(({ models }) => models.length > 0);
|
|
38
|
+
|
|
39
|
+
return Object.freeze({
|
|
40
|
+
architecture: 'chati-v2-rail',
|
|
41
|
+
enabled_providers: artifact.installation.enabled_providers.map(({ provider_id, harness_id }) => ({ provider_id, harness_id })),
|
|
42
|
+
rail_execution_pool: railExecutionPool,
|
|
43
|
+
release_lane: {
|
|
44
|
+
authority: 'explicit-human-authorization',
|
|
45
|
+
execution_authority: 'rail',
|
|
46
|
+
legacy_devops_agent: false,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
13
51
|
export function loadRuntimeInstallationV2(projectDir, { clock = () => new Date() } = {}) {
|
|
14
52
|
const path = join(projectDir, INSTALLATION_ARTIFACT_PATH);
|
|
15
53
|
if (!existsSync(path)) return null;
|
|
@@ -973,7 +973,7 @@ export function validateSession(projectDir) {
|
|
|
973
973
|
}
|
|
974
974
|
|
|
975
975
|
// Validate mode
|
|
976
|
-
const validModes = ['discover', 'plan', 'build', 'validate', 'deploy', 'completed'];
|
|
976
|
+
const validModes = ['discover', 'plan', 'rail', 'release', 'build', 'validate', 'deploy', 'completed'];
|
|
977
977
|
if (!validModes.includes(session.mode)) {
|
|
978
978
|
return {
|
|
979
979
|
exists: true,
|
package/src/wizard/feedback.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import ora from 'ora';
|
|
2
2
|
import { brand, success, dim } from '../utils/colors.js';
|
|
3
|
+
import { t } from './i18n.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Create a spinner with chati.dev branding
|
|
@@ -50,8 +51,8 @@ export function showQuickStart(title, steps) {
|
|
|
50
51
|
console.log(` ${dim(`${i + 1}.`)} ${step}`);
|
|
51
52
|
});
|
|
52
53
|
console.log();
|
|
53
|
-
console.log(`${dim('
|
|
54
|
-
console.log(`${dim('
|
|
54
|
+
console.log(`${dim(`${t('installer.documentation_label')}:`)} .chati.dev/constitution.md`);
|
|
55
|
+
console.log(`${dim(`${t('installer.session_label')}:`)} .chati/session.yaml`);
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
/**
|
package/src/wizard/i18n.js
CHANGED
|
@@ -30,6 +30,10 @@ const FALLBACK_EN = {
|
|
|
30
30
|
ide_selection_title: 'Select your IDEs / CLIs (multiple allowed):',
|
|
31
31
|
provider_selection_title: 'Which AI providers will you use?',
|
|
32
32
|
editor_selection_title: 'Which editor IDEs should get rules files? (optional)',
|
|
33
|
+
provider_claude_hint: 'Anthropic official CLI',
|
|
34
|
+
provider_gemini_hint: 'Google AI terminal agent',
|
|
35
|
+
provider_codex_hint: 'OpenAI Codex terminal agent',
|
|
36
|
+
provider_grok_hint: 'xAI terminal agent',
|
|
33
37
|
installation_mode_title: 'Select the installation mode',
|
|
34
38
|
installation_mode_open: 'Open',
|
|
35
39
|
installation_mode_open_hint: 'Public framework',
|
|
@@ -39,6 +43,19 @@ const FALLBACK_EN = {
|
|
|
39
43
|
back: 'Back',
|
|
40
44
|
back_hint: 'Return to the previous step',
|
|
41
45
|
install: 'Install',
|
|
46
|
+
cancelled: 'Installation cancelled.',
|
|
47
|
+
multiselect_hint: '(space to select, enter to confirm)',
|
|
48
|
+
greenfield_label: 'Greenfield',
|
|
49
|
+
brownfield_label: 'Brownfield',
|
|
50
|
+
none: 'None',
|
|
51
|
+
auto_installed: 'auto-installed',
|
|
52
|
+
connected_via: 'Connected via {providers}',
|
|
53
|
+
target: 'Target',
|
|
54
|
+
yes: 'Yes',
|
|
55
|
+
no: 'No',
|
|
56
|
+
auto_detection_title: 'Auto-detection',
|
|
57
|
+
documentation_label: 'Documentation',
|
|
58
|
+
session_label: 'Session',
|
|
42
59
|
model_routing_label: 'Model routing',
|
|
43
60
|
model_routing_automatic: 'Automatic per task across all enabled models',
|
|
44
61
|
providers_label: 'Providers',
|
|
@@ -64,6 +81,7 @@ const FALLBACK_EN = {
|
|
|
64
81
|
agents_valid: 'All agents implement 8 protocols',
|
|
65
82
|
handoff_ok: 'Handoff protocol: OK',
|
|
66
83
|
validation_ok: 'Self-validation criteria: OK',
|
|
84
|
+
validation_failed_count: "{count} validation check(s) did not pass. Run 'npx chati-dev health' for details.",
|
|
67
85
|
constitution_ok: 'Constitution: 25 articles verified',
|
|
68
86
|
created_memories: 'Created .chati/memories/ (Memory Layer)',
|
|
69
87
|
installed_intelligence: 'Installed Intelligence Layer (Context Engine, Memory, Registry)',
|
|
@@ -84,6 +102,29 @@ const FALLBACK_EN = {
|
|
|
84
102
|
tos_declined: 'Terms of Use declined. Installation cancelled.',
|
|
85
103
|
tos_telemetry_enabled: 'Telemetry: enabled (anonymous, opt-out — disable with: npx chati-dev telemetry disable)',
|
|
86
104
|
tos_telemetry_disabled: 'Telemetry: disabled',
|
|
105
|
+
clickup_required: 'Internal mode requires an authorized ClickUp MCP connection in at least one selected CLI. Configure ClickUp in Claude, Codex or Grok, then retry.',
|
|
106
|
+
system_prerequisites_failed: 'System prerequisites not met:',
|
|
107
|
+
fix_prerequisites: 'Fix the issues above and try again.',
|
|
108
|
+
system_check: 'System check:',
|
|
109
|
+
created_provider_claude: 'Created .claude/commands/ (thin router)',
|
|
110
|
+
created_provider_gemini: 'Created .gemini/commands/ (TOML command)',
|
|
111
|
+
created_provider_codex: 'Created .agents/skills/chati/ (Codex skill)',
|
|
112
|
+
created_provider_grok: 'Created .grok/commands/ (native markdown command)',
|
|
113
|
+
validation_phase: 'Validation',
|
|
114
|
+
installation_phase: 'Installation',
|
|
115
|
+
phase_failed: '{phase} failed: {error}',
|
|
116
|
+
license_activation_title: 'License Activation',
|
|
117
|
+
license_activation_info: 'Your license key works across all projects on this machine.',
|
|
118
|
+
license_trial_info: 'Get a free 14-day trial at: https://chati.dev/pricing',
|
|
119
|
+
license_prompt: 'Enter your license key (press Enter to skip, activate later with: npx chati-dev activate):',
|
|
120
|
+
license_placeholder: 'CHATI-XXXX-XXXX-XXXX',
|
|
121
|
+
license_skipped: 'Skipped. Run: npx chati-dev activate --key=YOUR-KEY when ready.',
|
|
122
|
+
license_activating: 'Activating license...',
|
|
123
|
+
license_activated: 'License activated! Plan: {plan}, {days} day(s) remaining.',
|
|
124
|
+
license_activation_failed: 'Activation failed: {error}',
|
|
125
|
+
license_retry: 'Run: npx chati-dev activate --key=YOUR-KEY to try again.',
|
|
126
|
+
license_saved_invalid: 'Saved license is not valid on this machine: {reason}',
|
|
127
|
+
license_verify_failed: 'Could not verify the saved license: {error}',
|
|
87
128
|
},
|
|
88
129
|
agents: {
|
|
89
130
|
starting: 'Starting agent: {agent}',
|
|
@@ -137,6 +178,7 @@ export function loadLanguage(lang, targetDir = null) {
|
|
|
137
178
|
// Try to load from installed project i18n
|
|
138
179
|
const paths = [
|
|
139
180
|
targetDir && join(targetDir, resolveFrameworkDir(targetDir), 'i18n', `${lang}.yaml`),
|
|
181
|
+
join(__dirname, '..', '..', 'framework', 'i18n', `${lang}.yaml`),
|
|
140
182
|
join(__dirname, '..', '..', 'assets', 'i18n', `${lang}.yaml`),
|
|
141
183
|
].filter(Boolean);
|
|
142
184
|
|
package/src/wizard/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import { validateInstallation } from '../installer/validator.js';
|
|
|
14
14
|
import { initCollector, track as telemetryTrack, flush as telemetryFlush } from '../telemetry/collector.js';
|
|
15
15
|
import { sendEvents } from '../telemetry/sender.js';
|
|
16
16
|
import { getTelemetryConfig } from '../telemetry/config.js';
|
|
17
|
-
import { t } from './i18n.js';
|
|
17
|
+
import { loadLanguage, t } from './i18n.js';
|
|
18
18
|
import { getLicenseKey, activateLicense, ensureCurrentMachineLicense, requireLicenseEntitlement } from '../license/client.js';
|
|
19
19
|
import { DEFAULT_MCPS } from '../config/mcp-configs.js';
|
|
20
20
|
import { IDE_CONFIGS } from '../config/ide-configs.js';
|
|
@@ -40,6 +40,10 @@ export async function runWizard(targetDir, options = {}) {
|
|
|
40
40
|
|
|
41
41
|
p.intro('Setting up chati.dev');
|
|
42
42
|
|
|
43
|
+
// Language is the first question and controls every subsequent wizard step.
|
|
44
|
+
let language = options.language || await stepLanguage();
|
|
45
|
+
loadLanguage(language);
|
|
46
|
+
|
|
43
47
|
await runLicenseActivationStep();
|
|
44
48
|
|
|
45
49
|
// Preflight: validate system prerequisites (Node >= 20, npm, Git, Playwright)
|
|
@@ -50,14 +54,11 @@ export async function runWizard(targetDir, options = {}) {
|
|
|
50
54
|
return ` ${icon} ${c.message}`;
|
|
51
55
|
}).join('\n');
|
|
52
56
|
if (!preflight.passed) {
|
|
53
|
-
p.log.error(
|
|
54
|
-
p.cancel('
|
|
57
|
+
p.log.error(`${t('installer.system_prerequisites_failed')}\n${preflightFmt}`);
|
|
58
|
+
p.cancel(t('installer.fix_prerequisites'));
|
|
55
59
|
process.exit(1);
|
|
56
60
|
}
|
|
57
|
-
p.log.success(
|
|
58
|
-
|
|
59
|
-
// Step 2: Language Selection
|
|
60
|
-
let language = options.language || await stepLanguage();
|
|
61
|
+
p.log.success(`${t('installer.system_check')}\n${preflightFmt}`);
|
|
61
62
|
|
|
62
63
|
// Step 2: Terms of Use (must accept to continue)
|
|
63
64
|
if (options.telemetry === undefined) {
|
|
@@ -156,7 +157,7 @@ export async function runWizard(targetDir, options = {}) {
|
|
|
156
157
|
}
|
|
157
158
|
clickupPreflight = options.clickupPreflight || checkClickUpMcp(selectedProviders);
|
|
158
159
|
if (!clickupPreflight.passed) {
|
|
159
|
-
p.log.error('
|
|
160
|
+
p.log.error(t('installer.clickup_required'));
|
|
160
161
|
continue;
|
|
161
162
|
}
|
|
162
163
|
}
|
|
@@ -229,10 +230,10 @@ export async function runWizard(targetDir, options = {}) {
|
|
|
229
230
|
|
|
230
231
|
// Show provider-specific command creation
|
|
231
232
|
const commandStepMap = {
|
|
232
|
-
'claude-code': '
|
|
233
|
-
'gemini-cli': '
|
|
234
|
-
'codex-cli': '
|
|
235
|
-
'grok-cli': '
|
|
233
|
+
'claude-code': t('installer.created_provider_claude'),
|
|
234
|
+
'gemini-cli': t('installer.created_provider_gemini'),
|
|
235
|
+
'codex-cli': t('installer.created_provider_codex'),
|
|
236
|
+
'grok-cli': t('installer.created_provider_grok'),
|
|
236
237
|
};
|
|
237
238
|
for (const cliIDE of selectedCLIIDEs) {
|
|
238
239
|
showStep(commandStepMap[cliIDE] || t('installer.created_commands'));
|
|
@@ -275,7 +276,7 @@ export async function runWizard(targetDir, options = {}) {
|
|
|
275
276
|
// Warn if any checks failed
|
|
276
277
|
if (validation.passed < validation.total) {
|
|
277
278
|
const failed = validation.total - validation.passed;
|
|
278
|
-
p.log.warn(
|
|
279
|
+
p.log.warn(t('installer.validation_failed_count', { count: failed }));
|
|
279
280
|
}
|
|
280
281
|
|
|
281
282
|
console.log();
|
|
@@ -316,8 +317,8 @@ export async function runWizard(targetDir, options = {}) {
|
|
|
316
317
|
return { success: true, config, validation };
|
|
317
318
|
} catch (err) {
|
|
318
319
|
installSpinner.stop();
|
|
319
|
-
const phase = err.message?.includes('validat') ? '
|
|
320
|
-
p.cancel(
|
|
320
|
+
const phase = err.message?.includes('validat') ? t('installer.validation_phase') : t('installer.installation_phase');
|
|
321
|
+
p.cancel(t('installer.phase_failed', { phase, error: err.message }));
|
|
321
322
|
return { success: false, error: err.message };
|
|
322
323
|
}
|
|
323
324
|
}
|
|
@@ -328,38 +329,38 @@ async function runLicenseActivationStep() {
|
|
|
328
329
|
try {
|
|
329
330
|
const status = await ensureCurrentMachineLicense({ key: existingKey });
|
|
330
331
|
if (status.status === 'VALID') return;
|
|
331
|
-
p.log.warn(
|
|
332
|
+
p.log.warn(t('installer.license_saved_invalid', { reason: status.reason || status.status }));
|
|
332
333
|
} catch (error) {
|
|
333
|
-
p.log.warn(
|
|
334
|
+
p.log.warn(t('installer.license_verify_failed', { error: error.message }));
|
|
334
335
|
}
|
|
335
336
|
}
|
|
336
337
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
338
|
+
p.note(
|
|
339
|
+
`${t('installer.license_activation_info')}\n${t('installer.license_trial_info')}`,
|
|
340
|
+
t('installer.license_activation_title'),
|
|
341
|
+
);
|
|
341
342
|
|
|
342
343
|
const keyInput = await p.text({
|
|
343
|
-
message: '
|
|
344
|
-
placeholder: '
|
|
344
|
+
message: t('installer.license_prompt'),
|
|
345
|
+
placeholder: t('installer.license_placeholder'),
|
|
345
346
|
});
|
|
346
347
|
|
|
347
348
|
if (p.isCancel(keyInput) || !keyInput?.trim()) {
|
|
348
|
-
console.log('
|
|
349
|
+
console.log(` ${t('installer.license_skipped')}\n`);
|
|
349
350
|
return;
|
|
350
351
|
}
|
|
351
352
|
|
|
352
|
-
const activateSpinner = createSpinner('
|
|
353
|
+
const activateSpinner = createSpinner(t('installer.license_activating'));
|
|
353
354
|
activateSpinner.start();
|
|
354
355
|
try {
|
|
355
356
|
const result = await activateLicense(null, keyInput.trim());
|
|
356
357
|
activateSpinner.stop();
|
|
357
358
|
const plan = result.plan ?? 'trial';
|
|
358
359
|
const days = result.days_remaining ?? '?';
|
|
359
|
-
console.log(` ✓
|
|
360
|
+
console.log(` ✓ ${t('installer.license_activated', { plan, days })}\n`);
|
|
360
361
|
} catch (err) {
|
|
361
362
|
activateSpinner.stop();
|
|
362
|
-
console.log(` ✗
|
|
363
|
-
console.log(
|
|
363
|
+
console.log(` ✗ ${t('installer.license_activation_failed', { error: err.message })}`);
|
|
364
|
+
console.log(` ${t('installer.license_retry')}\n`);
|
|
364
365
|
}
|
|
365
366
|
}
|
package/src/wizard/questions.js
CHANGED
|
@@ -9,6 +9,11 @@ import { supportedV2WizardProviders, wizardModelSuggestions } from '../installer
|
|
|
9
9
|
|
|
10
10
|
export const WIZARD_BACK = '__chati_wizard_back__';
|
|
11
11
|
|
|
12
|
+
function cancelInstallation() {
|
|
13
|
+
p.cancel(t('installer.cancelled'));
|
|
14
|
+
process.exit(0);
|
|
15
|
+
}
|
|
16
|
+
|
|
12
17
|
function backOption() {
|
|
13
18
|
return { value: WIZARD_BACK, label: `← ${t('installer.back')}`, hint: t('installer.back_hint') };
|
|
14
19
|
}
|
|
@@ -26,8 +31,7 @@ export async function stepLanguage() {
|
|
|
26
31
|
});
|
|
27
32
|
|
|
28
33
|
if (p.isCancel(language)) {
|
|
29
|
-
|
|
30
|
-
process.exit(0);
|
|
34
|
+
cancelInstallation();
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
// Load i18n strings from this point forward
|
|
@@ -45,7 +49,7 @@ export async function stepProjectType(targetDir, { allowBack = false } = {}) {
|
|
|
45
49
|
if (detection.suggestion === 'brownfield' && detection.confidence !== 'low') {
|
|
46
50
|
p.note(
|
|
47
51
|
`${success('✓')} ${t('installer.detected_brownfield')}\n${t('installer.suggestion_brownfield')}`,
|
|
48
|
-
dim('
|
|
52
|
+
dim(t('installer.auto_detection_title'))
|
|
49
53
|
);
|
|
50
54
|
}
|
|
51
55
|
|
|
@@ -60,8 +64,7 @@ export async function stepProjectType(targetDir, { allowBack = false } = {}) {
|
|
|
60
64
|
});
|
|
61
65
|
|
|
62
66
|
if (p.isCancel(projectType)) {
|
|
63
|
-
|
|
64
|
-
process.exit(0);
|
|
67
|
+
cancelInstallation();
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
return projectType;
|
|
@@ -101,19 +104,18 @@ export async function stepProviderSelection({ allowBack = false } = {}) {
|
|
|
101
104
|
options.push({
|
|
102
105
|
value: provider,
|
|
103
106
|
label: `${providerName}${suffix}`,
|
|
104
|
-
hint:
|
|
107
|
+
hint: t(`installer.provider_${provider}_hint`),
|
|
105
108
|
});
|
|
106
109
|
}
|
|
107
110
|
|
|
108
111
|
const selected = await p.multiselect({
|
|
109
|
-
message: `${t('installer.provider_selection_title')} ${dim(
|
|
112
|
+
message: `${t('installer.provider_selection_title')} ${dim(t('installer.multiselect_hint'))}`,
|
|
110
113
|
options: allowBack ? [...options, backOption()] : options,
|
|
111
114
|
required: true,
|
|
112
115
|
});
|
|
113
116
|
|
|
114
117
|
if (p.isCancel(selected)) {
|
|
115
|
-
|
|
116
|
-
process.exit(0);
|
|
118
|
+
cancelInstallation();
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
return selected.includes(WIZARD_BACK) ? WIZARD_BACK : selected;
|
|
@@ -134,8 +136,7 @@ export async function stepInstallationMode({ allowBack = false } = {}) {
|
|
|
134
136
|
initialValue: 'open',
|
|
135
137
|
});
|
|
136
138
|
if (p.isCancel(mode)) {
|
|
137
|
-
|
|
138
|
-
process.exit(0);
|
|
139
|
+
cancelInstallation();
|
|
139
140
|
}
|
|
140
141
|
return mode;
|
|
141
142
|
}
|
|
@@ -162,14 +163,13 @@ export async function stepEditorSelection({ allowBack = false } = {}) {
|
|
|
162
163
|
}));
|
|
163
164
|
|
|
164
165
|
const selected = await p.multiselect({
|
|
165
|
-
message: `${t('installer.editor_selection_title')} ${dim(
|
|
166
|
+
message: `${t('installer.editor_selection_title')} ${dim(t('installer.multiselect_hint'))}`,
|
|
166
167
|
options: allowBack ? [...options, backOption()] : options,
|
|
167
168
|
required: false,
|
|
168
169
|
});
|
|
169
170
|
|
|
170
171
|
if (p.isCancel(selected)) {
|
|
171
|
-
|
|
172
|
-
process.exit(0);
|
|
172
|
+
cancelInstallation();
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
return selected.includes(WIZARD_BACK) ? WIZARD_BACK : selected;
|
|
@@ -223,14 +223,13 @@ export async function stepIDESelection() {
|
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
const selectedIDEs = await p.multiselect({
|
|
226
|
-
message: `${t('installer.ide_selection_title')} ${dim(
|
|
226
|
+
message: `${t('installer.ide_selection_title')} ${dim(t('installer.multiselect_hint'))}`,
|
|
227
227
|
options,
|
|
228
228
|
required: true,
|
|
229
229
|
});
|
|
230
230
|
|
|
231
231
|
if (p.isCancel(selectedIDEs)) {
|
|
232
|
-
|
|
233
|
-
process.exit(0);
|
|
232
|
+
cancelInstallation();
|
|
234
233
|
}
|
|
235
234
|
|
|
236
235
|
// Filter out separator headers
|
|
@@ -269,13 +268,13 @@ export async function stepConfirmation(config, { allowBack = false } = {}) {
|
|
|
269
268
|
const editorIDEs = (selectedIDEs || []).filter(id => IDE_CONFIGS[id]?.group === 'editor');
|
|
270
269
|
const editorNames = editorIDEs.length > 0
|
|
271
270
|
? editorIDEs.map(id => IDE_CONFIGS[id]?.name || id).join(', ')
|
|
272
|
-
: '
|
|
271
|
+
: t('installer.none');
|
|
273
272
|
const mcpNames = selectedMCPs.length > 0
|
|
274
|
-
? `${selectedMCPs.join(', ')} (
|
|
275
|
-
: '
|
|
273
|
+
? `${selectedMCPs.join(', ')} (${t('installer.auto_installed')})`
|
|
274
|
+
: t('installer.none');
|
|
276
275
|
|
|
277
276
|
const summaryData = {
|
|
278
|
-
[t('installer.project_label')]: `${projectName} (${projectType === 'greenfield' ? '
|
|
277
|
+
[t('installer.project_label')]: `${projectName} (${projectType === 'greenfield' ? t('installer.greenfield_label') : t('installer.brownfield_label')})`,
|
|
279
278
|
[t('installer.language_label')]: langName,
|
|
280
279
|
[t('installer.providers_label')]: providersDisplay,
|
|
281
280
|
[t('installer.installation_mode_label')]: installationMode === 'internal'
|
|
@@ -289,7 +288,7 @@ export async function stepConfirmation(config, { allowBack = false } = {}) {
|
|
|
289
288
|
}
|
|
290
289
|
|
|
291
290
|
if (installationMode === 'internal') {
|
|
292
|
-
summaryData.ClickUp =
|
|
291
|
+
summaryData.ClickUp = t('installer.connected_via', { providers: (clickupPreflight?.connected_providers || []).join(', ') });
|
|
293
292
|
}
|
|
294
293
|
|
|
295
294
|
summaryData[t('installer.mcps_label')] = mcpNames;
|
|
@@ -299,7 +298,7 @@ export async function stepConfirmation(config, { allowBack = false } = {}) {
|
|
|
299
298
|
showSummary(summaryData);
|
|
300
299
|
|
|
301
300
|
console.log();
|
|
302
|
-
console.log(` ${t('installer.will_install')}
|
|
301
|
+
console.log(` ${t('installer.will_install')}`);
|
|
303
302
|
showChecklist([
|
|
304
303
|
t('installer.agents_count'),
|
|
305
304
|
t('installer.workflows_count'),
|
|
@@ -310,7 +309,7 @@ export async function stepConfirmation(config, { allowBack = false } = {}) {
|
|
|
310
309
|
]);
|
|
311
310
|
|
|
312
311
|
console.log();
|
|
313
|
-
console.log(` ${dim('
|
|
312
|
+
console.log(` ${dim(`${t('installer.target')}:`)} ${config.targetDir}`);
|
|
314
313
|
|
|
315
314
|
const proceed = allowBack
|
|
316
315
|
? await p.select({
|
|
@@ -324,13 +323,14 @@ export async function stepConfirmation(config, { allowBack = false } = {}) {
|
|
|
324
323
|
: await p.confirm({
|
|
325
324
|
message: t('installer.proceed'),
|
|
326
325
|
initialValue: true,
|
|
326
|
+
active: t('installer.yes'),
|
|
327
|
+
inactive: t('installer.no'),
|
|
327
328
|
});
|
|
328
329
|
|
|
329
330
|
if (proceed === WIZARD_BACK) return WIZARD_BACK;
|
|
330
331
|
|
|
331
332
|
if (p.isCancel(proceed) || !proceed) {
|
|
332
|
-
|
|
333
|
-
process.exit(0);
|
|
333
|
+
cancelInstallation();
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
return true;
|
|
@@ -354,6 +354,8 @@ export async function stepTermsOfUse() {
|
|
|
354
354
|
const accepted = await p.confirm({
|
|
355
355
|
message: t('installer.tos_accept'),
|
|
356
356
|
initialValue: true,
|
|
357
|
+
active: t('installer.yes'),
|
|
358
|
+
inactive: t('installer.no'),
|
|
357
359
|
});
|
|
358
360
|
|
|
359
361
|
if (p.isCancel(accepted) || !accepted) {
|