You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

994 lines
34 KiB

import Foundation
import MicrosoftCognitiveServicesSpeech
import open_ai_service
import chat_storage
/// 代理服务 - 处理语音识别、TTS和AI对话相关逻辑
///
/// 负责集成Azure语音服务、OpenAI服务和本地存储服务,
/// 提供语音识别、语音合成、AI对话等功能
class AgentService {
// 常量定义
private let TAG = "AgentService"
// 上下文和监听器
private var listeners = NSHashTable<AnyObject>.weakObjects()
// 配置参数
private var azureSpeechKey: String = ""
private var azureSpeechRegion: String = ""
private var openaiApiKey: String = ""
private var openaiBaseUrl: String = ""
private var openaiModel: String = "gpt-3.5-turbo"
private var mcpServer: String = ""
// Azure服务
private var azureAsrHelper: AzureAsrHelper?
private var azureTtsHelper: AzureTtsHelper?
// OpenAI服务
private var openAIService: OpenAIServiceBridge?
// 聊天存储服务
private var chatStorageHelper: ChatStorageHelperBridge?
// 会话ID,用于区分不同聊天上下文
private let sessionId = "default_agent"
// 历史聊天消息缓存
private var historyMessages = [[String: Any]]()
// 系统提示词
private var systemPrompt = ""
// 状态
private var isInitialized = false
private var isRecognitionActive = false
private var isTtsSpeaking = false
private var hasSpeechDetected = false
private var isAiStreaming = false
// AI流生成相关
private var currentAiTask: DispatchWorkItem?
// 空闲检测相关
private var idleCheckTimer: Timer?
private let maxIdleSeconds: TimeInterval = 10 // 最大空闲秒数
/// 初始化
init() {
// 创建OpenAI服务桥接器
openAIService = OpenAIServiceBridge()
// 创建聊天存储桥接器
chatStorageHelper = ChatStorageHelperBridge()
}
/**
* 初始化系统提示词
*/
private func initSystemPrompt() {
systemPrompt = """
你是一个友好、专业的语音助手,名叫"小语"。你的目标是通过对话为用户提供帮助、解答问题和完成任务。
遵循以下指导原则:
1. 保持简短精炼的回答,因为用户是通过语音与你交流
2. 优先使用中文回复,除非用户明确要求使用其他语言
3. 当用户问题不明确时,礼貌地请求更多信息
4. 避免过长的列表,尽量将信息分成小段
5. 不要使用需要视觉展示的元素(如表格、图表或代码块)
6. 记住用户之前的对话内容,保持对话连贯
7. 如果用户发送了图片,请根据图片内容和文字要求回答问题
你不仅可以回答知识性问题,还可以帮助用户设置提醒、提供建议,或进行轻松愉快的对话。
无论遇到什么问题,都要尽力以温暖、贴心的语气提供最佳帮助。
"""
}
/**
* 初始化
*
* - Parameter config: 配置参数,包含所需的所有API密钥和设置
* - Returns: 是否初始化成功
*/
func initialize(config: [String: Any]) -> Bool {
if isInitialized { return true }
do {
// 从配置中获取参数
if let azureKey = config["azureSpeechKey"] as? String {
azureSpeechKey = azureKey
}
if let azureRegion = config["azureSpeechRegion"] as? String {
azureSpeechRegion = azureRegion
}
if let openaiKey = config["openaiApiKey"] as? String {
openaiApiKey = openaiKey
}
if let baseUrl = config["openaiBaseUrl"] as? String {
openaiBaseUrl = baseUrl
}
if let model = config["openaiModel"] as? String {
openaiModel = model
}
if let server = config["mcpServer"] as? String {
mcpServer = server
}
// 自定义系统提示词
if let customSystemPrompt = config["systemPrompt"] as? String, !customSystemPrompt.isEmpty {
systemPrompt = customSystemPrompt
} else {
// 使用默认系统提示词
initSystemPrompt()
}
// 检查必要参数
if azureSpeechKey.isEmpty || azureSpeechRegion.isEmpty || openaiApiKey.isEmpty {
print("\(TAG): 初始化失败:关键配置参数缺失")
return false
}
// 初始化OpenAI服务
openAIService?.initialize(apiKey: openaiApiKey, baseUrl: openaiBaseUrl, model: openaiModel, mcpServer: mcpServer)
// 初始化Azure ASR
azureAsrHelper = AzureAsrHelper(self)
let asrInitResult = azureAsrHelper?.initialize(
subscriptionKey: azureSpeechKey,
region: azureSpeechRegion,
audioSourceType: .microphone
) ?? false
if !asrInitResult {
print("\(TAG): Azure ASR初始化失败")
return false
}
// 初始化Azure TTS
azureTtsHelper = AzureTtsHelper(self)
let ttsInitResult = azureTtsHelper?.initialize(
subscriptionKey: azureSpeechKey,
region: azureSpeechRegion,
callback: self
) ?? false
if !ttsInitResult {
print("\(TAG): Azure TTS初始化失败")
return false
}
// 加载最近的聊天记录
loadChatHistory()
isInitialized = true
print("\(TAG): 代理服务初始化成功")
return true
} catch {
print("\(TAG): 初始化失败:\(error.localizedDescription)")
return false
}
}
/**
* 添加事件监听器
*
* - Parameter listener: 要添加的监听器
*/
func addListener(_ listener: AgentServiceListener) {
listeners.add(listener as AnyObject)
}
/**
* 设置事件监听器(替换现有监听器)
*
* - Parameter listener: 要设置的监听器
*/
func setListener(_ listener: AgentServiceListener) {
listeners.removeAllObjects()
listeners.add(listener as AnyObject)
}
/**
* 移除事件监听器
*
* - Parameter listener: 要移除的监听器
*/
func removeListener(_ listener: AgentServiceListener) {
listeners.remove(listener as AnyObject)
}
/**
* 移除所有事件监听器
*/
func clearListeners() {
listeners.removeAllObjects()
}
/**
* 启动空闲检测
*/
private func startIdleCheck() {
stopIdleCheck() // 先停止现有的检查
if !isRecognitionActive { return }
// 创建定时器
idleCheckTimer = Timer.scheduledTimer(withTimeInterval: maxIdleSeconds, repeats: false) { [weak self] _ in
guard let self = self else { return }
// 如果状态仍然是空闲的,则停止识别
if self.isRecognitionActive && !self.hasSpeechDetected && !self.isTtsSpeaking && !self.isAiStreaming {
self.stopRecognition()
self.sendEvent("auto_stop", ["reason": "idle_timeout", "seconds": self.maxIdleSeconds])
}
}
}
/**
* 停止空闲检测
*/
private func stopIdleCheck() {
idleCheckTimer?.invalidate()
idleCheckTimer = nil
}
/**
* 重启空闲检测
* 当状态发生变化时调用
*/
private func restartIdleCheck() {
if isRecognitionActive {
startIdleCheck()
}
}
/**
* 开始语音识别
*
* - Returns: 是否成功开始识别
*/
func startRecognition() -> Bool {
if !isInitialized {
print("\(TAG): 服务未初始化")
return false
}
if isRecognitionActive { return true }
isRecognitionActive = true
hasSpeechDetected = false
do {
// 创建连续识别回调
class ContinuousRecognizeCallbackImpl: AzureAsrHelper.ContinuousRecognizeCallback {
private weak var service: AgentService?
init(_ service: AgentService) {
self.service = service
}
func onRecognizing(recognizing: String, detectedLanguage: String) {
guard let service = service else { return }
if !recognizing.isEmpty {
// 检测到语音,更新状态
let previousHasSpeech = service.hasSpeechDetected
service.hasSpeechDetected = true
// 状态发生变化时重启空闲检测
if !previousHasSpeech {
service.restartIdleCheck()
}
service.sendEvent("recognizing", [
"text": recognizing,
"language": detectedLanguage
])
// 如果TTS正在播放或AI正在生成,则触发打断
if service.isTtsSpeaking || service.isAiStreaming {
service.interruptCurrentResponse()
}
}
}
func onResult(text: String, detectedLanguage: String) {
guard let service = service else { return }
if !text.isEmpty {
service.sendEvent("recognition_result", [
"text": text,
"language": detectedLanguage
])
service.processWithOpenAI(text: text)
}
// 重置状态,继续识别
let previousHasSpeech = service.hasSpeechDetected
service.hasSpeechDetected = false
// 状态发生变化时重启空闲检测
if previousHasSpeech {
service.restartIdleCheck()
}
}
func onSessionStarted() {
guard let service = service else { return }
service.sendEvent("recognition_started", ["status": "started"])
// 启动空闲检测
service.startIdleCheck()
}
func onSessionStopped() {
guard let service = service else { return }
service.isRecognitionActive = false
service.stopIdleCheck()
service.sendEvent("recognition_stopped", ["status": "stopped"])
}
func onCanceled(reason: String, errorDetails: String) {
guard let service = service else { return }
service.isRecognitionActive = false
service.stopIdleCheck()
service.sendEvent("recognition_canceled", [
"reason": reason,
"details": errorDetails
])
}
func onError(error: String) {
guard let service = service else { return }
service.isRecognitionActive = false
service.stopIdleCheck()
print("\(service.TAG): 语音识别出错: \(error)")
service.sendEvent("error", [
"code": "RECOGNITION_ERROR",
"message": error
])
}
}
let callback = ContinuousRecognizeCallbackImpl(self)
let result = azureAsrHelper?.startContinuousRecognition(callback) ?? false
if !result {
isRecognitionActive = false
print("\(TAG): 启动语音识别失败")
sendEvent("error", [
"code": "RECOGNITION_START_ERROR",
"message": "启动语音识别失败"
])
}
return result
} catch {
isRecognitionActive = false
print("\(TAG): 启动语音识别失败: \(error.localizedDescription)")
sendEvent("error", [
"code": "RECOGNITION_START_ERROR",
"message": error.localizedDescription
])
return false
}
}
/**
* 停止语音识别
*/
func stopRecognition() {
if !isRecognitionActive { return }
print("\(TAG): 停止语音识别")
// 停止识别
let _ = azureAsrHelper?.stopContinuousRecognition()
isRecognitionActive = false
stopIdleCheck()
print("\(TAG): 语音识别已停止")
}
/**
* 打断当前响应
* 停止TTS播放和AI流输出
*/
func interruptCurrentResponse() {
if isAiStreaming || isTtsSpeaking {
// 停止TTS播放
stopTts()
// 停止AI流输出
stopAiStream()
// 发送打断事件
sendEvent("response_interrupted", ["status": "interrupted"])
}
}
/**
* 停止AI流输出
*/
private func stopAiStream() {
if isAiStreaming {
// 取消当前AI生成任务
currentAiTask?.cancel()
currentAiTask = nil
// 通知OpenAI服务终止当前流式请求
openAIService?.cancelCurrentStream()
// 更新状态
isAiStreaming = false
// 记录日志
print("\(TAG): AI流输出已停止")
}
}
/**
* 处理文本输入
* 作为语音输入的补充,直接处理文本并通过事件返回结果
*
* - Parameters:
* - text: 用户输入文本
* - speakResponse: 是否朗读回复,默认为false
* - Returns: 是否成功开始处理
*/
func processTextInput(text: String, speakResponse: Bool = false) -> Bool {
if !isInitialized {
print("\(TAG): 服务未初始化")
sendEvent("error", ["code": "NOT_INITIALIZED", "message": "服务未初始化"])
return false
}
if text.isEmpty {
print("\(TAG): 文本输入不能为空")
sendEvent("error", ["code": "EMPTY_TEXT", "message": "文本输入不能为空"])
return false
}
// 使用OpenAI处理文本
processWithOpenAI(text: text, speakResponse: speakResponse)
return true
}
/**
* 使用OpenAI处理语音识别结果
*
* - Parameter text: 用户输入文本
*/
private func processWithOpenAI(text: String) {
processWithOpenAI(text: text, speakResponse: true)
}
/**
* 使用OpenAI处理文本消息
*
* - Parameters:
* - text: 用户输入文本
* - speakResponse: 是否使用TTS朗读回复
*/
private func processWithOpenAI(text: String, speakResponse: Bool = true) {
print("\(TAG): 用户问题: \(text)")
// 创建用户文本消息并处理
guard let userMessage = openAIService?.createUserMessage(text: text) else {
print("\(TAG): 创建用户消息失败")
return
}
processWithOpenAIInternal(userMessage: userMessage, displayText: text, speakResponse: speakResponse)
}
/**
* 使用OpenAI处理图片
*
* - Parameters:
* - imagePath: 图片文件路径
* - text: 可选的文本描述或问题
* - speakResponse: 是否朗读回复
* - Returns: 是否成功开始处理
*/
func processImageInput(imagePath: String, text: String = "", speakResponse: Bool = false) -> Bool {
if !isInitialized {
print("\(TAG): 服务未初始化")
sendEvent("error", ["code": "NOT_INITIALIZED", "message": "服务未初始化"])
return false
}
if imagePath.isEmpty {
print("\(TAG): 图片路径不能为空")
sendEvent("error", ["code": "EMPTY_IMAGE_PATH", "message": "图片路径不能为空"])
return false
}
// 通知开始处理图片
sendEvent("image_processing", [
"status": "processing",
"imagePath": imagePath
])
// 异步处理图片
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
guard let self = self else { return }
// 将图片转换为Base64格式
guard let imageBase64 = self.openAIService?.fileToBase64(filePath: imagePath) else {
DispatchQueue.main.async {
print("\(self.TAG): 图片转换失败: \(imagePath)")
self.sendEvent("error", [
"code": "IMAGE_CONVERSION_FAILED",
"message": "图片转换失败"
])
}
return
}
// 通知图片准备完成
DispatchQueue.main.async {
self.sendEvent("image_ready", [
"status": "ready",
"imagePath": imagePath
])
// 处理包含图片的消息
self.processImageWithOpenAI(imageBase64: imageBase64, text: text, speakResponse: speakResponse)
}
}
return true
}
/**
* 使用OpenAI处理图片
*
* - Parameters:
* - imageBase64: Base64编码的图片数据
* - text: 可选的文本描述或问题
* - speakResponse: 是否朗读回复
*/
private func processImageWithOpenAI(imageBase64: String, text: String = "", speakResponse: Bool = false) {
print("\(TAG): 处理图片输入: \(text.isEmpty ? "无附加文本" : "附带文本: \(text)")")
// 创建带图片的用户消息并处理
guard let userMessage = openAIService?.createUserMessageWithImage(text: text, imageBase64: imageBase64) else {
print("\(TAG): 创建带图片的用户消息失败")
return
}
// 图片描述用于存储
let displayText = text.isEmpty ? "[图片]" : text
processWithOpenAIInternal(userMessage: userMessage, displayText: displayText, speakResponse: speakResponse, hasImage: true)
}
/**
* 内部方法:通用的OpenAI处理逻辑
*
* - Parameters:
* - userMessage: 用户消息(可以是文本或图片格式)
* - displayText: 用于显示和存储的文本
* - speakResponse: 是否朗读回复
* - hasImage: 是否包含图片
*/
private func processWithOpenAIInternal(userMessage: [String: Any], displayText: String, speakResponse: Bool = true, hasImage: Bool = false) {
// 如果有正在进行的AI流式输出,先停止它
stopAiStream()
// 创建AI任务
let workItem = DispatchWorkItem { [weak self] in
guard let self = self else { return }
// 设置状态为正在流式输出
self.isAiStreaming = true
// 使用历史记录作为上下文发送到OpenAI
var responseBuilder = ""
// 添加系统提示词到历史消息的副本中
var messagesWithSystemPrompt: [[String: Any]] = []
// 先添加系统提示词
if !self.systemPrompt.isEmpty {
if let systemMessage = self.openAIService?.createSystemMessage(text: self.systemPrompt) {
messagesWithSystemPrompt.append(systemMessage)
}
}
// 再添加历史消息
messagesWithSystemPrompt.append(contentsOf: self.historyMessages)
messagesWithSystemPrompt.append(userMessage)
// 将用户消息添加到历史记录
self.addToHistoryMessages(userMessage)
// 流式回调
class StreamCallbackBridge: NSObject, OpenAIStreamCallback {
private weak var service: AgentService?
private var responseBuilder: String
private let speakResponse: Bool
private let displayText: String
private let hasImage: Bool
init(_ service: AgentService, responseBuilder: String = "", speakResponse: Bool, displayText: String, hasImage: Bool) {
self.service = service
self.responseBuilder = responseBuilder
self.speakResponse = speakResponse
self.displayText = displayText
self.hasImage = hasImage
super.init()
}
func onToken(token: String) {
guard let service = service else { return }
responseBuilder.append(token)
if speakResponse {
_ = service.azureTtsHelper?.speakStream(token)
}
// 发送流式回复token
service.sendEvent("assistant_token", ["token": token])
}
func onComplete() {
guard let service = service else { return }
// 视情况决定是否朗读回复
if speakResponse {
_ = service.azureTtsHelper?.flushStream()
}
if !responseBuilder.isEmpty {
// 发送完整回复,包含是否有图片的标记
var responseData: [String: Any] = [
"text": responseBuilder,
"userInput": displayText
]
if hasImage {
responseData["hasImage"] = true
}
service.sendEvent("assistant_response", responseData)
// 添加AI回复到历史记录
if let assistantMessage = service.openAIService?.createAssistantMessage(text: responseBuilder) {
service.addToHistoryMessages(assistantMessage)
}
// 保存聊天记录
service.saveChatMessage(userMessage: displayText, assistantMessage: responseBuilder)
}
// 标记AI流式输出已完成
service.isAiStreaming = false
service.currentAiTask = nil
}
func onError(error: Error) {
guard let service = service else { return }
print("\(service.TAG): AI处理出错: \(error.localizedDescription)")
service.sendEvent("error", [
"code": "AI_ERROR",
"message": error.localizedDescription
])
// 标记AI流式输出已完成
service.isAiStreaming = false
service.currentAiTask = nil
}
func onFunctionCall(call: [String: Any]) {
guard let service = service else { return }
if let name = call["name"] as? String {
service.sendEvent("function_call", [
"name": name,
"arguments": call
])
if name == "exit_interaction" {
service.stopRecognition()
}
}
}
func onFunctionCallResult(functionCall: [String: Any], functionCallResult: [String: Any]) {
guard let service = service else { return }
service.sendEvent("function_call_result", [
"function_call": functionCall,
"result": functionCallResult,
])
}
}
let callback = StreamCallbackBridge(self, responseBuilder: responseBuilder, speakResponse: speakResponse, displayText: displayText, hasImage: hasImage)
self.openAIService?.sendMessageStream(messages: messagesWithSystemPrompt, callback: callback)
}
// 保存任务引用并在全局队列中执行
currentAiTask = workItem
DispatchQueue.global(qos: .userInitiated).async(execute: workItem)
}
/**
* 加载最近的聊天历史记录
*/
private func loadChatHistory() {
// 清空当前历史记录
historyMessages.removeAll()
// 使用ChatStorageHelper直接获取最近消息
guard let recentMessages = chatStorageHelper?.getRecentMessages(sessionId: sessionId, count: 10) else {
print("\(TAG): 没有找到历史记录")
return
}
// 将消息添加到历史记录
for message in recentMessages {
if let sender = message["sender"] as? String,
let content = message["message"] as? String {
if sender == "user" {
if let userMessage = openAIService?.createUserMessage(text: content) {
addToHistoryMessages(userMessage)
}
} else if sender == "assistant" {
if let assistantMessage = openAIService?.createAssistantMessage(text: content) {
addToHistoryMessages(assistantMessage)
}
}
}
}
print("\(TAG): 已加载\(recentMessages.count)条历史记录")
}
/**
* 添加消息到历史记录,保持最近10条
*/
private func addToHistoryMessages(_ message: [String: Any]) {
// 添加新消息
historyMessages.append(message)
// 如果超过10条,删除最早的消息
while historyMessages.count > 10 {
historyMessages.removeFirst()
}
}
/**
* TTS播放函数
*
* - Parameter text: 要播放的文本
*/
func speakText(text: String) {
if text.isEmpty { return }
// 更新状态
isTtsSpeaking = true
restartIdleCheck() // 状态变化,重启检测
// 播放文本
_ = azureTtsHelper?.speakText(text)
}
/**
* 停止TTS播放
*/
func stopTts() {
if isTtsSpeaking {
_ = azureTtsHelper?.stopSpeaking()
isTtsSpeaking = false
restartIdleCheck() // 状态变化,重启检测
sendEvent("tts_stopped", ["status": "stopped"])
}
}
/**
* 保存聊天消息
*/
private func saveChatMessage(userMessage: String, assistantMessage: String) {
DispatchQueue.global(qos: .background).async { [weak self] in
guard let self = self else { return }
// 保存用户消息
let userMessageId = self.chatStorageHelper?.saveMessage(
sessionId: self.sessionId,
message: userMessage,
sender: "user"
) ?? -1
if userMessageId != -1 {
// 保存AI回复
let assistantMessageId = self.chatStorageHelper?.saveMessage(
sessionId: self.sessionId,
message: assistantMessage,
sender: "assistant"
) ?? -1
if assistantMessageId == -1 {
print("\(self.TAG): 保存助手消息失败")
}
} else {
print("\(self.TAG): 保存用户消息失败")
}
}
}
/**
* 清除聊天历史
*/
func clearChatHistory(completion: @escaping (Bool) -> Void) {
DispatchQueue.global(qos: .background).async { [weak self] in
guard let self = self else {
DispatchQueue.main.async {
completion(false)
}
return
}
// 清除指定会话的所有消息
let success = self.chatStorageHelper?.deleteMessages(sessionId: self.sessionId) ?? false
if success {
// 清空内存中的历史记录
self.historyMessages.removeAll()
print("\(self.TAG): 聊天历史已清除")
} else {
print("\(self.TAG): 清除聊天历史失败")
}
DispatchQueue.main.async {
completion(success)
}
}
}
/**
* 发送事件
*/
private func sendEvent(_ eventName: String, _ data: [String: Any]) {
// 向所有监听器发送事件
let allListeners = listeners.allObjects
for case let listener as AgentServiceListener in allListeners {
listener.onEvent(eventName: eventName, data: data)
}
}
/**
* 释放资源
*/
func dispose() {
stopRecognition()
stopTts()
stopAiStream()
stopIdleCheck()
azureAsrHelper?.dispose()
azureTtsHelper?.dispose()
// 清除所有监听器
clearListeners()
// 重置单例状态,以便下次使用时可以重新初始化
isInitialized = false
print("\(TAG): 代理服务资源已释放")
}
}
// MARK: - AzureTtsHelper.TtsCallback
extension AgentService: AzureTtsHelper.TtsCallback {
func onSynthesisStarted() {
isTtsSpeaking = true
// 状态变化,重置空闲检测
restartIdleCheck()
sendEvent("tts_started", ["status": "started"])
}
func onSynthesizing() {
// 可以在此添加TTS合成中的处理逻辑
}
func onSynthesisCompleted() {
isTtsSpeaking = false
// 状态变化,重启空闲检测
restartIdleCheck()
sendEvent("tts_completed", ["status": "completed"])
}
func onSynthesisCanceled() {
isTtsSpeaking = false
// 状态变化,重启空闲检测
restartIdleCheck()
sendEvent("tts_canceled", ["status": "canceled"])
}
}
// MARK: - 外部插件桥接器
/// 桥接OpenAIService插件
class OpenAIServiceBridge {
private let service = OpenAIService()
/// 初始化服务
func initialize(apiKey: String, baseUrl: String, model: String, mcpServer: String) {
service.initialize(apiKey: apiKey, baseUrl: baseUrl, model: model, mcpServer: mcpServer)
}
/// 创建系统消息
func createSystemMessage(text: String) -> [String: Any] {
return service.createSystemMessage(text)
}
/// 创建用户消息
func createUserMessage(text: String) -> [String: Any] {
return service.createUserMessage(text)
}
/// 创建助手消息
func createAssistantMessage(text: String) -> [String: Any] {
return service.createAssistantMessage(text)
}
/// 创建带图片的用户消息
func createUserMessageWithImage(text: String, imageBase64: String) -> [String: Any]? {
return service.createUserMessageWithImage(text: text, imageBase64: imageBase64)
}
/// 文件转Base64
func fileToBase64(filePath: String) -> String? {
return service.fileToBase64(filePath: filePath)
}
/// 发送流式消息
func sendMessageStream(messages: [[String: Any]], callback: OpenAIStreamCallback) {
service.sendMessageStream(messages: messages, callback: callback)
}
/// 取消当前流
func cancelCurrentStream() {
service.cancelCurrentStream()
}
}
/// OpenAI流式回调协议
@objc protocol OpenAIStreamCallback {
func onToken(token: String)
func onComplete()
func onError(error: Error)
func onFunctionCall(call: [String: Any])
func onFunctionCallResult(functionCall: [String: Any], functionCallResult: [String: Any])
}
/// 桥接ChatStorageHelper插件
class ChatStorageHelperBridge {
private let helper = ChatStorageHelper()
/// 保存消息
func saveMessage(sessionId: String, message: String, sender: String) -> Int64 {
return helper.saveMessage(sessionId: sessionId, message: message, sender: sender)
}
/// 获取最近消息
func getRecentMessages(sessionId: String, count: Int) -> [[String: Any]]? {
return helper.getRecentMessages(sessionId: sessionId, count: count)
}
/// 删除消息
func deleteMessages(sessionId: String) -> Bool {
return helper.deleteMessages(sessionId: sessionId)
}
}