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
+56 -19
View File
@@ -2,7 +2,17 @@ import * as http from 'http';
import * as fs from 'fs';
import * as path from 'path';
// axios removed
import { getConfig, _getBrainDir, _isBrainDirExplicitlySet, findBrainFiles } from './utils';
import {
getConfig,
_getBrainDir,
_isBrainDirExplicitlySet,
findBrainFiles,
buildApiUrl,
logError,
logInfo,
resolveEngine,
summarizeText
} from './utils';
export interface BridgeInterface {
injectSystemMessage(msg: string): void;
@@ -48,7 +58,7 @@ export class BridgeServer {
});
this.server.listen(port, '127.0.0.1', () => {
console.log(`[G1nation] Bridge Server active on port ${port}`);
logInfo(`Bridge server active on 127.0.0.1:${port}.`);
});
}
@@ -72,6 +82,7 @@ export class BridgeServer {
const parsed = JSON.parse(body);
await processor(parsed, res);
} catch (e: any) {
logError('Bridge request failed.', { url: req.url, method: req.method, body: summarizeText(body), error: e?.message || String(e) });
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: e.message }));
}
@@ -145,27 +156,53 @@ export class BridgeServer {
private async callAI(prompt: string): Promise<string> {
const config = getConfig();
const isLMStudio = config.ollamaUrl.includes('1234') || config.ollamaUrl.includes('v1');
const apiUrl = isLMStudio ? `${config.ollamaUrl}/v1/chat/completions` : `${config.ollamaUrl}/api/chat`;
const primaryEngine = resolveEngine(config.ollamaUrl);
const engines = primaryEngine === 'lmstudio' ? ['lmstudio', 'ollama'] as const : ['ollama', 'lmstudio'] as const;
let lastError: Error | null = null;
const payload = {
model: config.defaultModel,
messages: [{ role: 'user', content: prompt }],
stream: false
};
for (const engine of engines) {
const apiUrl = buildApiUrl(config.ollamaUrl, engine, 'chat');
const payload = engine === 'lmstudio'
? {
model: config.defaultModel,
messages: [{ role: 'user', content: prompt }],
stream: false
}
: {
model: config.defaultModel,
messages: [{ role: 'user', content: prompt }],
stream: false
};
const res = await fetch(apiUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
signal: AbortSignal.timeout(config.timeout)
});
try {
logInfo('Bridge AI request started.', { engine, apiUrl, model: config.defaultModel });
const res = await fetch(apiUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
signal: AbortSignal.timeout(config.timeout)
});
if (!res.ok) {
throw new Error(`Bridge AI call failed: ${res.status}`);
const rawText = await res.text();
if (!res.ok) {
lastError = new Error(`Bridge AI call failed: ${res.status} ${summarizeText(rawText, 250)}`);
logError('Bridge AI request returned non-OK status.', { engine, apiUrl, status: res.status, body: summarizeText(rawText, 500) });
continue;
}
const data = rawText ? JSON.parse(rawText) as any : {};
const content = engine === 'lmstudio'
? (data.choices?.[0]?.message?.content || '')
: (data.message?.content || data.response || '');
logInfo('Bridge AI request succeeded.', { engine, apiUrl, responsePreview: summarizeText(content, 200) });
return content;
} catch (error: any) {
lastError = error instanceof Error ? error : new Error(String(error));
logError('Bridge AI request failed.', { engine, apiUrl, error: lastError.message });
}
}
const data = await res.json() as any;
return isLMStudio ? (data.choices?.[0]?.message?.content || '') : (data.message?.content || '');
throw lastError || new Error('Bridge AI call failed.');
}
}