vibecodingmachine-cli 2026.1.29-713 → 2026.2.20-423

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.
Files changed (45) hide show
  1. package/bin/vibecodingmachine.js +124 -0
  2. package/package.json +3 -2
  3. package/src/commands/agents-check.js +69 -0
  4. package/src/commands/auto-direct.js +930 -145
  5. package/src/commands/auto.js +26 -4
  6. package/src/commands/ide.js +2 -1
  7. package/src/commands/requirements.js +23 -27
  8. package/src/utils/auto-mode.js +4 -1
  9. package/src/utils/cline-js-handler.js +218 -0
  10. package/src/utils/config.js +22 -0
  11. package/src/utils/display-formatters-complete.js +229 -0
  12. package/src/utils/display-formatters-extracted.js +219 -0
  13. package/src/utils/display-formatters.js +157 -0
  14. package/src/utils/feedback-handler.js +143 -0
  15. package/src/utils/ide-detection-complete.js +126 -0
  16. package/src/utils/ide-detection-extracted.js +116 -0
  17. package/src/utils/ide-detection.js +124 -0
  18. package/src/utils/interactive-backup.js +5664 -0
  19. package/src/utils/interactive-broken.js +280 -0
  20. package/src/utils/interactive.js +31 -5534
  21. package/src/utils/provider-checker.js +410 -0
  22. package/src/utils/provider-manager.js +251 -0
  23. package/src/utils/provider-registry.js +18 -9
  24. package/src/utils/requirement-actions.js +884 -0
  25. package/src/utils/requirements-navigator.js +585 -0
  26. package/src/utils/rui-trui-adapter.js +311 -0
  27. package/src/utils/simple-trui.js +204 -0
  28. package/src/utils/status-helpers-extracted.js +125 -0
  29. package/src/utils/status-helpers.js +107 -0
  30. package/src/utils/trui-debug.js +261 -0
  31. package/src/utils/trui-feedback.js +133 -0
  32. package/src/utils/trui-nav-agents.js +119 -0
  33. package/src/utils/trui-nav-requirements.js +268 -0
  34. package/src/utils/trui-nav-settings.js +157 -0
  35. package/src/utils/trui-nav-specifications.js +139 -0
  36. package/src/utils/trui-navigation.js +303 -0
  37. package/src/utils/trui-provider-manager.js +182 -0
  38. package/src/utils/trui-quick-menu.js +365 -0
  39. package/src/utils/trui-req-actions.js +372 -0
  40. package/src/utils/trui-req-tree.js +534 -0
  41. package/src/utils/trui-specifications.js +359 -0
  42. package/src/utils/trui-text-editor.js +350 -0
  43. package/src/utils/trui-windsurf.js +336 -0
  44. package/src/utils/welcome-screen-extracted.js +135 -0
  45. package/src/utils/welcome-screen.js +134 -0
