fraim 2.0.176 → 2.0.179

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.
@@ -44,8 +44,6 @@ const prompts_1 = __importDefault(require("prompts"));
44
44
  const fs_1 = __importDefault(require("fs"));
45
45
  const path_1 = __importDefault(require("path"));
46
46
  const auto_mcp_setup_1 = require("../setup/auto-mcp-setup");
47
- const provider_client_1 = require("../api/provider-client");
48
- const provider_prompts_1 = require("../setup/provider-prompts");
49
47
  const provider_registry_1 = require("../providers/provider-registry");
50
48
  const script_sync_utils_1 = require("../utils/script-sync-utils");
51
49
  function parseModeOption(mode) {
@@ -170,67 +168,15 @@ const promptForMode = async () => {
170
168
  }
171
169
  return response.mode;
172
170
  };
173
- /**
174
- * Sanitize a token by removing control characters that cause JSON serialization issues
175
- */
176
- const sanitizeToken = (token) => {
177
- if (!token)
178
- return token;
179
- // Remove control characters (0x00-0x1F and 0x7F) that cause JSON escaping issues
180
- // These characters are not valid in API tokens and are likely copy-paste artifacts
181
- return token.replace(/[\x00-\x1F\x7F]/g, '');
182
- };
183
- /**
184
- * Sanitize all tokens in a ProviderTokens object
185
- */
186
- const sanitizeTokens = (tokens) => {
187
- const sanitized = {};
188
- Object.entries(tokens).forEach(([providerId, token]) => {
189
- if (token) {
190
- const originalToken = token;
191
- const sanitizedToken = sanitizeToken(token);
192
- if (originalToken !== sanitizedToken) {
193
- console.log(chalk_1.default.yellow(`⚠️ Sanitized ${providerId} token: removed ${originalToken.length - sanitizedToken.length} control character(s)`));
194
- }
195
- sanitized[providerId] = sanitizedToken;
196
- }
197
- });
198
- return sanitized;
199
- };
200
- const saveGlobalConfig = (fraimKey, mode, tokens, configs) => {
171
+ const saveGlobalConfig = (fraimKey, mode) => {
201
172
  const globalConfigDir = (0, script_sync_utils_1.getUserFraimDir)();
202
173
  const globalConfigPath = path_1.default.join(globalConfigDir, 'config.json');
203
174
  if (!fs_1.default.existsSync(globalConfigDir)) {
204
175
  fs_1.default.mkdirSync(globalConfigDir, { recursive: true });
205
176
  }
206
- // Read existing config to preserve any existing data
207
- let existingConfig = {};
208
- if (fs_1.default.existsSync(globalConfigPath)) {
209
- try {
210
- existingConfig = JSON.parse(fs_1.default.readFileSync(globalConfigPath, 'utf8'));
211
- }
212
- catch (e) {
213
- // Ignore parse errors, will create new config
214
- }
215
- }
216
- // Sanitize tokens before saving to prevent JSON serialization issues
217
- const sanitizedTokens = sanitizeTokens(tokens);
218
- // Merge provider configs (e.g., jiraConfig)
219
- const providerConfigs = { ...(existingConfig.providerConfigs || {}) };
220
- Object.entries(configs).forEach(([providerId, config]) => {
221
- providerConfigs[`${providerId}Config`] = {
222
- ...(providerConfigs[`${providerId}Config`] || {}),
223
- ...config
224
- };
225
- });
226
177
  const config = {
227
178
  apiKey: fraimKey,
228
179
  mode: mode,
229
- tokens: {
230
- ...(existingConfig.tokens || {}),
231
- ...sanitizedTokens
232
- },
233
- providerConfigs,
234
180
  configuredAt: new Date().toISOString(),
235
181
  userPreferences: {
236
182
  autoSync: true,
@@ -241,49 +187,6 @@ const saveGlobalConfig = (fraimKey, mode, tokens, configs) => {
241
187
  console.log(chalk_1.default.green('✅ Global FRAIM configuration saved'));
242
188
  };
243
189
  exports.saveGlobalConfig = saveGlobalConfig;
244
- // Parse CLI options into generic format using provider registry from server
245
- // Tokens/config are optional - will prompt if not provided
246
- const parseLegacyOptions = async (options, fraimKey) => {
247
- const requestedProviders = [];
248
- const providedTokens = {};
249
- const providedConfigs = {};
250
- // Use provider registry (with fallback) instead of direct client call
251
- const { getAllProviderIds, getProviderConfigRequirements } = await Promise.resolve().then(() => __importStar(require('../providers/provider-registry')));
252
- const providerIds = await getAllProviderIds();
253
- // Dynamically check for provider flags from server registry
254
- for (const providerId of providerIds) {
255
- // Check for provider flag (e.g., --github)
256
- if (options[providerId]) {
257
- requestedProviders.push(providerId);
258
- }
259
- // Check for token option (e.g., --github-token)
260
- const tokenKey = `${providerId}Token`;
261
- if (options[tokenKey]) {
262
- providedTokens[providerId] = options[tokenKey];
263
- }
264
- // Check for provider-specific config options
265
- const configReqs = await getProviderConfigRequirements(providerId);
266
- if (configReqs.length > 0) {
267
- const config = {};
268
- let hasAnyConfig = false;
269
- configReqs.forEach(req => {
270
- // Use custom CLI option name if provided, otherwise convert key to camelCase
271
- const optionSuffix = req.cliOptionName
272
- ? req.cliOptionName.charAt(0).toUpperCase() + req.cliOptionName.slice(1)
273
- : req.key.charAt(0).toUpperCase() + req.key.slice(1);
274
- const optionKey = `${providerId}${optionSuffix}`;
275
- if (options[optionKey]) {
276
- config[req.key] = options[optionKey];
277
- hasAnyConfig = true;
278
- }
279
- });
280
- if (hasAnyConfig) {
281
- providedConfigs[providerId] = config;
282
- }
283
- }
284
- }
285
- return { requestedProviders, providedTokens, providedConfigs };
286
- };
287
190
  const runSetup = async (options) => {
288
191
  console.log(chalk_1.default.blue('🚀 Welcome to FRAIM! Let\'s get you set up.\n'));
289
192
  // Determine if this is an update (adding platforms to existing setup)
@@ -291,54 +194,27 @@ const runSetup = async (options) => {
291
194
  const isUpdate = fs_1.default.existsSync(globalConfigPath);
292
195
  let fraimKey;
293
196
  let mode;
294
- const tokens = {};
295
- const configs = {};
296
- let requestedProviders = [];
297
- let providedTokens = {};
298
- let providedConfigs = {};
299
197
  if (isUpdate) {
300
- // Update existing setup - add platforms
301
198
  console.log(chalk_1.default.blue('📝 Existing FRAIM configuration detected.\n'));
302
199
  try {
303
200
  const existingConfig = JSON.parse(fs_1.default.readFileSync(globalConfigPath, 'utf8'));
304
- // Allow updating FRAIM key even without provider changes
305
201
  fraimKey = options.key || existingConfig.apiKey;
306
- // Now we can parse options with the FRAIM key
307
- const parsed = await parseLegacyOptions(options, fraimKey);
308
- requestedProviders = parsed.requestedProviders;
309
- providedTokens = parsed.providedTokens;
310
- providedConfigs = parsed.providedConfigs;
311
- // Check if this is just a key update or a provider update
202
+ mode = existingConfig.mode || 'integrated';
312
203
  const isKeyUpdate = options.key && options.key !== existingConfig.apiKey;
313
- const isProviderUpdate = requestedProviders.length > 0;
314
- // If no specific changes requested, offer interactive update
315
- if (!isKeyUpdate && !isProviderUpdate) {
204
+ if (!isKeyUpdate) {
316
205
  console.log(chalk_1.default.gray(' Current configuration:'));
317
- console.log(chalk_1.default.gray(` • Mode: ${existingConfig.mode || 'integrated'}`));
318
- // Show existing tokens
319
- const { getProvider } = await Promise.resolve().then(() => __importStar(require('../providers/provider-registry')));
320
- if (existingConfig.tokens && Object.keys(existingConfig.tokens).length > 0) {
321
- const providerNames = await Promise.all(Object.keys(existingConfig.tokens).map(async (id) => {
322
- const provider = await getProvider(id);
323
- return provider?.displayName || id;
324
- }));
325
- console.log(chalk_1.default.gray(` • Providers: ${providerNames.join(', ')}`));
326
- }
327
- else {
328
- console.log(chalk_1.default.gray(' • Providers: none'));
329
- }
206
+ console.log(chalk_1.default.gray(` • Mode: ${mode}`));
207
+ console.log(chalk_1.default.gray(' • Platforms: managed per-project via fraim add-provider'));
330
208
  console.log();
331
- // Ask user what they want to do
209
+ if (process.env.FRAIM_NON_INTERACTIVE || process.env.CI) {
210
+ console.log(chalk_1.default.gray('Setup already configured. Use "fraim add-provider <provider>" to connect platforms.'));
211
+ return;
212
+ }
332
213
  const response = await (0, prompts_1.default)({
333
214
  type: 'select',
334
215
  name: 'action',
335
216
  message: 'What would you like to do?',
336
217
  choices: [
337
- {
338
- title: 'Add a provider',
339
- value: 'add-provider',
340
- description: 'Add a new platform integration (GitHub, GitLab, etc.)'
341
- },
342
218
  {
343
219
  title: 'Update FRAIM key',
344
220
  value: 'update-key',
@@ -361,104 +237,27 @@ const runSetup = async (options) => {
361
237
  console.log(chalk_1.default.gray('\nSetup cancelled. No changes made.'));
362
238
  return;
363
239
  }
364
- if (response.action === 'add-provider') {
365
- console.log(chalk_1.default.blue('\n📦 Adding a provider...\n'));
366
- const providerClient = new provider_client_1.ProviderClient(fraimKey, process.env.FRAIM_REMOTE_URL || undefined);
367
- // Prompt for which provider to add
368
- const providersToAdd = await (0, provider_prompts_1.promptForProviders)(providerClient);
369
- requestedProviders = providersToAdd;
370
- }
371
- else if (response.action === 'update-key') {
240
+ if (response.action === 'update-key') {
372
241
  console.log(chalk_1.default.blue('\n🔑 Updating FRAIM key...\n'));
373
242
  fraimKey = await promptForFraimKey();
374
243
  }
375
244
  else if (response.action === 'reconfigure') {
376
245
  console.log(chalk_1.default.blue('\n🔄 Starting fresh setup...\n'));
377
- // Backup existing config
378
246
  const backupPath = globalConfigPath + '.backup.' + Date.now();
379
247
  fs_1.default.copyFileSync(globalConfigPath, backupPath);
380
248
  console.log(chalk_1.default.gray(` Backed up existing config to: ${path_1.default.basename(backupPath)}\n`));
381
- // Treat as fresh setup
382
249
  fraimKey = options.key || await promptForFraimKey();
383
250
  console.log(chalk_1.default.green('✅ FRAIM key accepted\n'));
384
251
  mode = options.mode ? parseModeOption(options.mode) : await promptForMode();
385
- const parsed = await parseLegacyOptions(options, fraimKey);
386
- requestedProviders = parsed.requestedProviders;
387
- providedTokens = parsed.providedTokens;
388
- providedConfigs = parsed.providedConfigs;
389
- // Clear existing tokens/configs for fresh start
390
- Object.keys(tokens).forEach(key => delete tokens[key]);
391
- Object.keys(configs).forEach(key => delete configs[key]);
392
- // Continue with fresh setup flow
393
- const providerClient = new provider_client_1.ProviderClient(fraimKey, process.env.FRAIM_REMOTE_URL || undefined);
394
- if (mode === 'integrated') {
395
- let providersToSetup = requestedProviders;
396
- if (providersToSetup.length === 0) {
397
- providersToSetup = await (0, provider_prompts_1.promptForProviders)(providerClient);
398
- }
399
- for (const providerId of providersToSetup) {
400
- try {
401
- const creds = await (0, provider_prompts_1.promptForProviderCredentials)(providerClient, providerId, providedTokens[providerId], providedConfigs[providerId]);
402
- tokens[providerId] = creds.token;
403
- if (creds.config) {
404
- configs[providerId] = creds.config;
405
- }
406
- }
407
- catch (e) {
408
- const providerName = await (0, provider_registry_1.getProviderDisplayName)(providerId);
409
- console.log(chalk_1.default.red(`❌ Failed to get ${providerName} credentials`));
410
- process.exit(1);
411
- }
412
- }
413
- }
414
- else if (mode === 'split') {
415
- // Split mode setup
416
- console.log(chalk_1.default.blue('\n🔀 Split Mode Configuration'));
417
- console.log(chalk_1.default.gray('Configure separate platforms for code hosting and issue tracking.\n'));
418
- const codeRepoProvider = await (0, provider_prompts_1.promptForSingleProvider)(providerClient, 'code');
419
- const creds1 = await (0, provider_prompts_1.promptForProviderCredentials)(providerClient, codeRepoProvider, providedTokens[codeRepoProvider], providedConfigs[codeRepoProvider]);
420
- tokens[codeRepoProvider] = creds1.token;
421
- if (creds1.config) {
422
- configs[codeRepoProvider] = creds1.config;
423
- }
424
- const issueProvider = await (0, provider_prompts_1.promptForSingleProvider)(providerClient, 'issues');
425
- if (!tokens[issueProvider]) {
426
- const creds2 = await (0, provider_prompts_1.promptForProviderCredentials)(providerClient, issueProvider, providedTokens[issueProvider], providedConfigs[issueProvider]);
427
- tokens[issueProvider] = creds2.token;
428
- if (creds2.config) {
429
- configs[issueProvider] = creds2.config;
430
- }
431
- }
432
- }
433
- // Save and configure MCP
434
252
  console.log(chalk_1.default.blue('\n💾 Saving global configuration...'));
435
- (0, exports.saveGlobalConfig)(fraimKey, mode, tokens, configs);
253
+ (0, exports.saveGlobalConfig)(fraimKey, mode);
436
254
  console.log(chalk_1.default.blue('\n🔌 Configuring MCP servers...'));
437
- const mcpTokens = {};
438
- Object.entries(tokens).forEach(([id, token]) => {
439
- mcpTokens[id] = token;
440
- });
441
- const providerConfigsMap = {};
442
- Object.entries(configs).forEach(([providerId, config]) => {
443
- providerConfigsMap[providerId] = config;
444
- });
445
- await (0, auto_mcp_setup_1.autoConfigureMCP)(fraimKey, mcpTokens, options.ide ? [options.ide] : undefined, providerConfigsMap);
255
+ await (0, auto_mcp_setup_1.autoConfigureMCP)(fraimKey, options.ide ? [options.ide] : undefined);
446
256
  console.log(chalk_1.default.green('\n🎯 Reconfiguration complete!'));
257
+ console.log(chalk_1.default.cyan('\n💡 To connect platforms, run: fraim add-provider <github|gitlab|ado|jira>'));
447
258
  return;
448
259
  }
449
260
  }
450
- mode = existingConfig.mode || 'integrated';
451
- // Preserve existing tokens
452
- if (existingConfig.tokens) {
453
- Object.assign(tokens, existingConfig.tokens);
454
- }
455
- // Preserve existing configs
456
- if (existingConfig.providerConfigs) {
457
- Object.entries(existingConfig.providerConfigs).forEach(([key, value]) => {
458
- const providerId = key.replace('Config', '');
459
- configs[providerId] = value;
460
- });
461
- }
462
261
  }
463
262
  catch (e) {
464
263
  console.log(chalk_1.default.red('❌ Failed to read existing configuration'));
@@ -467,129 +266,29 @@ const runSetup = async (options) => {
467
266
  }
468
267
  }
469
268
  else {
470
- // Initial setup
471
269
  console.log(chalk_1.default.yellow('📋 This setup will:'));
472
270
  console.log(chalk_1.default.gray(' • Validate your FRAIM key'));
473
271
  console.log(chalk_1.default.gray(' • Choose your usage mode'));
474
- console.log(chalk_1.default.gray(' • Configure platform integrations'));
272
+ console.log(chalk_1.default.gray(' • Configure FRAIM MCP servers in your IDEs'));
475
273
  console.log(chalk_1.default.gray(' • Sync FRAIM scripts to your system\n'));
476
- // Get FRAIM key
274
+ console.log(chalk_1.default.gray(' Platforms (GitHub, GitLab, etc.) are connected per-project'));
275
+ console.log(chalk_1.default.gray(' via "fraim add-provider" — no tokens needed here.\n'));
477
276
  fraimKey = options.key || await promptForFraimKey();
478
277
  console.log(chalk_1.default.green('✅ FRAIM key accepted\n'));
479
- // Ask for mode preference (or use explicit option)
480
278
  mode = options.mode ? parseModeOption(options.mode) : await promptForMode();
481
- // Parse provider CLI flags on first-time setup too
482
- const parsed = await parseLegacyOptions(options, fraimKey);
483
- requestedProviders = parsed.requestedProviders;
484
- providedTokens = parsed.providedTokens;
485
- providedConfigs = parsed.providedConfigs;
486
- }
487
- const providerClient = new provider_client_1.ProviderClient(fraimKey, process.env.FRAIM_REMOTE_URL || undefined);
488
- // Handle platform tokens based on mode
489
- if (mode === 'integrated') {
490
- let providersToSetup = requestedProviders;
491
- // If no specific providers requested and not an update, ask user
492
- if (!isUpdate && providersToSetup.length === 0) {
493
- providersToSetup = await (0, provider_prompts_1.promptForProviders)(providerClient);
494
- }
495
- // Get credentials for each provider
496
- for (const providerId of providersToSetup) {
497
- if (!tokens[providerId]) {
498
- try {
499
- // Use provided tokens if available, otherwise prompt
500
- const creds = await (0, provider_prompts_1.promptForProviderCredentials)(providerClient, providerId, providedTokens[providerId], providedConfigs[providerId]);
501
- tokens[providerId] = creds.token;
502
- if (creds.config) {
503
- configs[providerId] = creds.config;
504
- }
505
- }
506
- catch (e) {
507
- const providerName = await (0, provider_registry_1.getProviderDisplayName)(providerId);
508
- console.log(chalk_1.default.red(`❌ Failed to get ${providerName} credentials`));
509
- process.exit(1);
510
- }
511
- }
512
- }
513
- if (Object.keys(tokens).length === 0) {
514
- console.log(chalk_1.default.yellow('⚠️ No platform tokens configured.'));
515
- console.log(chalk_1.default.gray(' You can add them later with:'));
516
- const allProviderIds = await (0, provider_registry_1.getAllProviderIds)();
517
- allProviderIds.forEach(id => {
518
- console.log(chalk_1.default.cyan(` fraim setup --${id}`));
519
- });
520
- console.log();
521
- }
522
- }
523
- else if (mode === 'split') {
524
- // Split mode: separate platforms for code repository and issue tracking
525
- console.log(chalk_1.default.blue('\n🔀 Split Mode Configuration'));
526
- console.log(chalk_1.default.gray('Configure separate platforms for code hosting and issue tracking.\n'));
527
- // Get code repository platform
528
- const codeRepoProvider = await (0, provider_prompts_1.promptForSingleProvider)(providerClient, 'code');
529
- // Get code repository credentials
530
- if (!tokens[codeRepoProvider]) {
531
- try {
532
- // Use provided tokens if available, otherwise prompt
533
- const creds = await (0, provider_prompts_1.promptForProviderCredentials)(providerClient, codeRepoProvider, providedTokens[codeRepoProvider], providedConfigs[codeRepoProvider]);
534
- tokens[codeRepoProvider] = creds.token;
535
- if (creds.config) {
536
- configs[codeRepoProvider] = creds.config;
537
- }
538
- }
539
- catch (e) {
540
- const providerName = await (0, provider_registry_1.getProviderDisplayName)(codeRepoProvider);
541
- console.log(chalk_1.default.red(`❌ Failed to get ${providerName} credentials`));
542
- process.exit(1);
543
- }
544
- }
545
- // Get issue tracking platform
546
- const issueProvider = await (0, provider_prompts_1.promptForSingleProvider)(providerClient, 'issues');
547
- // Get issue tracking credentials (if different from code repo)
548
- if (!tokens[issueProvider]) {
549
- try {
550
- // Use provided tokens if available, otherwise prompt
551
- const creds = await (0, provider_prompts_1.promptForProviderCredentials)(providerClient, issueProvider, providedTokens[issueProvider], providedConfigs[issueProvider]);
552
- tokens[issueProvider] = creds.token;
553
- if (creds.config) {
554
- configs[issueProvider] = creds.config;
555
- }
556
- }
557
- catch (e) {
558
- const providerName = await (0, provider_registry_1.getProviderDisplayName)(issueProvider);
559
- console.log(chalk_1.default.red(`❌ Failed to get ${providerName} credentials`));
560
- process.exit(1);
561
- }
562
- }
563
- const codeRepoName = await (0, provider_registry_1.getProviderDisplayName)(codeRepoProvider);
564
- const issueName = await (0, provider_registry_1.getProviderDisplayName)(issueProvider);
565
- console.log(chalk_1.default.green(`\n✅ Split mode configured: ${codeRepoName} (code) + ${issueName} (issues)\n`));
566
- }
567
- else {
568
- console.log(chalk_1.default.gray('ℹ️ Conversational mode: No platform tokens needed\n'));
569
279
  }
570
- // Save global configuration
280
+ // Save global configuration (key + mode only; provider tokens live in IDE MCP configs)
571
281
  console.log(chalk_1.default.blue('💾 Saving global configuration...'));
572
- (0, exports.saveGlobalConfig)(fraimKey, mode, tokens, configs);
282
+ (0, exports.saveGlobalConfig)(fraimKey, mode);
573
283
  // Configure MCP servers
574
284
  if (!isUpdate) {
575
- // Initial setup - configure all detected IDEs
576
285
  console.log(chalk_1.default.blue('\n🔌 Configuring MCP servers...'));
577
- // Convert to legacy format for MCP config generator
578
- const mcpTokens = {};
579
- Object.entries(tokens).forEach(([id, token]) => {
580
- mcpTokens[id] = token;
581
- });
582
- if (mode === 'conversational' && Object.keys(mcpTokens).length === 0) {
583
- console.log(chalk_1.default.yellow('ℹ️ Conversational mode: Configuring MCP servers without platform integration'));
584
- console.log(chalk_1.default.gray(' FRAIM jobs will work, but platform-specific features will be unavailable\n'));
286
+ if (mode === 'conversational') {
287
+ console.log(chalk_1.default.yellow('ℹ️ Conversational mode: Configuring FRAIM MCP server'));
288
+ console.log(chalk_1.default.gray(' FRAIM jobs will work; platform-specific features are added via fraim add-provider\n'));
585
289
  }
586
290
  try {
587
- // Build providerConfigs map from configs
588
- const providerConfigsMap = {};
589
- Object.entries(configs).forEach(([providerId, config]) => {
590
- providerConfigsMap[providerId] = config;
591
- });
592
- await (0, auto_mcp_setup_1.autoConfigureMCP)(fraimKey, mcpTokens, options.ide ? [options.ide] : undefined, providerConfigsMap);
291
+ await (0, auto_mcp_setup_1.autoConfigureMCP)(fraimKey, options.ide ? [options.ide] : undefined);
593
292
  }
594
293
  catch (e) {
595
294
  console.log(chalk_1.default.yellow('⚠️ MCP configuration encountered issues'));
@@ -597,7 +296,6 @@ const runSetup = async (options) => {
597
296
  }
598
297
  }
599
298
  else {
600
- // Update existing setup - refresh all IDE MCP configs with new keys
601
299
  console.log(chalk_1.default.blue('\n🔄 Updating IDE MCP configurations...'));
602
300
  try {
603
301
  const { detectInstalledIDEs } = await Promise.resolve().then(() => __importStar(require('../setup/ide-detector')));
@@ -606,18 +304,8 @@ const runSetup = async (options) => {
606
304
  console.log(chalk_1.default.gray(' No IDE configurations found to update'));
607
305
  }
608
306
  else {
609
- // Convert to legacy format for MCP config generator
610
- const mcpTokens = {};
611
- Object.entries(tokens).forEach(([id, token]) => {
612
- mcpTokens[id] = token;
613
- });
614
- // Build providerConfigs map from configs
615
- const providerConfigsMap = {};
616
- Object.entries(configs).forEach(([providerId, config]) => {
617
- providerConfigsMap[providerId] = config;
618
- });
619
307
  const ideNames = installedIDEs.map(ide => ide.name);
620
- await (0, auto_mcp_setup_1.autoConfigureMCP)(fraimKey, mcpTokens, ideNames, providerConfigsMap);
308
+ await (0, auto_mcp_setup_1.autoConfigureMCP)(fraimKey, ideNames);
621
309
  console.log(chalk_1.default.green(`✅ Updated MCP configs for: ${ideNames.join(', ')}`));
622
310
  }
623
311
  }
@@ -709,18 +397,10 @@ const runSetup = async (options) => {
709
397
  console.log(chalk_1.default.white(' cd your-project && fraim init-project'));
710
398
  console.log(chalk_1.default.gray(' This enables project-specific customizations,'));
711
399
  console.log(chalk_1.default.gray(' GitHub workflows, and team learning.'));
712
- const configuredProviders = await Promise.all(Object.keys(tokens).map(async (id) => await (0, provider_registry_1.getProviderDisplayName)(id)));
713
- if (configuredProviders.length > 0) {
714
- console.log(chalk_1.default.gray(`\n Platforms: ${configuredProviders.join(', ')}`));
715
- }
716
- const allProviderIds = await (0, provider_registry_1.getAllProviderIds)();
717
- const unconfiguredProviders = allProviderIds.filter(id => !tokens[id]);
718
- if (unconfiguredProviders.length > 0) {
719
- console.log(chalk_1.default.gray('\n To add more platforms later:'));
720
- unconfiguredProviders.forEach(id => {
721
- console.log(chalk_1.default.gray(` fraim setup --${id}`));
722
- });
723
- }
400
+ console.log(chalk_1.default.cyan('\n To connect platforms (GitHub, GitLab, ADO, Jira):'));
401
+ console.log(chalk_1.default.white(' fraim add-provider <provider>'));
402
+ console.log(chalk_1.default.gray(' Provider tokens are stored directly in IDE MCP configs.'));
403
+ console.log(chalk_1.default.gray(' GitHub uses IDE-native OAuth — no token needed.'));
724
404
  }
725
405
  }
726
406
  else {