Browse Source

上传音量调节代码

newdev_shunjiawei
liwei1dao 1 year ago
parent
commit
77f4d3f656
  1. 2
      local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt
  2. 4
      local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift
  3. 4
      local_plugins/agent_service/ios/agent_service/Sources/agent_service/AudioSessionHub.swift
  4. 77
      local_plugins/chat_api/ios/chat_api/Sources/chat_api/MCPClient.swift
  5. 18
      local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift

2
local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt

@ -888,7 +888,7 @@ object AgentService : CoroutineScope {
responseBuilder.append(token) responseBuilder.append(token)
if (speakResponse && reply && broadcast) { if (speakResponse && reply && broadcast) {
ttsService?.speakStream(token) ttsService?.speakStream(token)
audioPlayer?.stopAudio() // audioPlayer?.stopAudio()
} }
if (reply && token.isNotEmpty()) { if (reply && token.isNotEmpty()) {
// 发送流式回复token // 发送流式回复token

4
local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift

@ -996,7 +996,7 @@ class ChatApiStreamCallback: StreamCallback {
if speakResponse && reply && broadcast{ if speakResponse && reply && broadcast{
try agentService.azureTtsHelper?.speakStream(token) try agentService.azureTtsHelper?.speakStream(token)
try agentService.audioPlayer?.stopAwaitSound() // try agentService.audioPlayer?.stopAwaitSound()
} }
if (reply && token != "") { if (reply && token != "") {
try agentService.sendEvent(name: "assistant_token", data: ["token": token]) try agentService.sendEvent(name: "assistant_token", data: ["token": token])
@ -1142,7 +1142,7 @@ extension AgentServiceImpl: TtsEventListener {
isSpeaking = true isSpeaking = true
restartIdleCheck() restartIdleCheck()
sendEvent(name: "tts_started", data: ["status": "started"]) sendEvent(name: "tts_started", data: ["status": "started"])
audioPlayer?.stopAwaitSound()
case .synthesisCompleted: case .synthesisCompleted:
isSpeaking = false isSpeaking = false
restartIdleCheck() restartIdleCheck()

4
local_plugins/agent_service/ios/agent_service/Sources/agent_service/AudioSessionHub.swift

@ -583,9 +583,9 @@ public class AudioSessionHub {
switch action { switch action {
case .increase: case .increase:
newValue = min(currentValue + 0.1, 1.0) newValue = min(currentValue + 0.2, 1.0) // 从 0.1 改为 0.2 (20%)
case .decrease: case .decrease:
newValue = max(currentValue - 0.1, 0.0) newValue = max(currentValue - 0.2, 0.0) // 从 0.1 改为 0.2 (20%)
case .mute: case .mute:
newValue = 0.0 newValue = 0.0
case .setMax: case .setMax:

77
local_plugins/chat_api/ios/chat_api/Sources/chat_api/MCPClient.swift

@ -28,6 +28,7 @@ public protocol FunctionHandler {
/// - 安全的JSON-RPC消息解析,包含错误修复逻辑 /// - 安全的JSON-RPC消息解析,包含错误修复逻辑
/// - 完整的SSE连接生命周期管理 /// - 完整的SSE连接生命周期管理
/// - 与Android端CustomSseClientTransport功能对等 /// - 与Android端CustomSseClientTransport功能对等
// 在 MCPSubClient 类中添加工具调用超时和重试配置
public class MCPSubClient { public class MCPSubClient {
private let serverId: String private let serverId: String
private let serverUrl: String private let serverUrl: String
@ -47,6 +48,10 @@ public class MCPSubClient {
private var retryCount = 0 private var retryCount = 0
private var reconnectTask: Task<Void, Never>? private var reconnectTask: Task<Void, Never>?
// 工具调用配置 - 添加这两行
private let maxToolCallRetries = 3
private let toolCallTimeout: TimeInterval = 30.0
// 连接状态锁 // 连接状态锁
private let connectionLock = NSLock() private let connectionLock = NSLock()
@ -178,27 +183,55 @@ public class MCPSubClient {
/// 调用工具前检查连接 /// 调用工具前检查连接
public func callTool(name: String, arguments: [String: Any]) async -> [String: Any]? { public func callTool(name: String, arguments: [String: Any]) async -> [String: Any]? {
return await callToolWithRetry(name: name, arguments: arguments, retryCount: 0)
}
private func callToolWithRetry(name: String, arguments: [String: Any], retryCount: Int) async -> [String: Any]? {
print("[MCPSubClient] 工具调用尝试 \(retryCount + 1)/\(maxToolCallRetries + 1): \(name)")
// 先检查连接状态 // 先检查连接状态
if !(await checkConnection()) { if !(await checkConnection()) {
if retryCount < maxToolCallRetries {
print("[MCPSubClient] 连接断开,尝试重连...")
if await connect() {
print("[MCPSubClient] 重连成功,重试工具调用")
return await callToolWithRetry(name: name, arguments: arguments, retryCount: retryCount + 1)
}
}
return [ return [
"content": [[ "content": [[
"type": "text", "type": "text",
"text": "Tool call failed: mcp: service not connected" "text": "工具调用失败,请重试:MCP 服务连接中断"
]], ]],
"isError": true "isError": true
] ]
} }
guard isConnectedFlag, let client = mcpClient else { guard isConnectedFlag, let client = mcpClient else {
return createErrorResult("Not connected to MCP server") if retryCount < maxToolCallRetries {
print("[MCPSubClient] MCP 客户端未连接,尝试重连...")
if await connect() {
return await callToolWithRetry(name: name, arguments: arguments, retryCount: retryCount + 1)
}
}
return createErrorResult("工具调用失败,请重试:MCP 服务未连接")
} }
do { do {
let mcpArguments = convertToMCPValue(arguments) // 使用超时控制的工具调用
let (content, isError) = try await client.callTool(name: name, arguments: mcpArguments) let result = try await withTimeout(seconds: toolCallTimeout) {
let mcpArguments = self.convertToMCPValue(arguments)
return try await client.callTool(name: name, arguments: mcpArguments)
}
let (content, isError) = result
if isError == true { if isError == true {
return createErrorResult("Tool execution failed") if retryCount < maxToolCallRetries {
print("[MCPSubClient] 工具执行失败,重试中...")
return await callToolWithRetry(name: name, arguments: arguments, retryCount: retryCount + 1)
}
return createErrorResult("工具调用失败,请重试:工具执行错误")
} }
var contextText = "" var contextText = ""
@ -225,13 +258,45 @@ public class MCPSubClient {
} }
} }
print("[MCPSubClient] 工具调用成功: \(name)")
return [ return [
"content": [["type": "text", "text": contextText.trimmingCharacters(in: .whitespacesAndNewlines)]], "content": [["type": "text", "text": contextText.trimmingCharacters(in: .whitespacesAndNewlines)]],
"isError": false "isError": false
] ]
} catch is TimeoutError {
print("[MCPSubClient] 工具调用超时: \(name)")
if retryCount < maxToolCallRetries {
print("[MCPSubClient] 超时重试中...")
return await callToolWithRetry(name: name, arguments: arguments, retryCount: retryCount + 1)
}
return createErrorResult("工具调用失败,请重试:连接超时")
} catch { } catch {
return createErrorResult("Tool call failed: \(error.localizedDescription)") print("[MCPSubClient] 工具调用异常: \(name), 错误: \(error.localizedDescription)")
// 检查是否是连接相关错误
let errorDescription = error.localizedDescription.lowercased()
if errorDescription.contains("connection") ||
errorDescription.contains("network") ||
errorDescription.contains("timeout") ||
errorDescription.contains("disconnected") {
if retryCount < maxToolCallRetries {
print("[MCPSubClient] 检测到连接错误,尝试重连并重试...")
// 标记连接断开
isConnectedFlag = false
// 尝试重连
if await connect() {
return await callToolWithRetry(name: name, arguments: arguments, retryCount: retryCount + 1)
}
}
} else if retryCount < maxToolCallRetries {
print("[MCPSubClient] 其他错误,直接重试...")
return await callToolWithRetry(name: name, arguments: arguments, retryCount: retryCount + 1)
}
return createErrorResult("工具调用失败,请重试:\(error.localizedDescription)")
} }
} }

18
local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift

@ -795,7 +795,7 @@ private class GetCurrentTimeHandler: FunctionHandler {
private class MediaPlayHandler: FunctionHandler { private class MediaPlayHandler: FunctionHandler {
func handle(arguments: [String: Any]) async throws -> String { func handle(arguments: [String: Any]) async throws -> String {
NotificationCenter.default.post(name: NSNotification.Name("MediaPlay"), object: nil) NotificationCenter.default.post(name: NSNotification.Name("MediaPlay"), object: nil)
return "{\"result\": \"已开始播放媒体\"}" return "{\"notreply\": true,\"result\": \"已开始播放媒体\"}"
} }
} }
@ -803,7 +803,7 @@ private class MediaPlayHandler: FunctionHandler {
private class MediaPauseHandler: FunctionHandler { private class MediaPauseHandler: FunctionHandler {
func handle(arguments: [String: Any]) async throws -> String { func handle(arguments: [String: Any]) async throws -> String {
NotificationCenter.default.post(name: NSNotification.Name("MediaPause"), object: nil) NotificationCenter.default.post(name: NSNotification.Name("MediaPause"), object: nil)
return "{\"result\": \"已暂停媒体播放\"}" return "{\"broadcast\": true,\"result\": \"已暂停媒体播放\"}"
} }
} }
@ -811,7 +811,7 @@ private class MediaPauseHandler: FunctionHandler {
private class MediaPreviousHandler: FunctionHandler { private class MediaPreviousHandler: FunctionHandler {
func handle(arguments: [String: Any]) async throws -> String { func handle(arguments: [String: Any]) async throws -> String {
NotificationCenter.default.post(name: NSNotification.Name("MediaPrevious"), object: nil) NotificationCenter.default.post(name: NSNotification.Name("MediaPrevious"), object: nil)
return "{\"result\": \"已切换到上一首\"}" return "{\"notreply\": true,\"result\": \"已切换到上一首\"}"
} }
} }
@ -819,7 +819,7 @@ private class MediaPreviousHandler: FunctionHandler {
private class MediaNextHandler: FunctionHandler { private class MediaNextHandler: FunctionHandler {
func handle(arguments: [String: Any]) async throws -> String { func handle(arguments: [String: Any]) async throws -> String {
NotificationCenter.default.post(name: NSNotification.Name("MediaNext"), object: nil) NotificationCenter.default.post(name: NSNotification.Name("MediaNext"), object: nil)
return "{\"result\": \"已切换到下一首\"}" return "{\"notreply\": true,\"result\": \"已切换到下一首\"}"
} }
} }
@ -833,7 +833,7 @@ private class OpenRecorderHandler: FunctionHandler {
} }
} }
return "{\"result\": \"无法打开录音机应用\"}" return "{\"notreply\": true,\"result\": \"无法打开录音机应用\"}"
} }
} }
@ -905,7 +905,7 @@ private class AddVolumeHandler: FunctionHandler {
object: volumeInfo object: volumeInfo
) )
return "{\"result\": \"音量增加请求已发送\"}" return "{\"broadcast\": false,\"result\": \"音量增加请求已发送\"}"
} }
} }
@ -921,7 +921,7 @@ private class ReduceVolumeHandler: FunctionHandler {
object: volumeInfo object: volumeInfo
) )
return "{\"result\": \"音量降低请求已发送\"}" return "{\"broadcast\": false,\"result\": \"音量降低请求已发送\"}"
} }
} }
@ -937,7 +937,7 @@ private class MuteVolumeHandler: FunctionHandler {
object: volumeInfo object: volumeInfo
) )
return "{\"result\": \"静音请求已发送\"}" return "{\"broadcast\": false,\"result\": \"静音请求已发送\"}"
} }
} }
@ -953,6 +953,6 @@ private class MaxVolumeHandler: FunctionHandler {
object: volumeInfo object: volumeInfo
) )
return "{\"result\": \"最大音量请求已发送\"}" return "{\"broadcast\": false,\"result\": \"最大音量请求已发送\"}"
} }
} }

Loading…
Cancel
Save