Files
connectai/src/extension.ts
T

160 lines
5.6 KiB
TypeScript

import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
// axios removed in favor of native fetch
import {
_getBrainDir,
_isBrainDirExplicitlySet,
findBrainFiles,
SYSTEM_PROMPT,
buildApiUrl,
logError,
logInfo
} from './utils';
import { getConfig, validateConfig } from './config';
import { AgentExecutor } from './agent';
import { BridgeServer } from './bridge';
import { SidebarChatProvider } from './sidebarProvider';
import { HealthCheckMonitor } from './core/health';
import { initAstraPathResolver } from './core/astraPath';
/**
* Astra Extension Entry Point
*/
export async function activate(context: vscode.ExtensionContext) {
logInfo('Astra activating...');
// Initialize Astra Path Resolver (.astra → ConnectAI/.astra/)
initAstraPathResolver(context);
// Start Environment Health Monitoring
HealthCheckMonitor.runAllChecks();
HealthCheckMonitor.startInterval(600000); // Check every 10 mins
// 0. Validate Configuration
const validation = validateConfig();
if (!validation.valid) {
vscode.window.showErrorMessage(`Astra Configuration Error: ${validation.errors.join(' ')}`);
logError('Configuration validation failed.', { errors: validation.errors });
}
// 1. Ensure Brain Directory
await _ensureBrainDir(context);
// 2. Initialize Agent Executor
const agent = new AgentExecutor(context);
// 3. Initialize Sidebar Provider
const provider = new SidebarChatProvider(context.extensionUri, context, agent);
context.subscriptions.push(
vscode.window.registerWebviewViewProvider(SidebarChatProvider.viewType, provider)
);
// 4. Initialize Bridge Server (Port 4825)
const bridge = new BridgeServer(provider);
try {
bridge.start();
logInfo('Bridge server started on port 4825.');
} catch (err) {
logError('Failed to start bridge server.', err);
}
// 5. Register Core Commands
context.subscriptions.push(
vscode.commands.registerCommand('g1nation.focusInput', () => {
provider.focusInput();
})
);
context.subscriptions.push(
vscode.commands.registerCommand('g1nation.clearChat', () => {
provider.clearChat();
})
);
context.subscriptions.push(
vscode.commands.registerCommand('g1nation.syncBrain', async () => {
await provider.syncBrain();
})
);
// 6. Run Initial Setup (Automatic Model/Engine Detection)
const setupComplete = context.globalState.get<boolean>('setupComplete', false);
if (!setupComplete) {
await runInitialSetup(context);
}
}
export function deactivate() {}
async function runInitialSetup(context: vscode.ExtensionContext) {
try {
let engineName = '';
let modelName = '';
try {
const res = await fetch(buildApiUrl('http://127.0.0.1:1234', 'lmstudio', 'models'), { signal: AbortSignal.timeout(2000) });
const data = await res.json() as any;
if (data?.data?.length > 0) {
engineName = 'LM Studio';
modelName = data.data[0].id;
await vscode.workspace.getConfiguration('g1nation').update('ollamaUrl', 'http://127.0.0.1:1234', vscode.ConfigurationTarget.Global);
await vscode.workspace.getConfiguration('g1nation').update('defaultModel', modelName, vscode.ConfigurationTarget.Global);
logInfo('Initial setup detected LM Studio.', { modelName });
}
} catch (err) {
logInfo('Initial setup could not reach LM Studio.', err);
}
if (!engineName) {
try {
const res = await fetch('http://127.0.0.1:11434/api/tags', { signal: AbortSignal.timeout(2000) });
const data = await res.json() as any;
if (data?.models?.length > 0) {
engineName = 'Ollama';
modelName = data.models[0].name;
await vscode.workspace.getConfiguration('g1nation').update('ollamaUrl', 'http://127.0.0.1:11434', vscode.ConfigurationTarget.Global);
await vscode.workspace.getConfiguration('g1nation').update('defaultModel', modelName, vscode.ConfigurationTarget.Global);
logInfo('Initial setup detected Ollama.', { modelName });
}
} catch (err) {
logInfo('Initial setup could not reach Ollama.', err);
}
}
context.globalState.update('setupComplete', true);
if (engineName) {
vscode.window.showInformationMessage(`Setup Complete: ${engineName} detected with model ${modelName}`);
}
} catch (e) {
logError('Initial setup failed.', e);
context.globalState.update('setupComplete', true);
}
}
async function _ensureBrainDir(context: vscode.ExtensionContext): Promise<string | null> {
if (_isBrainDirExplicitlySet()) {
const dir = _getBrainDir();
if (!fs.existsSync(dir)) {
try {
fs.mkdirSync(dir, { recursive: true });
} catch (e) {}
}
return dir;
}
const defaultDir = _getBrainDir();
if (!fs.existsSync(defaultDir)) {
try {
fs.mkdirSync(defaultDir, { recursive: true });
// Create a welcome file
fs.writeFileSync(path.join(defaultDir, 'Welcome.md'), "# Welcome to your Second Brain\n\nAstra will store and retrieve knowledge from here.");
} catch (e) {}
}
return defaultDir;
}
/**
* Astra Extension Entry Point
*/