mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-10-26 02:04:37 +08:00
refactor: remove redundant electron/main/ai/compression wrapper
Inline createCompressionLlmAdapter and logger into the sole caller (ipc/ai.ts) and import checkAndCompress/manualCompress directly from @openchatlab/node-runtime. The "old API compatibility" layer was unnecessary since there is only one internal consumer.
This commit is contained in:
1 parent
787e645a60
commit
596eaa3051
2 files changed
+67
-107
No files matched your search
@@ -1,100 +0,0 @@
|
||||
/**
|
||||
* 上下文压缩 — Electron 薄包装
|
||||
*
|
||||
* 实际逻辑已提取到 @openchatlab/node-runtime。
|
||||
* 此处提供与旧 API 兼容的函数签名,注入 Electron 的 LLM adapter 和 logger。
|
||||
*/
|
||||
|
||||
export type { CompressionConfig, CompressionResult } from '@openchatlab/node-runtime'
|
||||
export {
|
||||
checkAndCompress as sharedCheckAndCompress,
|
||||
manualCompress as sharedManualCompress,
|
||||
} from '@openchatlab/node-runtime'
|
||||
import type { CompressionConfig, CompressionResult, CompressionLlmAdapter } from '@openchatlab/node-runtime'
|
||||
import {
|
||||
checkAndCompress as sharedCheckAndCompress,
|
||||
manualCompress as sharedManualCompress,
|
||||
} from '@openchatlab/node-runtime'
|
||||
import { buildPiModel, findModelDefinition } from '../llm'
|
||||
import type { AIServiceConfig } from '../llm/types'
|
||||
import { completeSimple, type PiTextContent } from '@openchatlab/node-runtime'
|
||||
import { aiLogger } from '../logger'
|
||||
import { getManager } from '../conversations'
|
||||
|
||||
const DEFAULT_CONTEXT_WINDOW = 128000
|
||||
|
||||
function createLlmAdapter(activeAIConfig: AIServiceConfig, onCompressing?: () => void): CompressionLlmAdapter {
|
||||
const modelDef = findModelDefinition(activeAIConfig.provider, activeAIConfig.model || '')
|
||||
const contextWindow = modelDef?.contextWindow ?? DEFAULT_CONTEXT_WINDOW
|
||||
const piModel = buildPiModel(activeAIConfig)
|
||||
|
||||
return {
|
||||
contextWindow,
|
||||
compress: async (prompt: string, maxTokens: number) => {
|
||||
onCompressing?.()
|
||||
try {
|
||||
const result = await completeSimple(
|
||||
piModel,
|
||||
{
|
||||
systemPrompt: undefined,
|
||||
messages: [{ role: 'user', content: [{ type: 'text', text: prompt }], timestamp: Date.now() }] as any,
|
||||
},
|
||||
{ apiKey: activeAIConfig.apiKey, maxTokens }
|
||||
)
|
||||
const text = result.content
|
||||
.filter((item): item is PiTextContent => item.type === 'text')
|
||||
.map((item) => item.text)
|
||||
.join('')
|
||||
return text || null
|
||||
} catch (error) {
|
||||
aiLogger.warn('Compression', 'LLM compression attempt failed', { error: String(error) })
|
||||
return null
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const electronLogger = {
|
||||
info: (cat: string, msg: string, extra?: Record<string, unknown>) => aiLogger.info(cat, msg, extra),
|
||||
warn: (cat: string, msg: string, extra?: Record<string, unknown>) => aiLogger.warn(cat, msg, extra),
|
||||
error: (cat: string, msg: string, extra?: Record<string, unknown>) => aiLogger.error(cat, msg, extra),
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容旧 API:检查并执行上下文压缩
|
||||
*/
|
||||
export async function checkAndCompress(
|
||||
conversationId: string,
|
||||
config: CompressionConfig,
|
||||
systemPrompt: string,
|
||||
activeAIConfig: AIServiceConfig,
|
||||
onCompressing?: () => void
|
||||
): Promise<CompressionResult> {
|
||||
return sharedCheckAndCompress(
|
||||
conversationId,
|
||||
config,
|
||||
systemPrompt,
|
||||
createLlmAdapter(activeAIConfig, onCompressing),
|
||||
getManager(),
|
||||
electronLogger
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容旧 API:手动压缩
|
||||
*/
|
||||
export async function manualCompress(
|
||||
conversationId: string,
|
||||
config: CompressionConfig,
|
||||
systemPrompt: string,
|
||||
activeAIConfig: AIServiceConfig
|
||||
): Promise<CompressionResult> {
|
||||
return sharedManualCompress(
|
||||
conversationId,
|
||||
config,
|
||||
systemPrompt,
|
||||
createLlmAdapter(activeAIConfig),
|
||||
getManager(),
|
||||
electronLogger
|
||||
)
|
||||
}
|
||||
+67
-7
@@ -9,19 +9,71 @@ import { serializeError } from '../ai/serialize-error'
|
||||
import { getLogsDir } from '../paths'
|
||||
import { Agent, type AgentStreamChunk, type SkillContext } from '../ai/agent'
|
||||
import { getDefaultGeneralAssistantId } from '../ai/assistant/defaultGeneral'
|
||||
import { getDefaultAssistantConfig, buildPiModel } from '../ai/llm'
|
||||
import { checkAndCompress, manualCompress, type CompressionConfig } from '../ai/compression'
|
||||
import { getDefaultAssistantConfig, buildPiModel, findModelDefinition } from '../ai/llm'
|
||||
import type { AIServiceConfig } from '../ai/llm/types'
|
||||
import { countMessagesTokens } from '../ai/tokenizer'
|
||||
import * as assistantManager from '../ai/assistant'
|
||||
import type { AssistantConfig } from '../ai/assistant/types'
|
||||
import * as skillManager from '../ai/skills'
|
||||
import { completeSimple, streamSimple, type PiMessage, type PiTextContent } from '@openchatlab/node-runtime'
|
||||
import {
|
||||
checkAndCompress,
|
||||
manualCompress,
|
||||
type CompressionConfig,
|
||||
type CompressionLlmAdapter,
|
||||
completeSimple,
|
||||
streamSimple,
|
||||
type PiMessage,
|
||||
type PiTextContent,
|
||||
} from '@openchatlab/node-runtime'
|
||||
import { getManager as getConversationManager } from '../ai/conversations'
|
||||
import { t } from '../i18n'
|
||||
import type { ToolContext } from '../ai/tools/types'
|
||||
import { TOOL_REGISTRY } from '../ai/tools/definitions'
|
||||
import { getDefaultRulesForLocale, mergeRulesForLocale } from '@openchatlab/node-runtime'
|
||||
import type { IpcContext } from './types'
|
||||
|
||||
const DEFAULT_CONTEXT_WINDOW = 128000
|
||||
|
||||
const compressionLogger = {
|
||||
info: (cat: string, msg: string, extra?: Record<string, unknown>) => aiLogger.info(cat, msg, extra),
|
||||
warn: (cat: string, msg: string, extra?: Record<string, unknown>) => aiLogger.warn(cat, msg, extra),
|
||||
error: (cat: string, msg: string, extra?: Record<string, unknown>) => aiLogger.error(cat, msg, extra),
|
||||
}
|
||||
|
||||
function createCompressionLlmAdapter(
|
||||
activeAIConfig: AIServiceConfig,
|
||||
onCompressing?: () => void
|
||||
): CompressionLlmAdapter {
|
||||
const modelDef = findModelDefinition(activeAIConfig.provider, activeAIConfig.model || '')
|
||||
const contextWindow = modelDef?.contextWindow ?? DEFAULT_CONTEXT_WINDOW
|
||||
const piModel = buildPiModel(activeAIConfig)
|
||||
|
||||
return {
|
||||
contextWindow,
|
||||
compress: async (prompt: string, maxTokens: number) => {
|
||||
onCompressing?.()
|
||||
try {
|
||||
const result = await completeSimple(
|
||||
piModel,
|
||||
{
|
||||
systemPrompt: undefined,
|
||||
messages: [{ role: 'user', content: [{ type: 'text', text: prompt }], timestamp: Date.now() }] as any,
|
||||
},
|
||||
{ apiKey: activeAIConfig.apiKey, maxTokens }
|
||||
)
|
||||
const text = result.content
|
||||
.filter((item): item is PiTextContent => item.type === 'text')
|
||||
.map((item) => item.text)
|
||||
.join('')
|
||||
return text || null
|
||||
} catch (error) {
|
||||
aiLogger.warn('Compression', 'LLM compression attempt failed', { error: String(error) })
|
||||
return null
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function toPiSimpleMessages(messages: Array<{ role: string; content: string }>, timestamp: number): PiMessage[] {
|
||||
// pi-ai 的 simple API 在类型上要求完整 Message 联合,这里沿用现有轻量消息格式并集中做兼容转换。
|
||||
return messages.map((message) => ({
|
||||
@@ -1120,8 +1172,7 @@ export function registerAIHandlers({ win }: IpcContext): void {
|
||||
context.conversationId,
|
||||
compressionConfig,
|
||||
systemPromptForCompression,
|
||||
activeAIConfig,
|
||||
() => {
|
||||
createCompressionLlmAdapter(activeAIConfig, () => {
|
||||
win.webContents.send('agent:streamChunk', {
|
||||
requestId,
|
||||
chunk: {
|
||||
@@ -1136,7 +1187,9 @@ export function registerAIHandlers({ win }: IpcContext): void {
|
||||
} satisfies import('@electron/shared/types').AgentRuntimeStatus,
|
||||
},
|
||||
})
|
||||
}
|
||||
}),
|
||||
getConversationManager(),
|
||||
compressionLogger
|
||||
)
|
||||
|
||||
aiLogger.info('IPC', `Compression result for ${requestId}`, compressionResult)
|
||||
@@ -1351,7 +1404,14 @@ export function registerAIHandlers({ win }: IpcContext): void {
|
||||
return { success: false, error: t('llm.notConfigured') }
|
||||
}
|
||||
|
||||
const result = await manualCompress(conversationId, compressionConfig, systemPrompt, activeAIConfig)
|
||||
const result = await manualCompress(
|
||||
conversationId,
|
||||
compressionConfig,
|
||||
systemPrompt,
|
||||
createCompressionLlmAdapter(activeAIConfig),
|
||||
getConversationManager(),
|
||||
compressionLogger
|
||||
)
|
||||
return { success: true, result }
|
||||
} catch (error) {
|
||||
aiLogger.error('IPC', 'Manual compression failed', { error: String(error) })
|
||||
|
||||
Reference in new issue
Block a user