Update ConnectAI codebase
This commit is contained in:
@@ -1302,6 +1302,16 @@ export class AgentExecutor {
|
||||
memoryLayers: this._lastRetrievalInfo?.usedMemoryLayers ?? [],
|
||||
note: `continuations=${continuationCount} historyDropped=${reqMessages.length - budgetedHistory.length}`,
|
||||
});
|
||||
// ── Devil Agent (도현) — 비활성 시 silent skip. 활성 시 별도 LLM 호출로 반박 카드 emit. ──
|
||||
// 비동기 — main turn 완료에 영향 없음. 실패해도 main 답변은 보존됨.
|
||||
void this._maybeEmitDevilRebuttal({
|
||||
userPrompt: prompt || '',
|
||||
assistantAnswer: finalAssistantContent,
|
||||
baseUrl: ollamaUrl,
|
||||
modelName: actualModel,
|
||||
contextLength: ctxLimits.contextLength,
|
||||
engine,
|
||||
});
|
||||
} else {
|
||||
this.webview.postMessage({ type: 'streamChunk', value: finalAssistantContent });
|
||||
}
|
||||
@@ -2885,6 +2895,62 @@ export class AgentExecutor {
|
||||
* "lock() request could not be registered" error this method is helping
|
||||
* to avoid.
|
||||
*/
|
||||
/**
|
||||
* Devil Agent 반박 emit — main turn 완료 직후 호출 (fire-and-forget).
|
||||
* 비활성 시 즉시 return. 활성 시 별도 LLM 호출 (callNonStreaming 재사용) 로 짧은 비판 생성.
|
||||
* 성공 시 webview 에 'devilRebuttal' 메시지 전송 → UI 가 카드로 렌더.
|
||||
*/
|
||||
private async _maybeEmitDevilRebuttal(opts: {
|
||||
userPrompt: string;
|
||||
assistantAnswer: string;
|
||||
baseUrl: string;
|
||||
modelName: string;
|
||||
contextLength: number;
|
||||
engine: 'lmstudio' | 'ollama';
|
||||
}): Promise<void> {
|
||||
try {
|
||||
const { isDevilAgentEnabled, generateDevilRebuttal, DEVIL_PERSONA_NAME } =
|
||||
await import('./features/devilAgent');
|
||||
if (!isDevilAgentEnabled()) return;
|
||||
if (!opts.userPrompt.trim() || !opts.assistantAnswer.trim()) return;
|
||||
// Local callLLM wrapper — callNonStreaming 재사용 (cloud / local 자동 라우팅).
|
||||
const callLLM = async (system: string, userMessage: string, maxTokens: number) => {
|
||||
const r = await this.callNonStreaming({
|
||||
baseUrl: opts.baseUrl,
|
||||
modelName: opts.modelName,
|
||||
engine: opts.engine,
|
||||
messages: [
|
||||
{ role: 'system', content: system },
|
||||
{ role: 'user', content: userMessage },
|
||||
],
|
||||
temperature: 0.7,
|
||||
maxTokens,
|
||||
contextLength: opts.contextLength,
|
||||
signal: this.abortController?.signal,
|
||||
});
|
||||
return r.text;
|
||||
};
|
||||
const rebuttal = await generateDevilRebuttal(callLLM, {
|
||||
userPrompt: opts.userPrompt,
|
||||
assistantAnswer: opts.assistantAnswer,
|
||||
});
|
||||
if (!rebuttal) return;
|
||||
this.webview?.postMessage({
|
||||
type: 'devilRebuttal',
|
||||
value: {
|
||||
persona: DEVIL_PERSONA_NAME,
|
||||
text: rebuttal,
|
||||
// 사용자가 '재반박' 누를 때 원래 컨텍스트로 돌아갈 수 있게 stash.
|
||||
userPrompt: opts.userPrompt,
|
||||
assistantAnswer: opts.assistantAnswer,
|
||||
},
|
||||
});
|
||||
} catch (e: any) {
|
||||
// Devil 실패는 main 답변에 영향 없음 — silent log.
|
||||
logInfo('Devil rebuttal skipped.', { error: e?.message ?? String(e) });
|
||||
}
|
||||
}
|
||||
|
||||
private async callNonStreaming(params: {
|
||||
baseUrl: string;
|
||||
modelName: string;
|
||||
|
||||
Reference in New Issue
Block a user