refactor[Logger]: replace console logging with logger service (#8271)

* refactor: replace console logging with logger service across multiple components

- Updated various files to utilize the logger service instead of console.log for improved logging consistency and error tracking.
- Enhanced logging levels to better categorize messages, including debug and error levels.
- Refactored logging in components such as ApiClientFactory, KnowledgeService, and MemoryProcessor to align with the new logging standards.

* refactor: update logging level in App component from error to info

- Changed the logging level in the App component to provide a more appropriate context for initialization messages, enhancing clarity in the logging output.

* refactor(logging): replace console.log with logger service in middleware and update ESLint comments

- Updated the logging implementation in the createSimpleLoggingMiddleware function to use logger.debug and logger.error instead of console.log and console.error for improved logging consistency.
- Added eslint-disable comments for restricted syntax in preload and useAppInit hooks to suppress warnings.
This commit is contained in:
fullex 2025-07-18 16:01:03 +08:00 committed by GitHub
parent f9c5ca258a
commit 7764ffc8bb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 118 additions and 75 deletions

View File

@ -80,7 +80,6 @@ import { ChunkType } from '@renderer/types' // 调整路径
export const createSimpleLoggingMiddleware = (): CompletionsMiddleware => {
return (api: MiddlewareAPI<AiProviderMiddlewareCompletionsContext, [CompletionsParams]>) => {
// console.log(`[LoggingMiddleware] Initialized for provider: ${api.getProviderId()}`);
return (next: (context: AiProviderMiddlewareCompletionsContext, params: CompletionsParams) => Promise<any>) => {
return async (context: AiProviderMiddlewareCompletionsContext, params: CompletionsParams): Promise<void> => {
@ -88,7 +87,7 @@ export const createSimpleLoggingMiddleware = (): CompletionsMiddleware => {
// 从 context 中获取 onChunk (它最初来自 params.onChunk)
const onChunk = context.onChunk
console.log(
logger.debug(
`[LoggingMiddleware] Request for ${context.methodName} with params:`,
params.messages?.[params.messages.length - 1]?.content
)
@ -104,14 +103,14 @@ export const createSimpleLoggingMiddleware = (): CompletionsMiddleware => {
// 如果在之前,那么它需要自己处理 rawSdkResponse 或确保下游会处理。
const duration = Date.now() - startTime
console.log(`[LoggingMiddleware] Request for ${context.methodName} completed in ${duration}ms.`)
logger.debug(`[LoggingMiddleware] Request for ${context.methodName} completed in ${duration}ms.`)
// 假设下游已经通过 onChunk 发送了所有数据。
// 如果这个中间件是链的末端,并且需要确保 BLOCK_COMPLETE 被发送,
// 它可能需要更复杂的逻辑来跟踪何时所有数据都已发送。
} catch (error) {
const duration = Date.now() - startTime
console.error(`[LoggingMiddleware] Request for ${context.methodName} failed after ${duration}ms:`, error)
logger.error(`[LoggingMiddleware] Request for ${context.methodName} failed after ${duration}ms:`, error)
// 如果 onChunk 可用,可以尝试发送一个错误块
if (onChunk) {
@ -207,7 +206,7 @@ export default middlewareConfig
### 调试技巧
- 在中间件的关键点使用 `console.log` 或调试器来检查 `params`、`context` 的状态以及 `next` 的返回值。
- 在中间件的关键点使用 `logger.debug` 或调试器来检查 `params`、`context` 的状态以及 `next` 的返回值。
- 暂时简化中间件链,只保留你正在调试的中间件和最简单的核心逻辑,以隔离问题。
- 编写单元测试来独立验证每个中间件的行为。

View File

@ -129,8 +129,8 @@ if (!app.requestSingleInstanceLock()) {
if (isDev) {
installExtension([REDUX_DEVTOOLS, REACT_DEVELOPER_TOOLS])
.then((name) => console.log(`Added Extension: ${name}`))
.catch((err) => console.log('An error occurred: ', err))
.then((name) => logger.info(`Added Extension: ${name}`))
.catch((err) => logger.error('An error occurred: ', err))
}
//start selection assistant service

View File

@ -205,9 +205,9 @@ export default class MineruPreprocessProvider extends BasePreprocessProvider {
try {
// 步骤1: 获取上传URL
const { batchId, fileUrls } = await this.getBatchUploadUrls(file)
logger.info(`Got upload URLs for batch: ${batchId}`)
logger.debug(`Got upload URLs for batch: ${batchId}`)
console.log('batchId:', batchId, 'fileurls:', fileUrls)
logger.debug(`batchId: ${batchId}, fileurls: ${fileUrls}`)
// 步骤2: 上传文件到获取的URL
await this.putFileToUrl(file.path, fileUrls[0])
logger.info(`File uploaded successfully: ${file.path}`)

View File

@ -57,7 +57,7 @@ class FileStorage {
findDuplicateFile = async (filePath: string): Promise<FileMetadata | null> => {
const stats = fs.statSync(filePath)
console.log('stats', stats, filePath)
logger.debug('stats', stats, filePath)
const fileSize = stats.size
const files = await fs.promises.readdir(this.storageDir)

View File

@ -156,7 +156,7 @@ class KnowledgeService {
}
public delete = async (_: Electron.IpcMainInvokeEvent, id: string): Promise<void> => {
console.log('id', id)
logger.debug('delete id', id)
const dbPath = path.join(this.storageDir, id)
if (fs.existsSync(dbPath)) {
fs.rmSync(dbPath, { recursive: true })

View File

@ -622,7 +622,7 @@ class McpService {
const client = await this.initClient(server)
const result = await client.callTool({ name, arguments: args }, undefined, {
onprogress: (process) => {
console.log('[MCP] Progress:', process.progress / (process.total || 1))
logger.debug(`Progress: ${process.progress / (process.total || 1)}`)
window.api.mcp.setProgress(process.progress / (process.total || 1))
},
timeout: server.timeout ? server.timeout * 1000 : 60000, // Default timeout of 1 minute

View File

@ -364,6 +364,7 @@ if (process.contextIsolated) {
getFiles: (vaultName: string) => ipcRenderer.invoke(IpcChannel.Obsidian_GetFiles, vaultName)
})
} catch (error) {
// eslint-disable-next-line no-restricted-syntax
console.error(error)
}
} else {

View File

@ -26,7 +26,7 @@ import TranslatePage from './pages/translate/TranslatePage'
const logger = loggerService.withContext('App.tsx')
function App(): React.ReactElement {
logger.error('App initialized')
logger.info('App initialized')
return (
<Provider store={store}>

View File

@ -1,3 +1,4 @@
import { loggerService } from '@logger'
import { Provider } from '@renderer/types'
import { AihubmixAPIClient } from './AihubmixAPIClient'
@ -10,6 +11,8 @@ import { OpenAIAPIClient } from './openai/OpenAIApiClient'
import { OpenAIResponseAPIClient } from './openai/OpenAIResponseAPIClient'
import { PPIOAPIClient } from './ppio/PPIOAPIClient'
const logger = loggerService.withContext('ApiClientFactory')
/**
* Factory for creating ApiClient instances based on provider configuration
* ApiClient实例的工厂
@ -20,7 +23,7 @@ export class ApiClientFactory {
* ApiClient实例
*/
static create(provider: Provider): BaseApiClient {
console.log(`[ApiClientFactory] Creating ApiClient for provider:`, {
logger.debug(`Creating ApiClient for provider:`, {
id: provider.id,
type: provider.type
})
@ -29,17 +32,17 @@ export class ApiClientFactory {
// 首先检查特殊的provider id
if (provider.id === 'aihubmix') {
console.log(`[ApiClientFactory] Creating AihubmixAPIClient for provider: ${provider.id}`)
logger.debug(`Creating AihubmixAPIClient for provider: ${provider.id}`)
instance = new AihubmixAPIClient(provider) as BaseApiClient
return instance
}
if (provider.id === 'new-api') {
console.log(`[ApiClientFactory] Creating NewAPIClient for provider: ${provider.id}`)
logger.debug(`Creating NewAPIClient for provider: ${provider.id}`)
instance = new NewAPIClient(provider) as BaseApiClient
return instance
}
if (provider.id === 'ppio') {
console.log(`[ApiClientFactory] Creating PPIOAPIClient for provider: ${provider.id}`)
logger.debug(`Creating PPIOAPIClient for provider: ${provider.id}`)
instance = new PPIOAPIClient(provider) as BaseApiClient
return instance
}
@ -63,7 +66,7 @@ export class ApiClientFactory {
instance = new AnthropicAPIClient(provider) as BaseApiClient
break
default:
console.log(`[ApiClientFactory] Using default OpenAIApiClient for provider: ${provider.id}`)
logger.debug(`Using default OpenAIApiClient for provider: ${provider.id}`)
instance = new OpenAIAPIClient(provider) as BaseApiClient
break
}

View File

@ -1,9 +1,12 @@
import { loggerService } from '@logger'
import { Chunk } from '@renderer/types/chunk'
import { CompletionsResult } from '../schemas'
import { CompletionsContext } from '../types'
import { createErrorChunk } from '../utils'
const logger = loggerService.withContext('ErrorHandlerMiddleware')
export const MIDDLEWARE_NAME = 'ErrorHandlerMiddleware'
/**
@ -25,7 +28,7 @@ export const ErrorHandlerMiddleware =
// 尝试执行下一个中间件
return await next(ctx, params)
} catch (error: any) {
console.log('ErrorHandlerMiddleware_error', error)
logger.error('ErrorHandlerMiddleware_error', error)
// 1. 使用通用的工具函数将错误解析为标准格式
const errorChunk = createErrorChunk(error)
// 2. 调用从外部传入的 onError 回调

View File

@ -1,9 +1,12 @@
import { loggerService } from '@logger'
import { ChunkType } from '@renderer/types/chunk'
import { flushLinkConverterBuffer, smartLinkConverter } from '@renderer/utils/linkConverter'
import { CompletionsParams, CompletionsResult, GenericChunk } from '../schemas'
import { CompletionsContext, CompletionsMiddleware } from '../types'
const logger = loggerService.withContext('WebSearchMiddleware')
export const MIDDLEWARE_NAME = 'WebSearchMiddleware'
/**
@ -99,7 +102,7 @@ export const WebSearchMiddleware: CompletionsMiddleware =
stream: enhancedStream
}
} else {
console.log(`[${MIDDLEWARE_NAME}] No stream to process or not a ReadableStream.`)
logger.debug(`No stream to process or not a ReadableStream.`)
}
}

View File

@ -1,9 +1,12 @@
import { linter } from '@codemirror/lint' // statically imported by @uiw/codemirror-extensions-basic-setup
import { EditorView } from '@codemirror/view'
import { loggerService } from '@logger'
import { useCodeStyle } from '@renderer/context/CodeStyleProvider'
import { Extension, keymap } from '@uiw/react-codemirror'
import { useEffect, useMemo, useState } from 'react'
const logger = loggerService.withContext('CodeEditorHooks')
// 语言对应的 linter 加载器
const linterLoaders: Record<string, () => Promise<any>> = {
json: async () => {
@ -39,7 +42,7 @@ async function loadLanguageExtension(language: string, languageMap: Record<strin
try {
return await specialLoader()
} catch (error) {
console.debug(`Failed to load language ${normalizedLang}`, error)
logger.debug(`Failed to load language ${normalizedLang}`, error)
return null
}
}
@ -50,7 +53,7 @@ async function loadLanguageExtension(language: string, languageMap: Record<strin
const extension = loadLanguage(normalizedLang as any)
return extension || null
} catch (error) {
console.debug(`Failed to load language ${normalizedLang}`, error)
logger.debug(`Failed to load language ${normalizedLang}`, error)
return null
}
}
@ -65,7 +68,7 @@ async function loadLinterExtension(language: string): Promise<Extension | null>
try {
return await loader()
} catch (error) {
console.debug(`Failed to load linter for ${language}`, error)
logger.debug(`Failed to load linter for ${language}`, error)
return null
}
}
@ -105,7 +108,7 @@ export const useLanguageExtensions = (language: string, lint?: boolean) => {
setExtensions(results)
} catch (error) {
if (!cancelled) {
console.debug('Failed to load language extensions:', error)
logger.debug('Failed to load language extensions:', error)
setExtensions([])
}
}

View File

@ -10,6 +10,7 @@ import {
PushpinOutlined,
ReloadOutlined
} from '@ant-design/icons'
import { loggerService } from '@logger'
import { isLinux, isMac, isWin } from '@renderer/config/constant'
import { DEFAULT_MIN_APPS } from '@renderer/config/minapps'
import { useBridge } from '@renderer/hooks/useBridge'
@ -31,6 +32,8 @@ import styled from 'styled-components'
import WebviewContainer from './WebviewContainer'
const logger = loggerService.withContext('MinappPopupContainer')
interface AppExtraInfo {
canPinned: boolean
isPinned: boolean
@ -296,7 +299,7 @@ const MinappPopupContainer: React.FC = () => {
const handleWebviewNavigate = (appid: string, url: string) => {
// 记录当前URL用于GoogleLoginTip判断
if (appid === currentMinappId) {
console.log('URL changed:', url)
logger.debug('URL changed:', url)
setCurrentUrl(url)
}
}

View File

@ -34,6 +34,7 @@ export function useAppInit() {
useEffect(() => {
document.getElementById('spinner')?.remove()
// eslint-disable-next-line no-restricted-syntax
console.timeEnd('init')
// Initialize MemoryService after app is ready

View File

@ -1,3 +1,4 @@
import { loggerService } from '@logger'
import { db } from '@renderer/databases'
import KnowledgeQueue from '@renderer/queue/KnowledgeQueue'
import { getKnowledgeBaseParams } from '@renderer/services/KnowledgeService'
@ -26,6 +27,8 @@ import { v4 as uuidv4 } from 'uuid'
import { useAgents } from './useAgents'
import { useAssistants } from './useAssistant'
const logger = loggerService.withContext('useKnowledge')
export const useKnowledge = (baseId: string) => {
const dispatch = useDispatch()
const base = useSelector((state: RootState) => state.knowledge.bases.find((b) => b.id === baseId))
@ -53,7 +56,7 @@ export const useKnowledge = (baseId: string) => {
processingError: '',
retryCount: 0
}))
console.log('Adding files:', filesItems)
logger.debug('Adding files:', filesItems)
dispatch(addFilesAction({ baseId, items: filesItems }))
setTimeout(() => KnowledgeQueue.checkAllBases(), 0)
}

View File

@ -1,4 +1,5 @@
import { RedoOutlined } from '@ant-design/icons'
import { loggerService } from '@logger'
import CustomTag from '@renderer/components/CustomTag'
import { HStack } from '@renderer/components/Layout'
import { useKnowledge } from '@renderer/hooks/useKnowledge'
@ -20,6 +21,7 @@ import KnowledgeNotes from './items/KnowledgeNotes'
import KnowledgeSitemaps from './items/KnowledgeSitemaps'
import KnowledgeUrls from './items/KnowledgeUrls'
const logger = loggerService.withContext('KnowledgeContent')
interface KnowledgeContentProps {
selectedBase: KnowledgeBase
}
@ -52,7 +54,7 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
}),
window.electron.ipcRenderer.on('directory-processing-percent', (_, { itemId, percent }) => {
console.log('[Progress] Directory:', itemId, percent)
logger.debug('[Progress] Directory:', itemId, percent)
setProgressMap((prev) => new Map(prev).set(itemId, percent))
})
]

View File

@ -17,6 +17,7 @@ import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
const logger = loggerService.withContext('KnowledgeSettings')
interface ShowParams {
base: KnowledgeBase
}
@ -25,8 +26,6 @@ interface Props extends ShowParams {
resolve: (data: any) => void
}
const logger = loggerService.withContext('KnowledgeSettings')
const PopupContainer: React.FC<Props> = ({ base: _base, resolve }) => {
const { preprocessProviders } = usePreprocessProviders()
const { ocrProviders } = useOcrProviders()
@ -96,7 +95,7 @@ const PopupContainer: React.FC<Props> = ({ base: _base, resolve }) => {
const onOk = async () => {
try {
console.log('newbase', newBase)
logger.debug('newbase', newBase)
updateKnowledgeBase(newBase)
setOpen(false)
resolve(newBase)

View File

@ -1,10 +1,12 @@
import { CheckCircleOutlined, CloseCircleOutlined } from '@ant-design/icons'
import { loggerService } from '@logger'
import { KnowledgeBase, ProcessingStatus } from '@renderer/types'
import { Progress, Tooltip } from 'antd'
import React, { FC, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
const logger = loggerService.withContext('StatusIcon')
interface StatusIconProps {
sourceId: string
base: KnowledgeBase
@ -26,7 +28,7 @@ const StatusIcon: FC<StatusIconProps> = ({
const status = getProcessingStatus(sourceId)
const item = base.items.find((item) => item.id === sourceId)
const errorText = item?.processingError
console.log('[StatusIcon] Rendering for item:', item?.id, 'Status:', status, 'Progress:', progress)
logger.debug('[StatusIcon] Rendering for item:', item?.id, 'Status:', status, 'Progress:', progress)
return useMemo(() => {
if (!status) {

View File

@ -1,4 +1,5 @@
import { DeleteOutlined } from '@ant-design/icons'
import { loggerService } from '@logger'
import Ellipsis from '@renderer/components/Ellipsis'
import { useKnowledge } from '@renderer/hooks/useKnowledge'
import FileItem from '@renderer/pages/files/FileItem'
@ -16,6 +17,8 @@ import { FC, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
const logger = loggerService.withContext('KnowledgeFiles')
import {
ClickableSpan,
FlexAlignCenter,
@ -113,7 +116,7 @@ const KnowledgeFiles: FC<KnowledgeContentProps> = ({ selectedBase, progressMap,
})
.filter(({ ext }) => fileTypes.includes(ext))
const uploadedFiles = await FileManager.uploadFiles(_files)
console.log('uploadedFiles', uploadedFiles)
logger.debug('uploadedFiles', uploadedFiles)
addFiles(uploadedFiles)
}
}

View File

@ -338,7 +338,7 @@ const MemoriesPage = () => {
const loadMemories = useCallback(
async (userId?: string) => {
const targetUser = userId || currentUser
console.log('Loading all memories for user:', targetUser)
logger.debug('Loading all memories for user:', targetUser)
setLoading(true)
try {
// First, ensure the memory service is using the correct user
@ -349,7 +349,7 @@ const MemoriesPage = () => {
// Get all memories for current user context (load up to 10000)
const result = await memoryService.list({ limit: 10000, offset: 0 })
console.log('Loaded memories for user:', targetUser, 'count:', result.results?.length || 0)
logger.debug('Loaded memories for user:', targetUser, 'count:', result.results?.length || 0)
setAllMemories(result.results || [])
} catch (error) {
logger.error('Failed to load memories:', error)
@ -363,7 +363,7 @@ const MemoriesPage = () => {
// Sync memoryService with Redux store on mount and when currentUser changes
useEffect(() => {
console.log('useEffect triggered for currentUser:', currentUser)
logger.debug('useEffect triggered for currentUser:', currentUser)
// Reset to first page when user changes
setCurrentPage(1)
loadMemories(currentUser)
@ -453,7 +453,7 @@ const MemoriesPage = () => {
}
const handleUserSwitch = async (userId: string) => {
console.log('Switching to user:', userId)
logger.debug('Switching to user:', userId)
// First update Redux state
dispatch(setCurrentUserId(userId))

View File

@ -207,7 +207,7 @@ const AihubmixPage: FC<{ Options: string[] }> = ({ Options }) => {
// 确保渲染速度参数正确传递
const renderSpeed = painting.renderingSpeed || 'DEFAULT'
console.log('使用渲染速度:', renderSpeed)
logger.silly(`使用渲染速度: ${renderSpeed}`)
formData.append('rendering_speed', renderSpeed)
formData.append('num_images', String(painting.numImages || 1))
@ -215,7 +215,7 @@ const AihubmixPage: FC<{ Options: string[] }> = ({ Options }) => {
// Convert aspect ratio format from ASPECT_1_1 to 1x1 for V3 API
if (painting.aspectRatio) {
const aspectRatioValue = painting.aspectRatio.replace('ASPECT_', '').replace('_', 'x').toLowerCase()
console.log('转换后的宽高比:', aspectRatioValue)
logger.silly(`转换后的宽高比: ${aspectRatioValue}`)
formData.append('aspect_ratio', aspectRatioValue)
}
@ -223,39 +223,39 @@ const AihubmixPage: FC<{ Options: string[] }> = ({ Options }) => {
// 确保样式类型与API文档一致保持大写形式
// V3 API支持的样式类型: AUTO, GENERAL, REALISTIC, DESIGN
const styleType = painting.styleType
console.log('使用样式类型:', styleType)
logger.silly(`使用样式类型: ${styleType}`)
formData.append('style_type', styleType)
} else {
// 确保明确设置默认样式类型
console.log('使用默认样式类型: AUTO')
logger.silly('使用默认样式类型: AUTO')
formData.append('style_type', 'AUTO')
}
if (painting.seed) {
console.log('使用随机种子:', painting.seed)
logger.silly(`使用随机种子: ${painting.seed}`)
formData.append('seed', painting.seed)
}
if (painting.negativePrompt) {
console.log('使用负面提示词:', painting.negativePrompt)
logger.silly(`使用负面提示词: ${painting.negativePrompt}`)
formData.append('negative_prompt', painting.negativePrompt)
}
if (painting.magicPromptOption !== undefined) {
const magicPrompt = painting.magicPromptOption ? 'ON' : 'OFF'
console.log('使用魔法提示词:', magicPrompt)
logger.silly(`使用魔法提示词: ${magicPrompt}`)
formData.append('magic_prompt', magicPrompt)
}
// 打印所有FormData内容
console.log('FormData内容:')
logger.silly('FormData内容:')
for (const pair of formData.entries()) {
console.log(pair[0] + ': ' + pair[1])
logger.silly(`${pair[0]}: ${pair[1]}`)
}
body = formData
// For V3 endpoints - 使用模板字符串而不是字符串连接
console.log('API 端点:', `${aihubmixProvider.apiHost}/ideogram/v1/ideogram-v3/generate`)
logger.silly(`API 端点: ${aihubmixProvider.apiHost}/ideogram/v1/ideogram-v3/generate`)
// 调整请求头可能需要指定multipart/form-data
// 注意FormData会自动设置Content-Type不应手动设置
@ -275,7 +275,7 @@ const AihubmixPage: FC<{ Options: string[] }> = ({ Options }) => {
}
const data = await response.json()
console.log('V3 API响应:', data)
logger.silly(`V3 API响应: ${data}`)
const urls = data.data.map((item) => item.url)
if (urls.length > 0) {
@ -391,7 +391,7 @@ const AihubmixPage: FC<{ Options: string[] }> = ({ Options }) => {
}
const data = await response.json()
console.log('V3 Remix API响应:', data)
logger.silly(`V3 Remix API响应: ${data}`)
const urls = data.data.map((item) => item.url)
// Handle the downloaded images
@ -461,7 +461,7 @@ const AihubmixPage: FC<{ Options: string[] }> = ({ Options }) => {
}
const data = await response.json()
console.log('通用API响应:', data)
logger.silly(`通用API响应: ${data}`)
const urls = data.data.filter((item) => item.url).map((item) => item.url)
const base64s = data.data.filter((item) => item.b64_json).map((item) => item.b64_json)

View File

@ -1,3 +1,4 @@
import { loggerService } from '@logger'
import { useAppDispatch } from '@renderer/store'
import { setDefaultPaintingProvider } from '@renderer/store/settings'
import { PaintingProvider } from '@renderer/types'
@ -10,6 +11,8 @@ import NewApiPage from './NewApiPage'
import SiliconPage from './SiliconPage'
import TokenFluxPage from './TokenFluxPage'
const logger = loggerService.withContext('PaintingsRoutePage')
const Options = ['aihubmix', 'silicon', 'dmxapi', 'tokenflux', 'new-api']
const PaintingsRoutePage: FC = () => {
@ -18,7 +21,7 @@ const PaintingsRoutePage: FC = () => {
const dispatch = useAppDispatch()
useEffect(() => {
console.debug('defaultPaintingProvider', provider)
logger.debug('defaultPaintingProvider', provider)
if (provider && Options.includes(provider)) {
dispatch(setDefaultPaintingProvider(provider as PaintingProvider))
}

View File

@ -125,7 +125,7 @@ export const syncTokenLanYunServers = async (
// Transform Token servers to MCP servers format
const addedServers: MCPServer[] = []
console.log('TokenLanYun servers:', servers)
logger.debug('TokenLanYun servers:', servers)
for (const server of servers) {
try {
if (!server.operationalUrls?.[0]?.url) continue

View File

@ -370,7 +370,7 @@ export async function fetchChatCompletion({
// TODO
// onChunkStatus: (status: 'searching' | 'processing' | 'success' | 'error') => void
}) {
console.log('fetchChatCompletion', messages, assistant)
logger.debug('fetchChatCompletion', messages, assistant)
const provider = getAssistantProvider(assistant)
const AI = new AiProvider(provider)
@ -518,12 +518,12 @@ async function processConversationMemory(messages: Message[], assistant: Assista
memoryProcessor
.processConversation(conversationMessages, processorConfig)
.then((result) => {
console.log('Memory processing completed:', result)
logger.debug('Memory processing completed:', result)
if (result.facts.length > 0) {
console.log('Extracted facts from conversation:', result.facts)
console.log('Memory operations performed:', result.operations)
logger.debug('Extracted facts from conversation:', result.facts)
logger.debug('Memory operations performed:', result.operations)
} else {
console.log('No facts extracted from conversation')
logger.debug('No facts extracted from conversation')
}
})
.catch((error) => {

View File

@ -61,7 +61,7 @@ export const getKnowledgeBaseParams = (base: KnowledgeBase): KnowledgeBaseParams
}
export const getFileFromUrl = async (url: string): Promise<FileMetadata | null> => {
console.log('getFileFromUrl', url)
logger.debug('getFileFromUrl', url)
let fileName = ''
if (url && url.includes('CherryStudio')) {
@ -73,10 +73,10 @@ export const getFileFromUrl = async (url: string): Promise<FileMetadata | null>
fileName = url.split('\\Data\\Files\\')[1]
}
}
console.log('fileName', fileName)
logger.debug('fileName', fileName)
if (fileName) {
const actualFileName = fileName.split(/[/\\]/).pop() || fileName
console.log('actualFileName', actualFileName)
logger.debug('actualFileName', actualFileName)
const fileId = actualFileName.split('.')[0]
const file = await FileManager.getFile(fileId)
if (file) {
@ -135,7 +135,7 @@ export const searchKnowledgeBase = async (
return await Promise.all(
limitedResults.map(async (item) => {
const file = await getFileFromUrl(item.metadata.source)
console.log('Knowledge search item:', item, 'File:', file)
logger.debug('Knowledge search item:', item, 'File:', file)
return { ...item, file }
})
)

View File

@ -238,7 +238,7 @@ export class MemoryProcessor {
limit
})
console.log(
logger.debug(
'Searching memories with query:',
query,
'for user:',

View File

@ -1,3 +1,4 @@
import { loggerService } from '@logger'
import { autoRenameTopic } from '@renderer/hooks/useTopic'
import i18n from '@renderer/i18n'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
@ -21,6 +22,7 @@ import { isFocused, isOnHomePage } from '@renderer/utils/window'
import { BlockManager } from '../BlockManager'
const logger = loggerService.withContext('BaseCallbacks')
interface BaseCallbacksDependencies {
blockManager: BlockManager
dispatch: any
@ -68,7 +70,7 @@ export const createBaseCallbacks = (deps: BaseCallbacksDependencies) => {
},
onError: async (error: any) => {
console.dir(error, { depth: null })
logger.debug('onError', error)
const isErrorTypeAbort = isAbortError(error)
let pauseErrorLanguagePlaceholder = ''
if (isErrorTypeAbort) {

View File

@ -43,9 +43,9 @@ export const createCitationCallbacks = (deps: CitationCallbacksDependencies) =>
onLLMWebSearchInProgress: async () => {
if (blockManager.hasInitialPlaceholder) {
// blockManager.lastBlockType = MessageBlockType.CITATION
console.log('blockManager.initialPlaceholderBlockId', blockManager.initialPlaceholderBlockId)
logger.debug('blockManager.initialPlaceholderBlockId', blockManager.initialPlaceholderBlockId)
citationBlockId = blockManager.initialPlaceholderBlockId!
console.log('citationBlockId', citationBlockId)
logger.debug('citationBlockId', citationBlockId)
const changes = {
type: MessageBlockType.CITATION,

View File

@ -1,7 +1,10 @@
import { loggerService } from '@logger'
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import FileManager from '@renderer/services/FileManager'
import { FileMetadata, KnowledgeBase, KnowledgeItem, ProcessingStatus } from '@renderer/types'
const logger = loggerService.withContext('Store:Knowledge')
export interface KnowledgeState {
bases: KnowledgeBase[]
}
@ -176,7 +179,7 @@ const knowledgeSlice = createSlice({
action: PayloadAction<{ baseId: string; itemId: string; uniqueId: string; uniqueIds: string[] }>
) {
const base = state.bases.find((b) => b.id === action.payload.baseId)
console.log('base2', base)
logger.silly('base2', base)
if (base) {
const item = base.items.find((item) => item.id === action.payload.itemId)
if (item) {
@ -191,10 +194,10 @@ const knowledgeSlice = createSlice({
action: PayloadAction<{ baseId: string; itemId: string; isPreprocessed: boolean }>
) {
const base = state.bases.find((b) => b.id === action.payload.baseId)
console.log('base', base)
logger.silly('base', base)
if (base) {
const item = base.items.find((item) => item.id === action.payload.itemId)
console.log('item', item)
logger.silly('item', item)
if (item) {
item.isPreprocessed = action.payload.isPreprocessed
}

View File

@ -1,3 +1,4 @@
import { loggerService } from '@logger'
import { BundledLanguage, BundledTheme } from 'shiki/bundle/web'
import { getTokenStyleObject, type HighlighterGeneric, SpecialLanguage, ThemedToken } from 'shiki/core'
@ -6,6 +7,8 @@ import { AsyncInitializer } from './asyncInitializer'
export const DEFAULT_LANGUAGES = ['javascript', 'typescript', 'python', 'java', 'markdown', 'json']
export const DEFAULT_THEMES = ['one-light', 'material-theme-darker']
const logger = loggerService.withContext('Shiki')
/**
* shiki
*/
@ -87,7 +90,7 @@ export async function loadThemeIfNeeded(highlighter: HighlighterGeneric<any, any
await highlighter.loadTheme(themeData)
} catch (error) {
// 回退到 one-light
console.debug(`Failed to load theme '${theme}', falling back to 'one-light':`, error)
logger.debug(`Failed to load theme '${theme}', falling back to 'one-light':`, error)
const oneLightTheme = await shiki.bundledThemes['one-light']()
await highlighter.loadTheme(oneLightTheme)
loadedTheme = 'one-light'
@ -153,7 +156,7 @@ export async function getMarkdownIt(theme: string, markdown: string) {
try {
actualTheme = await loadThemeIfNeeded(highlighter, theme)
} catch (error) {
console.debug(`Failed to load theme '${theme}', using 'one-light' as fallback:`, error)
logger.debug(`Failed to load theme '${theme}', using 'one-light' as fallback:`, error)
actualTheme = 'one-light'
}

View File

@ -1,5 +1,9 @@
/// <reference lib="webworker" />
import { loggerService } from '@logger'
const logger = loggerService.withContext('PyodideWorker')
// 定义输出结构类型
interface PyodideOutput {
result: any
@ -47,7 +51,7 @@ const pyodidePromise = (async () => {
})
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : String(error)
console.error('Failed to load Pyodide:', errorMessage)
logger.error('Failed to load Pyodide:', errorMessage)
// 通知主线程初始化错误
self.postMessage({
@ -77,7 +81,7 @@ function processResult(result: any): any {
return result
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : String(error)
console.error('Result processing error:', errorMessage)
logger.error('Result processing error:', errorMessage)
return { __error__: 'Result processing failed', details: errorMessage }
}
}
@ -89,7 +93,7 @@ pyodidePromise
})
.catch((error: unknown) => {
const errorMessage = error instanceof Error ? error.message : String(error)
console.error('Failed to load Pyodide:', errorMessage)
logger.error('Failed to load Pyodide:', errorMessage)
self.postMessage({ type: 'error', error: errorMessage })
})
@ -141,7 +145,7 @@ self.onmessage = async (event) => {
} catch (error: unknown) {
// 处理所有其他错误
const errorMessage = error instanceof Error ? error.message : String(error)
console.error('Python processing error:', errorMessage)
logger.error('Python processing error:', errorMessage)
if (output.error) {
output.error += `\nSystem error:\n${errorMessage}`

View File

@ -1,11 +1,14 @@
/// <reference lib="webworker" />
import { loggerService } from '@logger'
import { LRUCache } from 'lru-cache'
import type { HighlighterCore, SpecialLanguage, ThemedToken } from 'shiki/core'
// 注意保持 ShikiStreamTokenizer 依赖简单,避免打包出问题
import { ShikiStreamTokenizer, ShikiStreamTokenizerOptions } from '../services/ShikiStreamTokenizer'
const logger = loggerService.withContext('ShikiStreamWorker')
// Worker 消息类型
type WorkerMessageType = 'init' | 'highlight' | 'cleanup' | 'dispose'
@ -93,7 +96,7 @@ async function ensureLanguageAndThemeLoaded(
await highlighter.loadTheme(themeData)
} catch (error) {
// 回退到 one-light
console.debug(`Worker: Failed to load theme '${theme}', falling back to 'one-light':`, error)
logger.debug(`Worker: Failed to load theme '${theme}', falling back to 'one-light':`, error)
const { bundledThemes } = await import('shiki')
const oneLightTheme = await bundledThemes['one-light']()
await highlighter.loadTheme(oneLightTheme)
@ -154,7 +157,7 @@ async function highlightCodeChunk(
recall: result.recall
}
} catch (error) {
console.error('Worker failed to highlight code chunk:', error)
logger.error('Worker failed to highlight code chunk:', error)
// 提供简单的 fallback
const fallbackToken: ThemedToken = { content: chunk || '', color: '#000000', offset: 0 }