scai 0.1.115 → 0.1.117

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.
@@ -11,6 +11,7 @@ import { CONFIG_PATH } from './constants.js';
11
11
  const MODEL_PORT = 11434;
12
12
  const REQUIRED_MODELS = ['llama3:8b'];
13
13
  const OLLAMA_URL = 'https://ollama.com/download';
14
+ const VSCODE_URL = 'https://code.visualstudio.com/download';
14
15
  const isYesMode = process.argv.includes('--yes') || process.env.SCAI_YES === '1';
15
16
  let ollamaChecked = false;
16
17
  let ollamaAvailable = false;
@@ -38,7 +39,7 @@ function promptUser(question, timeout = 20000) {
38
39
  return new Promise((resolve) => {
39
40
  const timer = setTimeout(() => {
40
41
  rl.close();
41
- resolve(''); // treat empty as "continue"
42
+ resolve('');
42
43
  }, timeout);
43
44
  rl.question(question, (answer) => {
44
45
  clearTimeout(timer);
@@ -89,7 +90,7 @@ async function ensureOllamaRunning() {
89
90
  windowsHide: true,
90
91
  });
91
92
  child.unref();
92
- await new Promise((res) => setTimeout(res, 10000)); // give more time
93
+ await new Promise((res) => setTimeout(res, 10000));
93
94
  if (await isOllamaRunning()) {
94
95
  console.log(chalk.green('✅ Ollama started successfully.'));
95
96
  ollamaAvailable = true;
@@ -102,13 +103,11 @@ async function ensureOllamaRunning() {
102
103
  process.exit(1);
103
104
  }
104
105
  }
105
- // Ollama not detected; prompt user but allow continuing
106
106
  console.log(chalk.red('❌ Ollama is not installed or not in PATH.'));
107
107
  console.log(chalk.yellow(`📦 Ollama is required to run local AI models.`));
108
108
  const answer = await promptUser(`🌐 Recommended model: ${REQUIRED_MODELS.join(', ')}\nOpen download page in browser? (y/N): `);
109
- if (answer.toLowerCase() === 'y') {
109
+ if (answer.toLowerCase() === 'y')
110
110
  openBrowser(OLLAMA_URL);
111
- }
112
111
  await promptUser('⏳ Press Enter once Ollama is installed or to continue without it: ');
113
112
  if (await isOllamaRunning()) {
114
113
  console.log(chalk.green('✅ Ollama detected. Continuing...'));
@@ -116,7 +115,7 @@ async function ensureOllamaRunning() {
116
115
  }
117
116
  else {
118
117
  console.log(chalk.yellow('⚠️ Ollama not running. Models will not be available until installed.'));
119
- ollamaAvailable = false; // continue anyway
118
+ ollamaAvailable = false;
120
119
  }
121
120
  }
122
121
  // 🧰 List installed models
@@ -159,9 +158,49 @@ async function ensureModelsDownloaded() {
159
158
  }
160
159
  }
161
160
  }
161
+ // 🌟 Check if VSCode CLI is available
162
+ async function isVSCodeAvailable() {
163
+ try {
164
+ execSync('code --version', { stdio: 'ignore' });
165
+ return true;
166
+ }
167
+ catch {
168
+ return false;
169
+ }
170
+ }
171
+ // ⚡ Ensure VSCode CLI is installed
172
+ async function ensureVSCodeInstalled() {
173
+ if (await isVSCodeAvailable()) {
174
+ console.log(chalk.green('✅ VSCode CLI is available.'));
175
+ return;
176
+ }
177
+ console.log(chalk.red('❌ VSCode CLI not found.'));
178
+ const answer = await promptUser('Do you want to open the VSCode download page? (y/N): ');
179
+ if (answer.toLowerCase() === 'y')
180
+ openBrowser(VSCODE_URL);
181
+ await promptUser('VSCode CLI was not found. If you want to use VSCode features, please install it manually. ' +
182
+ 'Once installed, press Enter to continue. If you prefer to skip VSCode, just press Enter to continue without it: ');
183
+ if (await isVSCodeAvailable()) {
184
+ console.log(chalk.green('✅ VSCode CLI detected. Continuing...'));
185
+ }
186
+ else {
187
+ console.log(chalk.yellow('⚠️ VSCode CLI still not found. Some features may be disabled.'));
188
+ }
189
+ }
162
190
  // 🏁 Main bootstrap logic
163
191
  export async function bootstrap() {
164
192
  await autoInitIfNeeded();
165
193
  await ensureOllamaRunning();
166
194
  await ensureModelsDownloaded();
195
+ await ensureVSCodeInstalled();
196
+ }
197
+ // 🔗 Helper: open file or diff in VSCode
198
+ export function openInVSCode(filePath, options) {
199
+ const args = options?.diffWith ? ['--diff', options.diffWith, filePath] : [filePath];
200
+ try {
201
+ spawn('code', args, { stdio: 'inherit' });
202
+ }
203
+ catch {
204
+ console.log(chalk.red('❌ Failed to launch VSCode CLI. Make sure it is installed and in PATH.'));
205
+ }
167
206
  }
@@ -104,6 +104,26 @@ export const cleanupModule = {
104
104
  break;
105
105
  }
106
106
  }
107
- return { content: jsonLines.join('\n').trim() };
107
+ let finalContent = jsonLines.join('\n').trim();
108
+ // --- VALIDATE JSON ---
109
+ try {
110
+ JSON.parse(finalContent);
111
+ return { content: finalContent };
112
+ }
113
+ catch (err) {
114
+ console.warn(chalk.yellow(`[cleanupModule] Initial JSON.parse failed:`), chalk.red(err instanceof Error ? err.message : err));
115
+ // Attempt simple cleanup: remove trailing commas before } or ]
116
+ finalContent = finalContent.replace(/,\s*([}\]])/g, '$1');
117
+ try {
118
+ JSON.parse(finalContent);
119
+ console.log(chalk.green(`[cleanupModule] Fixed JSON by removing trailing commas.`));
120
+ return { content: finalContent };
121
+ }
122
+ catch (err2) {
123
+ console.error(chalk.red(`[cleanupModule] JSON still invalid after cleanup:`), chalk.yellow(err2 instanceof Error ? err2.message : err2));
124
+ // Return best-effort content even if invalid, so downstream can log/debug
125
+ return { content: finalContent };
126
+ }
127
+ }
108
128
  }
109
129
  };