chati-dev 4.5.1 → 4.5.2
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/config.yaml +2 -2
- package/framework/context/root.md +1 -1
- package/framework/i18n/en.yaml +8 -2
- package/framework/i18n/es.yaml +8 -2
- package/framework/i18n/fr.yaml +8 -2
- package/framework/i18n/pt.yaml +8 -2
- package/framework/manifest.json +12 -12
- package/framework/manifest.sig +1 -1
- package/node_modules/@chati/provider-registry/src/index.js +21 -5
- package/package.json +1 -1
- package/src/installer/core.js +14 -13
- package/src/installer/provider-overlay.js +8 -15
- package/src/installer/templates.js +9 -22
- package/src/installer/validator.js +4 -9
- package/src/installer-v2/catalog-client.js +32 -8
- package/src/installer-v2/index.js +4 -1
- package/src/installer-v2/model-catalog-envelope.json +224 -5
- package/src/installer-v2/model-catalog.json +101 -4
- package/src/installer-v2/model-catalog.sig +1 -1
- package/src/installer-v2/wizard-installation.js +12 -11
- package/src/license/client.js +26 -0
- package/src/orchestrator/runtime-installation-v2.js +23 -4
- package/src/terminal/cli-registry.js +6 -5
- package/src/terminal/prompt-builder.js +2 -2
- package/src/utils/config-parser.js +3 -8
- package/src/wizard/i18n.js +8 -8
- package/src/wizard/index.js +20 -23
- package/src/wizard/questions.js +31 -66
package/src/wizard/i18n.js
CHANGED
|
@@ -30,14 +30,14 @@ 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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
installation_mode_title: 'Select the installation mode',
|
|
34
|
+
installation_mode_open: 'Open',
|
|
35
|
+
installation_mode_open_hint: 'Public framework without mandatory company integrations',
|
|
36
|
+
installation_mode_internal: 'Internal',
|
|
37
|
+
installation_mode_internal_hint: 'Requires an authorized license and enables ClickUp tracking plus internal policies',
|
|
38
|
+
installation_mode_label: 'Installation mode',
|
|
39
|
+
model_routing_label: 'Model routing',
|
|
40
|
+
model_routing_automatic: 'Automatic per task across all enabled models',
|
|
41
41
|
providers_label: 'Providers',
|
|
42
42
|
quick_start_switch_hint: 'Switch CLIs anytime — your session continues from where you left off',
|
|
43
43
|
created_overlays: 'Created provider overlay directories',
|
package/src/wizard/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { existsSync, readFileSync } from 'fs';
|
|
|
3
3
|
import { join, dirname, basename } from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
import { logBanner } from '../utils/logger.js';
|
|
6
|
-
import { stepLanguage, stepProjectType, stepProviderSelection, stepEditorSelection,
|
|
6
|
+
import { stepLanguage, stepProjectType, stepProviderSelection, stepEditorSelection, stepModelSelection, stepInstallationMode, stepConfirmation, stepTermsOfUse } from './questions.js';
|
|
7
7
|
import { createSpinner, showStep, showValidation, showQuickStart } from './feedback.js';
|
|
8
8
|
import { installFramework } from '../installer/core.js';
|
|
9
9
|
import { INSTALLATION_ARTIFACT_PATH, dryRunV2, installV2, reconfigureV2 } from '../installer-v2/index.js';
|
|
@@ -14,9 +14,9 @@ import { initCollector, track as telemetryTrack, flush as telemetryFlush } from
|
|
|
14
14
|
import { sendEvents } from '../telemetry/sender.js';
|
|
15
15
|
import { getTelemetryConfig } from '../telemetry/config.js';
|
|
16
16
|
import { t } from './i18n.js';
|
|
17
|
-
import { getLicenseKey, activateLicense } from '../license/client.js';
|
|
17
|
+
import { getLicenseKey, activateLicense, requireLicenseEntitlement } from '../license/client.js';
|
|
18
18
|
import { DEFAULT_MCPS } from '../config/mcp-configs.js';
|
|
19
|
-
import { IDE_CONFIGS
|
|
19
|
+
import { IDE_CONFIGS } from '../config/ide-configs.js';
|
|
20
20
|
|
|
21
21
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
22
22
|
const VERSION = JSON.parse(readFileSync(join(__dirname, '..', '..', 'package.json'), 'utf-8')).version;
|
|
@@ -69,11 +69,8 @@ export async function runWizard(targetDir, options = {}) {
|
|
|
69
69
|
// Step 3a: Provider Selection (which AI providers to use)
|
|
70
70
|
const selectedProviders = options.providers || await stepProviderSelection();
|
|
71
71
|
|
|
72
|
-
// Step 3b:
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
// Step 3c: Models allowed for each selected provider. Never add a provider
|
|
76
|
-
// or model that the user did not explicitly bind to this installation.
|
|
72
|
+
// Step 3b: Enable the full signed lineup for every selected provider. Runtime
|
|
73
|
+
// routing selects the right model per task instead of pinning one at install.
|
|
77
74
|
if (options.capabilityCatalog) {
|
|
78
75
|
throw Object.assign(new Error('unsigned capabilityCatalog injection is forbidden; provide signedCapabilityCatalogEnvelope'), { code: 'UNSIGNED_CATALOG_FORBIDDEN' });
|
|
79
76
|
}
|
|
@@ -82,9 +79,12 @@ export async function runWizard(targetDir, options = {}) {
|
|
|
82
79
|
: await resolveCapabilityCatalog({ projectDir: targetDir, catalogUrl: options.catalogUrl, fetchImpl: options.catalogFetch });
|
|
83
80
|
const modelSelections = options.modelSelections || await stepModelSelection(selectedProviders, catalogResolution.catalog);
|
|
84
81
|
|
|
85
|
-
// Step
|
|
86
|
-
//
|
|
87
|
-
const
|
|
82
|
+
// Step 3c: Internal mode is a server-authorized entitlement. It enables the
|
|
83
|
+
// internal policy bundle, including mandatory ClickUp tracking.
|
|
84
|
+
const installationMode = options.installationMode || await stepInstallationMode();
|
|
85
|
+
if (installationMode === 'internal') {
|
|
86
|
+
await requireLicenseEntitlement('internal', { validate: options.licenseValidator });
|
|
87
|
+
}
|
|
88
88
|
|
|
89
89
|
// Step 3e: Editor Selection (which editor IDEs get rules files)
|
|
90
90
|
const selectedEditors = options.editors || await stepEditorSelection();
|
|
@@ -107,21 +107,20 @@ export async function runWizard(targetDir, options = {}) {
|
|
|
107
107
|
projectName,
|
|
108
108
|
projectType,
|
|
109
109
|
language,
|
|
110
|
-
llmProvider: primaryProvider,
|
|
111
110
|
allProviders: cliProviders,
|
|
112
111
|
selectedIDEs,
|
|
113
112
|
selectedMCPs,
|
|
114
|
-
|
|
113
|
+
installationMode,
|
|
114
|
+
modelSelections,
|
|
115
115
|
targetDir,
|
|
116
116
|
version: VERSION,
|
|
117
117
|
};
|
|
118
118
|
const v2InstallationInput = buildWizardV2InstallationInput({
|
|
119
119
|
projectName,
|
|
120
120
|
selectedProviders: cliProviders,
|
|
121
|
-
primaryProvider,
|
|
122
121
|
modelSelections,
|
|
123
122
|
capabilityCatalog: catalogResolution.catalog,
|
|
124
|
-
|
|
123
|
+
installationMode,
|
|
125
124
|
});
|
|
126
125
|
// Validate the complete v2 material and refuse a repeated init before the
|
|
127
126
|
// legacy installer writes anything. Reconfiguration uses its own backup and
|
|
@@ -137,8 +136,7 @@ export async function runWizard(targetDir, options = {}) {
|
|
|
137
136
|
config.telemetryEnabled = options.telemetry !== undefined ? options.telemetry : true;
|
|
138
137
|
|
|
139
138
|
// Installation + Validation
|
|
140
|
-
const
|
|
141
|
-
const primaryIDEName = IDE_CONFIGS[primaryIDE]?.name || primaryIDE;
|
|
139
|
+
const selectedCLIIDEs = selectedIDEs.filter(ide => IDE_CONFIGS[ide]?.group === 'cli');
|
|
142
140
|
|
|
143
141
|
const installStart = Date.now();
|
|
144
142
|
|
|
@@ -161,8 +159,9 @@ export async function runWizard(targetDir, options = {}) {
|
|
|
161
159
|
'gemini-cli': 'Created .gemini/commands/ (TOML command)',
|
|
162
160
|
'codex-cli': 'Created .agents/skills/chati/ (Codex skill)',
|
|
163
161
|
};
|
|
164
|
-
const
|
|
165
|
-
|
|
162
|
+
for (const cliIDE of selectedCLIIDEs) {
|
|
163
|
+
showStep(commandStepMap[cliIDE] || t('installer.created_commands'));
|
|
164
|
+
}
|
|
166
165
|
|
|
167
166
|
showStep(t('installer.installed_constitution'));
|
|
168
167
|
showStep(t('installer.created_session'));
|
|
@@ -211,10 +210,9 @@ export async function runWizard(targetDir, options = {}) {
|
|
|
211
210
|
const invokeCmdMap = {
|
|
212
211
|
'codex-cli': '$chati',
|
|
213
212
|
};
|
|
214
|
-
const invokeCmd = invokeCmdMap[primaryIDE] || '/chati';
|
|
215
213
|
const quickStartSteps = [
|
|
216
|
-
|
|
217
|
-
|
|
214
|
+
t('installer.quick_start_1'),
|
|
215
|
+
...selectedCLIIDEs.map((cliIDE) => `${IDE_CONFIGS[cliIDE]?.name || cliIDE}: ${invokeCmdMap[cliIDE] || '/chati'}`),
|
|
218
216
|
t('installer.quick_start_3'),
|
|
219
217
|
];
|
|
220
218
|
|
|
@@ -232,7 +230,6 @@ export async function runWizard(targetDir, options = {}) {
|
|
|
232
230
|
editors: selectedEditors,
|
|
233
231
|
projectType,
|
|
234
232
|
language,
|
|
235
|
-
primaryProvider,
|
|
236
233
|
installDuration: Date.now() - installStart,
|
|
237
234
|
});
|
|
238
235
|
const installEvents = telemetryFlush();
|
package/src/wizard/questions.js
CHANGED
|
@@ -5,7 +5,7 @@ import { showSummary, showChecklist } from './feedback.js';
|
|
|
5
5
|
import { brand, dim, success } from '../utils/colors.js';
|
|
6
6
|
import { isProviderAvailable } from '../terminal/cli-registry.js';
|
|
7
7
|
import { IDE_CONFIGS, IDE_TO_PROVIDER } from '../config/ide-configs.js';
|
|
8
|
-
import { supportedV2WizardProviders,
|
|
8
|
+
import { supportedV2WizardProviders, wizardModelSuggestions } from '../installer-v2/wizard-installation.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Step 1: Language Selection (always in English)
|
|
@@ -93,7 +93,7 @@ export async function stepProviderSelection() {
|
|
|
93
93
|
const providerName = PROVIDER_DISPLAY_NAMES[provider] || config.name;
|
|
94
94
|
options.push({
|
|
95
95
|
value: provider,
|
|
96
|
-
label: `${providerName}${
|
|
96
|
+
label: `${providerName}${suffix}`,
|
|
97
97
|
hint: config.description,
|
|
98
98
|
});
|
|
99
99
|
}
|
|
@@ -116,22 +116,26 @@ export async function stepProviderSelection() {
|
|
|
116
116
|
* Selects the operational policy profile. Focus AI internal projects require
|
|
117
117
|
* ClickUp tracking; standard projects do not gain that external dependency.
|
|
118
118
|
*/
|
|
119
|
-
export async function
|
|
120
|
-
const
|
|
121
|
-
message: t('installer.
|
|
119
|
+
export async function stepInstallationMode() {
|
|
120
|
+
const mode = await p.select({
|
|
121
|
+
message: t('installer.installation_mode_title'),
|
|
122
122
|
options: [
|
|
123
|
-
{ value: '
|
|
124
|
-
{ value: '
|
|
123
|
+
{ value: 'open', label: t('installer.installation_mode_open'), hint: t('installer.installation_mode_open_hint') },
|
|
124
|
+
{ value: 'internal', label: t('installer.installation_mode_internal'), hint: t('installer.installation_mode_internal_hint') },
|
|
125
125
|
],
|
|
126
|
-
initialValue: '
|
|
126
|
+
initialValue: 'open',
|
|
127
127
|
});
|
|
128
|
-
if (p.isCancel(
|
|
128
|
+
if (p.isCancel(mode)) {
|
|
129
129
|
p.cancel('Installation cancelled.');
|
|
130
130
|
process.exit(0);
|
|
131
131
|
}
|
|
132
|
-
return
|
|
132
|
+
return mode;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
// Backward-compatible programmatic alias. The interactive wizard no longer
|
|
136
|
+
// exposes an abstract execution profile to users.
|
|
137
|
+
export const stepExecutionProfile = stepInstallationMode;
|
|
138
|
+
|
|
135
139
|
/**
|
|
136
140
|
* Step 3b: Editor Selection (multi-select, optional)
|
|
137
141
|
*
|
|
@@ -226,59 +230,22 @@ export async function stepIDESelection() {
|
|
|
226
230
|
}
|
|
227
231
|
|
|
228
232
|
/**
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
* Determines which provider's adapted files go in chati.dev/ (main).
|
|
233
|
-
*/
|
|
234
|
-
export async function stepPrimaryProvider(cliProviders) {
|
|
235
|
-
if (cliProviders.length <= 1) return cliProviders[0] || 'claude';
|
|
236
|
-
|
|
237
|
-
const primary = await p.select({
|
|
238
|
-
message: t('installer.primary_provider_title'),
|
|
239
|
-
options: cliProviders.map(prov => ({
|
|
240
|
-
value: prov,
|
|
241
|
-
label: PROVIDER_DISPLAY_NAMES[prov] || prov,
|
|
242
|
-
})),
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
if (p.isCancel(primary)) {
|
|
246
|
-
p.cancel('Installation cancelled.');
|
|
247
|
-
process.exit(0);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return primary;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Records exactly which models the installation is allowed to orchestrate.
|
|
255
|
-
* A catalog refresh can replace the suggestion, but the user remains the
|
|
256
|
-
* authority for the final binding stored in the installation artifact.
|
|
233
|
+
* Enables every catalog model for each selected provider. Runtime routing
|
|
234
|
+
* chooses a model per task, so installation never collapses a provider to one
|
|
235
|
+
* supposedly universal "recommended" model.
|
|
257
236
|
*/
|
|
258
237
|
export async function stepModelSelection(providers, capabilityCatalog) {
|
|
259
238
|
const selections = {};
|
|
239
|
+
const summary = [];
|
|
260
240
|
|
|
261
241
|
for (const provider of providers) {
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
message: `Models for ${PROVIDER_DISPLAY_NAMES[provider] || provider} (comma-separated):`,
|
|
266
|
-
placeholder: suggestions.join(', '),
|
|
267
|
-
initialValue: suggested,
|
|
268
|
-
validate: (value) => {
|
|
269
|
-
const models = String(value || '').split(',').map((item) => item.trim()).filter(Boolean);
|
|
270
|
-
return models.length > 0 ? undefined : 'Select at least one model.';
|
|
271
|
-
},
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
if (p.isCancel(answer)) {
|
|
275
|
-
p.cancel('Installation cancelled.');
|
|
276
|
-
process.exit(0);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
selections[provider] = String(answer).split(',').map((item) => item.trim()).filter(Boolean);
|
|
242
|
+
const models = wizardModelSuggestions(provider, capabilityCatalog);
|
|
243
|
+
selections[provider] = [...models];
|
|
244
|
+
summary.push(`${PROVIDER_DISPLAY_NAMES[provider] || provider}: ${models.join(', ')}`);
|
|
280
245
|
}
|
|
281
246
|
|
|
247
|
+
p.note(summary.join('\n'), t('installer.model_routing_label'));
|
|
248
|
+
|
|
282
249
|
return selections;
|
|
283
250
|
}
|
|
284
251
|
|
|
@@ -286,16 +253,13 @@ export async function stepModelSelection(providers, capabilityCatalog) {
|
|
|
286
253
|
* Step 4: Confirmation
|
|
287
254
|
*/
|
|
288
255
|
export async function stepConfirmation(config) {
|
|
289
|
-
const { projectName, projectType, language,
|
|
256
|
+
const { projectName, projectType, language, selectedMCPs, selectedIDEs, allProviders, installationMode } = config;
|
|
290
257
|
|
|
291
258
|
const langName = SUPPORTED_LANGUAGES.find(l => l.value === language)?.label || language;
|
|
292
259
|
|
|
293
|
-
// Show all providers
|
|
294
|
-
const providers = allProviders || [
|
|
295
|
-
const providersDisplay = providers.map(prov =>
|
|
296
|
-
const name = PROVIDER_DISPLAY_NAMES[prov] || prov;
|
|
297
|
-
return prov === llmProvider ? `${name} (Primary)` : name;
|
|
298
|
-
}).join(', ');
|
|
260
|
+
// Show all enabled providers symmetrically.
|
|
261
|
+
const providers = allProviders || [];
|
|
262
|
+
const providersDisplay = providers.map(prov => PROVIDER_DISPLAY_NAMES[prov] || prov).join(', ');
|
|
299
263
|
|
|
300
264
|
// Separate editors from CLI IDEs for display
|
|
301
265
|
const editorIDEs = (selectedIDEs || []).filter(id => IDE_CONFIGS[id]?.group === 'editor');
|
|
@@ -310,9 +274,10 @@ export async function stepConfirmation(config) {
|
|
|
310
274
|
[t('installer.project_label')]: `${projectName} (${projectType === 'greenfield' ? 'Greenfield' : 'Brownfield'})`,
|
|
311
275
|
[t('installer.language_label')]: langName,
|
|
312
276
|
[t('installer.providers_label')]: providersDisplay,
|
|
313
|
-
[t('installer.
|
|
314
|
-
|
|
315
|
-
|
|
277
|
+
[t('installer.model_routing_label')]: t('installer.model_routing_automatic'),
|
|
278
|
+
[t('installer.installation_mode_label')]: installationMode === 'internal'
|
|
279
|
+
? t('installer.installation_mode_internal')
|
|
280
|
+
: t('installer.installation_mode_open'),
|
|
316
281
|
};
|
|
317
282
|
|
|
318
283
|
// Only show editor IDEs line if any were selected
|