chore: sync connectai

This commit is contained in:
한예성
2026-04-25 12:55:14 +09:00
parent 78a50bd1f9
commit acc6c76a4f
6 changed files with 291 additions and 110 deletions
+76
View File
@@ -24,6 +24,82 @@ export function getConfig() {
};
}
export type EngineKind = 'lmstudio' | 'ollama';
const outputChannel = vscode.window.createOutputChannel('Connect AI');
function timestamp() {
return new Date().toISOString();
}
function stringifyMeta(meta: unknown): string {
if (meta === undefined) return '';
if (typeof meta === 'string') return meta;
if (meta instanceof Error) return `${meta.name}: ${meta.message}\n${meta.stack || ''}`;
try {
return JSON.stringify(meta, null, 2);
} catch {
return String(meta);
}
}
function appendLog(level: 'INFO' | 'WARN' | 'ERROR', message: string, meta?: unknown) {
const suffix = meta === undefined ? '' : `\n${stringifyMeta(meta)}`;
outputChannel.appendLine(`[${timestamp()}] [${level}] ${message}${suffix}`);
}
export function logInfo(message: string, meta?: unknown) {
appendLog('INFO', message, meta);
}
export function logWarn(message: string, meta?: unknown) {
appendLog('WARN', message, meta);
}
export function logError(message: string, meta?: unknown) {
appendLog('ERROR', message, meta);
}
export function normalizeBaseUrl(rawUrl: string): string {
const trimmed = rawUrl.trim().replace(/\/+$/, '');
if (!trimmed) {
return 'http://127.0.0.1:11434';
}
return trimmed;
}
export function resolveEngine(baseUrl: string): EngineKind {
const normalized = normalizeBaseUrl(baseUrl);
try {
const parsed = new URL(normalized);
if (parsed.pathname.endsWith('/v1') || parsed.port === '1234') return 'lmstudio';
if (parsed.pathname.endsWith('/api') || parsed.port === '11434') return 'ollama';
} catch {
if (normalized.includes('/v1') || normalized.includes(':1234')) return 'lmstudio';
}
return 'ollama';
}
export function buildApiUrl(baseUrl: string, engine: EngineKind, endpoint: 'models' | 'chat'): string {
const normalized = normalizeBaseUrl(baseUrl);
if (engine === 'lmstudio') {
if (normalized.endsWith('/v1')) {
return endpoint === 'models' ? `${normalized}/models` : `${normalized}/chat/completions`;
}
return endpoint === 'models' ? `${normalized}/v1/models` : `${normalized}/v1/chat/completions`;
}
if (normalized.endsWith('/api')) {
return endpoint === 'models' ? `${normalized}/tags` : `${normalized}/chat`;
}
return endpoint === 'models' ? `${normalized}/api/tags` : `${normalized}/api/chat`;
}
export function summarizeText(text: string, maxLength: number = 400): string {
const normalized = text.replace(/\s+/g, ' ').trim();
if (normalized.length <= maxLength) return normalized;
return `${normalized.slice(0, maxLength)}...`;
}
export function shouldAutoPushBrain(): boolean {
const cfg = vscode.workspace.getConfiguration('g1nation');
return cfg.get<boolean>('autoPushBrain', false);