mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-10-25 17:54:34 +08:00
feat(tools): implement CoreDataProvider and WorkerDataProvider
Add ToolDataProvider implementations for both platforms: - CoreDataProvider: wraps @openchatlab/core sync queries for Server/MCP - WorkerDataProvider: wraps workerManager async IPC for Electron
This commit is contained in:
1 parent
21a0ce36f4
commit
b1df81b064
3 files changed
+185
No files matched your search
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* WorkerDataProvider
|
||||
*
|
||||
* 基于 workerManager 的 ToolDataProvider 实现。
|
||||
* 通过 Worker IPC 异步访问 SQLite,供 Electron Agent 使用。
|
||||
*/
|
||||
|
||||
import * as workerManager from '../../worker/workerManager'
|
||||
import type {
|
||||
ToolDataProvider,
|
||||
SearchMessagesResult,
|
||||
MemberStatItem,
|
||||
SchemaTableInfo,
|
||||
TimeFilter,
|
||||
} from '@openchatlab/tools'
|
||||
|
||||
export class WorkerDataProvider implements ToolDataProvider {
|
||||
constructor(private sessionId: string) {}
|
||||
|
||||
async searchMessages(
|
||||
keywords: string[],
|
||||
options?: { timeFilter?: TimeFilter; limit?: number; senderId?: number }
|
||||
): Promise<SearchMessagesResult> {
|
||||
const result = await workerManager.searchMessages(
|
||||
this.sessionId,
|
||||
keywords,
|
||||
options?.timeFilter,
|
||||
options?.limit ?? 50,
|
||||
0,
|
||||
options?.senderId
|
||||
)
|
||||
|
||||
return {
|
||||
messages: result.messages.map((m) => ({
|
||||
id: m.id,
|
||||
senderName: m.senderName,
|
||||
senderPlatformId: m.senderPlatformId,
|
||||
content: m.content,
|
||||
timestamp: m.timestamp,
|
||||
})),
|
||||
total: result.total,
|
||||
}
|
||||
}
|
||||
|
||||
async getRecentMessages(options?: { timeFilter?: TimeFilter; limit?: number }): Promise<SearchMessagesResult> {
|
||||
const result = await workerManager.getRecentMessages(this.sessionId, options?.timeFilter, options?.limit ?? 50)
|
||||
|
||||
return {
|
||||
messages: result.messages.map((m) => ({
|
||||
id: m.id,
|
||||
senderName: m.senderName,
|
||||
senderPlatformId: m.senderPlatformId,
|
||||
content: m.content,
|
||||
timestamp: m.timestamp,
|
||||
})),
|
||||
total: result.total,
|
||||
}
|
||||
}
|
||||
|
||||
async getMemberStats(options?: { timeFilter?: TimeFilter; top?: number }): Promise<MemberStatItem[]> {
|
||||
const top = options?.top ?? 20
|
||||
const members = await workerManager.getMemberActivity(this.sessionId, options?.timeFilter)
|
||||
return members.slice(0, top).map((m: any) => ({
|
||||
name: m.name,
|
||||
messageCount: m.messageCount,
|
||||
percentage: m.percentage,
|
||||
}))
|
||||
}
|
||||
|
||||
async getTimeStats(type: 'hourly' | 'weekday' | 'daily', options?: { timeFilter?: TimeFilter }): Promise<unknown[]> {
|
||||
const filter = options?.timeFilter
|
||||
switch (type) {
|
||||
case 'weekday':
|
||||
return workerManager.getWeekdayActivity(this.sessionId, filter)
|
||||
case 'daily':
|
||||
return workerManager.getDailyActivity(this.sessionId, filter)
|
||||
case 'hourly':
|
||||
default:
|
||||
return workerManager.getHourlyActivity(this.sessionId, filter)
|
||||
}
|
||||
}
|
||||
|
||||
async executeSql(sql: string): Promise<unknown> {
|
||||
return workerManager.executeRawSQL(this.sessionId, sql)
|
||||
}
|
||||
|
||||
async getSchema(): Promise<SchemaTableInfo[]> {
|
||||
const tables = await workerManager.getSchema(this.sessionId)
|
||||
return tables.map((t) => ({
|
||||
name: t.name,
|
||||
sql: t.columns.map((c) => `${c.name} ${c.type}${c.pk ? ' PK' : ''}${c.notnull ? ' NOT NULL' : ''}`).join(', '),
|
||||
}))
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
export { TOOL_REGISTRY, getToolByName } from './registry'
|
||||
export { CoreDataProvider } from './providers/core-data-provider'
|
||||
export type {
|
||||
ToolDefinition,
|
||||
ToolExecutionContext,
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* CoreDataProvider
|
||||
*
|
||||
* 基于 @openchatlab/core 同步查询函数的 ToolDataProvider 实现。
|
||||
* 供 Server / MCP 使用,通过 DatabaseAdapter 直接访问 SQLite。
|
||||
*/
|
||||
|
||||
import type { DatabaseAdapter } from '@openchatlab/core'
|
||||
import {
|
||||
searchMessagesLike,
|
||||
getRecentMessages,
|
||||
getMemberActivity,
|
||||
getHourlyActivity,
|
||||
getWeekdayActivity,
|
||||
getDailyActivity,
|
||||
executeReadonlySql,
|
||||
getDatabaseSchema,
|
||||
} from '@openchatlab/core'
|
||||
import type { ToolDataProvider, SearchMessagesResult, MemberStatItem, SchemaTableInfo, TimeFilter } from '../types'
|
||||
|
||||
export class CoreDataProvider implements ToolDataProvider {
|
||||
constructor(private db: DatabaseAdapter) {}
|
||||
|
||||
async searchMessages(
|
||||
keywords: string[],
|
||||
options?: { timeFilter?: TimeFilter; limit?: number; senderId?: number }
|
||||
): Promise<SearchMessagesResult> {
|
||||
const keyword = keywords.join(' ')
|
||||
const result = searchMessagesLike(this.db, keyword, { limit: options?.limit ?? 50 })
|
||||
|
||||
return {
|
||||
messages: result.messages.map((m) => ({
|
||||
id: m.id,
|
||||
senderId: m.senderId,
|
||||
senderName: m.senderName,
|
||||
senderPlatformId: m.senderPlatformId,
|
||||
content: m.content,
|
||||
timestamp: m.timestamp,
|
||||
})),
|
||||
total: result.total ?? result.messages.length,
|
||||
}
|
||||
}
|
||||
|
||||
async getRecentMessages(options?: { timeFilter?: TimeFilter; limit?: number }): Promise<SearchMessagesResult> {
|
||||
const messages = getRecentMessages(this.db, { limit: options?.limit ?? 50 })
|
||||
|
||||
return {
|
||||
messages: messages.map((m) => ({
|
||||
id: m.id,
|
||||
senderId: m.senderId,
|
||||
senderName: m.senderName,
|
||||
senderPlatformId: m.senderPlatformId,
|
||||
content: m.content,
|
||||
timestamp: m.timestamp,
|
||||
})),
|
||||
total: messages.length,
|
||||
}
|
||||
}
|
||||
|
||||
async getMemberStats(options?: { timeFilter?: TimeFilter; top?: number }): Promise<MemberStatItem[]> {
|
||||
const top = options?.top ?? 20
|
||||
const members = getMemberActivity(this.db, options?.timeFilter)
|
||||
return members.slice(0, top).map((m) => ({
|
||||
name: m.name,
|
||||
messageCount: m.messageCount,
|
||||
percentage: m.percentage,
|
||||
}))
|
||||
}
|
||||
|
||||
async getTimeStats(type: 'hourly' | 'weekday' | 'daily', options?: { timeFilter?: TimeFilter }): Promise<unknown[]> {
|
||||
const filter = options?.timeFilter
|
||||
switch (type) {
|
||||
case 'weekday':
|
||||
return getWeekdayActivity(this.db, filter)
|
||||
case 'daily':
|
||||
return getDailyActivity(this.db, filter)
|
||||
case 'hourly':
|
||||
default:
|
||||
return getHourlyActivity(this.db, filter)
|
||||
}
|
||||
}
|
||||
|
||||
async executeSql(sql: string): Promise<unknown> {
|
||||
return executeReadonlySql(this.db, sql)
|
||||
}
|
||||
|
||||
async getSchema(): Promise<SchemaTableInfo[]> {
|
||||
return getDatabaseSchema(this.db)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user