@@ -0,0 +1,229 @@
1
+ const os = require('os');
2
+ const path = require('path');
3
+ const fs = require('fs');
4
+ const { t } = require('vibecodingmachine-core');
5
+
6
+ /**
7
+ * Translate workflow stage names
8
+ * @param {string} stage - Stage name to translate
9
+ * @returns {string} Translated stage name
10
+ */
11
+ function translateStage(stage) {
12
+ const stageMap = {
13
+ 'PREPARE': 'workflow.stage.prepare',
14
+ 'REPRODUCE': 'workflow.stage.reproduce',
15
+ 'CREATE UNIT TEST': 'workflow.stage.create.unit.test',
16
+ 'ACT': 'workflow.stage.act',
17
+ 'CLEAN UP': 'workflow.stage.clean.up',
18
+ 'VERIFY': 'workflow.stage.verify',
19
+ 'RUN UNIT TESTS': 'workflow.stage.run.unit.tests',
20
+ 'DONE': 'workflow.stage.done'
21
+ };
22
+
23
+ const key = stageMap[stage];
24
+ return key ? t(key) : stage;
25
+ }
26
+
27
+ /**
28
+ * Format IDE name for display
29
+ * @param {string} ide - Internal IDE identifier
30
+ * @returns {string} Display name for IDE
31
+ */
32
+ function formatIDEName(ide) {
33
+ const ideNames = {
34
+ 'claude-code': 'Claude Code CLI',
35
+ 'aider': 'Aider CLI',
36
+ 'continue': 'Continue CLI',
37
+ 'cline': 'Cline CLI',
38
+ 'cursor': 'Cursor',
39
+ 'vscode': 'VS Code',
40
+ 'windsurf': 'Windsurf',
41
+ 'kiro': 'AWS Kiro'
42
+ };
43
+ return ideNames[ide] || ide;
44
+ }
45
+
46
+ /**
47
+ * Get current AI provider name for IDEs that require it (like Cline and Continue)
48
+ * @param {string} ide - Internal IDE identifier
49
+ * @returns {string|null} Provider name or null if not applicable/configured
50
+ */
51
+ function getCurrentAIProvider(ide) {
52
+ // Aider, Cline, and Continue require AI provider configuration
53
+ if (ide !== 'aider' && ide !== 'cline' && ide !== 'continue') {
54
+ return null;
55
+ }
56
+
57
+ // Aider uses Ollama by default (or Bedrock if configured)
58
+ if (ide === 'aider') {
59
+ try {
60
+ const { getAutoConfig } = require('./config');
61
+ // Note: getAutoConfig is async, but this function is sync
62
+ // We'll use a sync read for now, or make this function async
63
+ const fs = require('fs');
64
+ const path = require('path');
65
+ const os = require('os');
66
+ const configPath = path.join(os.homedir(), '.config', 'vibecodingmachine', 'config.json');
67
+ if (fs.existsSync(configPath)) {
68
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
69
+ const aiderModel = config.auto?.aiderModel;
70
+ if (aiderModel) {
71
+ return `Ollama (${aiderModel})`;
72
+ }
73
+ }
74
+ return 'Ollama';
75
+ } catch (error) {
76
+ return 'Ollama';
77
+ }
78
+ }
79
+
80
+ // Handle Continue CLI - read from Continue config
81
+ if (ide === 'continue') {
82
+ try {
83
+ const fs = require('fs');
84
+ const path = require('path');
85
+ const os = require('os');
86
+ const yaml = require('js-yaml');
87
+ const configPath = path.join(os.homedir(), '.continue', 'config.yaml');
88
+
89
+ if (!fs.existsSync(configPath)) {
90
+ return 'Not configured';
91
+ }
92
+
93
+ const config = yaml.load(fs.readFileSync(configPath, 'utf8'));
94
+ const models = config.models || [];
95
+
96
+ if (models.length === 0) {
97
+ return 'Not configured';
98
+ }
99
+
100
+ const firstModel = models[0];
101
+ if (firstModel.provider === 'ollama') {
102
+ return `Ollama (${firstModel.model || 'model configured'})`;
103
+ }
104
+
105
+ return firstModel.provider || 'Configured';
106
+ } catch (error) {
107
+ return 'Not configured';
108
+ }
109
+ }
110
+
111
+ try {
112
+ const { ClineCLIManager } = require('vibecodingmachine-core');
113
+ const clineManager = new ClineCLIManager();
114
+
115
+ if (!clineManager.isConfigured()) {
116
+ return 'Not configured';
117
+ }
118
+
119
+ const fs = require('fs');
120
+ const path = require('path');
121
+ const os = require('os');
122
+ const configPath = path.join(os.homedir(), '.cline_cli', 'cline_cli_settings.json');
123
+
124
+ if (!fs.existsSync(configPath)) {
125
+ return 'Not configured';
126
+ }
127
+
128
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
129
+ const apiProvider = config.globalState?.apiProvider;
130
+ const openAiBaseUrl = config.globalState?.openAiBaseUrl;
131
+
132
+ if (!apiProvider) {
133
+ return 'Not configured';
134
+ }
135
+
136
+ // Map provider identifiers to display names
137
+ if (apiProvider === 'anthropic') {
138
+ return 'Anthropic Claude';
139
+ } else if (apiProvider === 'openrouter') {
140
+ return 'OpenRouter';
141
+ } else if (apiProvider === 'openai-native') {
142
+ if (openAiBaseUrl === 'http://localhost:11434/v1') {
143
+ return 'Ollama';
144
+ } else if (openAiBaseUrl?.includes('generativelanguage.googleapis.com')) {
145
+ return 'Google Gemini';
146
+ }
147
+ return 'OpenAI Native';
148
+ }
149
+
150
+ return apiProvider;
151
+ } catch (error) {
152
+ return 'Unknown';
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Get unified agent name (IDE or LLM-based)
158
+ * @param {string} agentType - Agent type (e.g., 'cursor', 'ollama', 'anthropic')
159
+ * @returns {string} - Display name like "Cursor IDE Agent" or "Ollama (qwen2.5-coder:32b)"
160
+ */
161
+ function getAgentDisplayName(agentType) {
162
+ // IDE-based agents
163
+ if (agentType === 'cursor') return 'Cursor IDE Agent';
164
+ if (agentType === 'windsurf') return 'Windsurf IDE Agent';
165
+ if (agentType === 'antigravity') return 'Google Antigravity IDE Agent';
166
+ if (agentType === 'kiro') return 'AWS Kiro AI IDE Agent';
167
+ if (agentType === 'vscode') return 'VS Code IDE Agent';
168
+
169
+ // Claude Code CLI
170
+ if (agentType === 'claude-code') return 'Claude Code CLI';
171
+
172
+ // Direct LLM agents
173
+ if (agentType === 'ollama' || agentType === 'anthropic' || agentType === 'groq' || agentType === 'bedrock') {
174
+ try {
175
+ const fs = require('fs');
176
+ const path = require('path');
177
+ const os = require('os');
178
+ const configPath = path.join(os.homedir(), '.config', 'vibecodingmachine', 'config.json');
179
+ if (fs.existsSync(configPath)) {
180
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
181
+ const model = config.auto?.llmModel || config.auto?.aiderModel || config.auto?.groqModel;
182
+
183
+ if (agentType === 'ollama' && model && !model.includes('groq/')) {
184
+ return `Ollama (${model})`;
185
+ } else if (agentType === 'anthropic') {
186
+ return 'Anthropic (Claude Sonnet 4)';
187
+ } else if (agentType === 'groq') {
188
+ // Extract model name from groq/model format
189
+ const groqModel = model && model.includes('groq/') ? model.split('/')[1] : 'llama-3.3-70b-versatile';
190
+ return `Groq (${groqModel})`;
191
+ } else if (agentType === 'bedrock') {
192
+ return 'AWS Bedrock (Claude)';
193
+ }
194
+ }
195
+ } catch (error) {
196
+ // Fallback to generic names
197
+ }
198
+
199
+ // Fallback names
200
+ if (agentType === 'ollama') return 'Ollama (Local)';
201
+ if (agentType === 'anthropic') return 'Anthropic (Claude)';
202
+ if (agentType === 'groq') return 'Groq (llama-3.3-70b-versatile)';
203
+ if (agentType === 'bedrock') return 'AWS Bedrock';
204
+ }
205
+
206
+ // Legacy support for old IDE names
207
+ return formatIDEName(agentType);
208
+ }
209
+
210
+ /**
211
+ * Format file path for display (shorten home directory)
212
+ * @param {string} fullPath - Full path to format
213
+ * @returns {string} Formatted path
214
+ */
215
+ function formatPath(fullPath) {
216
+ const homeDir = os.homedir();
217
+ if (fullPath.startsWith(homeDir)) {
218
+ return fullPath.replace(homeDir, '~');
219
+ }
220
+ return fullPath;
221
+ }
222
+
223
+ module.exports = {
224
+ translateStage,
225
+ formatIDEName,
226
+ getAgentDisplayName,
227
+ getCurrentAIProvider,
228
+ formatPath
229
+ };
@@ -0,0 +1,219 @@
1
+ const os = require('os');
2
+ const path = require('path');
3
+ const fs = require('fs');
4
+ const { t } = require('vibecodingmachine-core');
5
+
6
+ function translateStage(stage) {
7
+ const stageMap = {
8
+ 'PREPARE': 'workflow.stage.prepare',
9
+ 'REPRODUCE': 'workflow.stage.reproduce',
10
+ 'CREATE UNIT TEST': 'workflow.stage.create.unit.test',
11
+ 'ACT': 'workflow.stage.act',
12
+ 'CLEAN UP': 'workflow.stage.clean.up',
13
+ 'VERIFY': 'workflow.stage.verify',
14
+ 'RUN UNIT TESTS': 'workflow.stage.run.unit.tests',
15
+ 'DONE': 'workflow.stage.done'
16
+ };
17
+
18
+ const key = stageMap[stage];
19
+ return key ? t(key) : stage;
20
+ }
21
+
22
+ /**
23
+ * Format IDE name for display
24
+ * @param {string} ide - Internal IDE identifier
25
+ * @returns {string} Display name for IDE
26
+ */
27
+ function formatIDEName(ide) {
28
+ const ideNames = {
29
+ 'claude-code': 'Claude Code CLI',
30
+ 'aider': 'Aider CLI',
31
+ 'continue': 'Continue CLI',
32
+ 'cline': 'Cline CLI',
33
+ 'cursor': 'Cursor',
34
+ 'vscode': 'VS Code',
35
+ 'windsurf': 'Windsurf',
36
+ 'kiro': 'AWS Kiro'
37
+ };
38
+ return ideNames[ide] || ide;
39
+ }
40
+
41
+ /**
42
+ * Get current AI provider name for IDEs that require it (like Cline and Continue)
43
+ * @param {string} ide - Internal IDE identifier
44
+ * @returns {string|null} Provider name or null if not applicable/configured
45
+ */
46
+ /**
47
+ * Get unified agent name (IDE or LLM-based)
48
+ * @param {string} agentType - Agent type (e.g., 'cursor', 'ollama', 'anthropic')
49
+ * @returns {string} - Display name like "Cursor IDE Agent" or "Ollama (qwen2.5-coder:32b)"
50
+ */
51
+ function getAgentDisplayName(agentType) {
52
+ // IDE-based agents
53
+ if (agentType === 'cursor') return 'Cursor IDE Agent';
54
+ if (agentType === 'windsurf') return 'Windsurf IDE Agent';
55
+ if (agentType === 'antigravity') return 'Google Antigravity IDE Agent';
56
+ if (agentType === 'kiro') return 'AWS Kiro AI IDE Agent';
57
+ if (agentType === 'vscode') return 'VS Code IDE Agent';
58
+
59
+ // Claude Code CLI
60
+ if (agentType === 'claude-code') return 'Claude Code CLI';
61
+
62
+ // Direct LLM agents
63
+ if (agentType === 'ollama' || agentType === 'anthropic' || agentType === 'groq' || agentType === 'bedrock') {
64
+ try {
65
+ const fs = require('fs');
66
+ const path = require('path');
67
+ const os = require('os');
68
+ const configPath = path.join(os.homedir(), '.config', 'vibecodingmachine', 'config.json');
69
+ if (fs.existsSync(configPath)) {
70
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
71
+ const model = config.auto?.llmModel || config.auto?.aiderModel || config.auto?.groqModel;
72
+
73
+ if (agentType === 'ollama' && model && !model.includes('groq/')) {
74
+ return `Ollama (${model})`;
75
+ } else if (agentType === 'anthropic') {
76
+ return 'Anthropic (Claude Sonnet 4)';
77
+ } else if (agentType === 'groq') {
78
+ // Extract model name from groq/model format
79
+ const groqModel = model && model.includes('groq/') ? model.split('/')[1] : 'llama-3.3-70b-versatile';
80
+ return `Groq (${groqModel})`;
81
+ } else if (agentType === 'bedrock') {
82
+ return 'AWS Bedrock (Claude)';
83
+ }
84
+ }
85
+ } catch (error) {
86
+ // Fallback to generic names
87
+ }
88
+
89
+ // Fallback names
90
+ if (agentType === 'ollama') return 'Ollama (Local)';
91
+ if (agentType === 'anthropic') return 'Anthropic (Claude)';
92
+ if (agentType === 'groq') return 'Groq (llama-3.3-70b-versatile)';
93
+ if (agentType === 'bedrock') return 'AWS Bedrock';
94
+ }
95
+
96
+ // Legacy support for old IDE names
97
+ return formatIDEName(agentType);
98
+ }
99
+
100
+ function getCurrentAIProvider(ide) {
101
+ // Aider, Cline, and Continue require AI provider configuration
102
+ if (ide !== 'aider' && ide !== 'cline' && ide !== 'continue') {
103
+ return null;
104
+ }
105
+
106
+ // Aider uses Ollama by default (or Bedrock if configured)
107
+ if (ide === 'aider') {
108
+ try {
109
+ const { getAutoConfig } = require('./config');
110
+ // Note: getAutoConfig is async, but this function is sync
111
+ // We'll use a sync read for now, or make this function async
112
+ const fs = require('fs');
113
+ const path = require('path');
114
+ const os = require('os');
115
+ const configPath = path.join(os.homedir(), '.config', 'vibecodingmachine', 'config.json');
116
+ if (fs.existsSync(configPath)) {
117
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
118
+ const aiderModel = config.auto?.aiderModel;
119
+ if (aiderModel) {
120
+ return `Ollama (${aiderModel})`;
121
+ }
122
+ }
123
+ return 'Ollama';
124
+ } catch (error) {
125
+ return 'Ollama';
126
+ }
127
+ }
128
+
129
+ // Handle Continue CLI - read from Continue config
130
+ if (ide === 'continue') {
131
+ try {
132
+ const fs = require('fs');
133
+ const path = require('path');
134
+ const os = require('os');
135
+ const yaml = require('js-yaml');
136
+ const configPath = path.join(os.homedir(), '.continue', 'config.yaml');
137
+
138
+ if (!fs.existsSync(configPath)) {
139
+ return 'Not configured';
140
+ }
141
+
142
+ const config = yaml.load(fs.readFileSync(configPath, 'utf8'));
143
+ const models = config.models || [];
144
+
145
+ if (models.length === 0) {
146
+ return 'Not configured';
147
+ }
148
+
149
+ const firstModel = models[0];
150
+ if (firstModel.provider === 'ollama') {
151
+ return `Ollama (${firstModel.model || 'model configured'})`;
152
+ }
153
+
154
+ return firstModel.provider || 'Configured';
155
+ } catch (error) {
156
+ return 'Not configured';
157
+ }
158
+ }
159
+
160
+ try {
161
+ const { ClineCLIManager } = require('vibecodingmachine-core');
162
+ const clineManager = new ClineCLIManager();
163
+
164
+ if (!clineManager.isConfigured()) {
165
+ return 'Not configured';
166
+ }
167
+
168
+ const fs = require('fs');
169
+ const path = require('path');
170
+ const os = require('os');
171
+ const configPath = path.join(os.homedir(), '.cline_cli', 'cline_cli_settings.json');
172
+
173
+ if (!fs.existsSync(configPath)) {
174
+ return 'Not configured';
175
+ }
176
+
177
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
178
+ const apiProvider = config.globalState?.apiProvider;
179
+ const openAiBaseUrl = config.globalState?.openAiBaseUrl;
180
+
181
+ if (!apiProvider) {
182
+ return 'Not configured';
183
+ }
184
+
185
+ // Map provider identifiers to display names
186
+ if (apiProvider === 'anthropic') {
187
+ return 'Anthropic Claude';
188
+ } else if (apiProvider === 'openrouter') {
189
+ return 'OpenRouter';
190
+ } else if (apiProvider === 'openai-native') {
191
+ if (openAiBaseUrl === 'http://localhost:11434/v1') {
192
+ return 'Ollama';
193
+ } else if (openAiBaseUrl?.includes('generativelanguage.googleapis.com')) {
194
+ return 'Google Gemini';
195
+ }
196
+ return 'OpenAI Native';
197
+ }
198
+
199
+ return apiProvider;
200
+ } catch (error) {
201
+ return 'Unknown';
202
+ }
203
+ }
204
+
205
+ function formatPath(fullPath) {
206
+ const homeDir = os.homedir();
207
+ if (fullPath.startsWith(homeDir)) {
208
+ return fullPath.replace(homeDir, '~');
209
+ }
210
+ return fullPath;
211
+ }
212
+
213
+ module.exports = {
214
+ translateStage,
215
+ formatIDEName,
216
+ getAgentDisplayName,
217
+ getCurrentAIProvider,
218
+ formatPath
219
+ };
@@ -0,0 +1,157 @@
1
+ const os = require('os');
2
+ const path = require('path');
3
+ const fs = require('fs');
4
+ const { t } = require('vibecodingmachine-core');
5
+
6
+ /**
7
+ * Translate workflow stage names
8
+ * @param {string} stage - Stage name to translate
9
+ * @returns {string} Translated stage name
10
+ */
11
+ function translateStage(stage) {
12
+ const stageMap = {
13
+ 'PREPARE': 'workflow.stage.prepare',
14
+ 'REPRODUCE': 'workflow.stage.reproduce',
15
+ 'CREATE UNIT TEST': 'workflow.stage.create.unit.test',
16
+ 'ACT': 'workflow.stage.act',
17
+ 'CLEAN UP': 'workflow.stage.clean.up',
18
+ 'VERIFY': 'workflow.stage.verify',
19
+ 'RUN UNIT TESTS': 'workflow.stage.run.unit.tests',
20
+ 'DONE': 'workflow.stage.done'
21
+ };
22
+
23
+ const key = stageMap[stage];
24
+ return key ? t(key) : stage;
25
+ }
26
+
27
+ /**
28
+ * Format IDE name for display
29
+ * @param {string} ide - Internal IDE identifier
30
+ * @returns {string} Display name for IDE
31
+ */
32
+ function formatIDEName(ide) {
33
+ const ideNames = {
34
+ 'claude-code': 'Claude Code CLI',
35
+ 'aider': 'Aider CLI',
36
+ 'continue': 'Continue CLI',
37
+ 'cline': 'Cline CLI',
38
+ 'cursor': 'Cursor',
39
+ 'vscode': 'VS Code',
40
+ 'windsurf': 'Windsurf',
41
+ 'kiro': 'AWS Kiro'
42
+ };
43
+ return ideNames[ide] || ide;
44
+ }
45
+
46
+ /**
47
+ * Get unified agent name (IDE or LLM-based)
48
+ * @param {string} agentType - Agent type (e.g., 'cursor', 'ollama', 'anthropic')
49
+ * @returns {string} - Display name like "Cursor IDE Agent" or "Ollama (qwen2.5-coder:32b)"
50
+ */
51
+ function getAgentDisplayName(agentType) {
52
+ // IDE-based agents
53
+ if (agentType === 'cursor') return 'Cursor IDE Agent';
54
+ if (agentType === 'windsurf') return 'Windsurf IDE Agent';
55
+ if (agentType === 'antigravity') return 'Google Antigravity IDE Agent';
56
+ if (agentType === 'kiro') return 'AWS Kiro AI IDE Agent';
57
+ if (agentType === 'vscode') return 'VS Code IDE Agent';
58
+
59
+ // Claude Code CLI
60
+ if (agentType === 'claude-code') return 'Claude Code CLI';
61
+
62
+ // Direct LLM agents
63
+ if (agentType === 'ollama' || agentType === 'anthropic' || agentType === 'groq' || agentType === 'bedrock') {
64
+ try {
65
+ const configPath = path.join(os.homedir(), '.config', 'vibecodingmachine', 'config.json');
66
+ if (fs.existsSync(configPath)) {
67
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
68
+ const model = config.auto?.llmModel || config.auto?.aiderModel || config.auto?.groqModel;
69
+
70
+ if (agentType === 'ollama' && model && !model.includes('groq/')) {
71
+ return `Ollama (${model})`;
72
+ } else if (agentType === 'anthropic') {
73
+ return 'Anthropic (Claude Sonnet 4)';
74
+ } else if (agentType === 'groq') {
75
+ // Extract model name from groq/model format
76
+ const groqModel = model && model.includes('groq/') ? model.split('/')[1] : 'llama-3.3-70b-versatile';
77
+ return `Groq (${groqModel})`;
78
+ } else if (agentType === 'bedrock') {
79
+ return 'AWS Bedrock (Claude)';
80
+ }
81
+ }
82
+ } catch (error) {
83
+ // Fallback to generic names
84
+ }
85
+
86
+ // Fallback names
87
+ if (agentType === 'ollama') return 'Ollama (Local)';
88
+ if (agentType === 'anthropic') return 'Anthropic (Claude)';
89
+ if (agentType === 'groq') return 'Groq (llama-3.3-70b-versatile)';
90
+ if (agentType === 'bedrock') return 'AWS Bedrock';
91
+ }
92
+
93
+ // Legacy support for old IDE names
94
+ return formatIDEName(agentType);
95
+ }
96
+
97
+ /**
98
+ * Get current AI provider name for IDEs that require it (like Cline and Continue)
99
+ * @param {string} ide - Internal IDE identifier
100
+ * @returns {string|null} Provider name or null if not applicable/configured
101
+ */
102
+ function getCurrentAIProvider(ide) {
103
+ // Aider, Cline, and Continue require AI provider configuration
104
+ if (ide !== 'aider' && ide !== 'cline' && ide !== 'continue') {
105
+ return null;
106
+ }
107
+
108
+ // Aider uses Ollama by default (or Bedrock if configured)
109
+ if (ide === 'aider') {
110
+ try {
111
+ const configPath = path.join(os.homedir(), '.config', 'vibecodingmachine', 'config.json');
112
+ if (fs.existsSync(configPath)) {
113
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
114
+ const provider = config.auto?.provider || 'ollama';
115
+ return provider.charAt(0).toUpperCase() + provider.slice(1);
116
+ }
117
+ } catch (error) {
118
+ return 'Ollama';
119
+ }
120
+ return 'Ollama';
121
+ }
122
+
123
+ // For Cline and Continue, check their respective configs
124
+ if (ide === 'cline' || ide === 'continue') {
125
+ try {
126
+ // This would need to read from the IDE's specific config files
127
+ // For now, return a generic placeholder
128
+ const provider = ide === 'cline' ? 'OpenAI' : 'Anthropic';
129
+ return provider;
130
+ } catch (error) {
131
+ return 'Unknown';
132
+ }
133
+ }
134
+
135
+ return null;
136
+ }
137
+
138
+ /**
139
+ * Format file path for display (shorten home directory)
140
+ * @param {string} fullPath - Full path to format
141
+ * @returns {string} Formatted path
142
+ */
143
+ function formatPath(fullPath) {
144
+ const homeDir = os.homedir();
145
+ if (fullPath.startsWith(homeDir)) {
146
+ return fullPath.replace(homeDir, '~');
147
+ }
148
+ return fullPath;
149
+ }
150
+
151
+ module.exports = {
152
+ translateStage,
153
+ formatIDEName,
154
+ getAgentDisplayName,
155
+ getCurrentAIProvider,
156
+ formatPath
157
+ };