import Flutter import UIKit import Foundation /// OpenAI服务插件主类 public class OpenAIServicePlugin: NSObject, FlutterPlugin, FlutterStreamHandler { // MARK: - 常量 private static let methodChannelName = "com.yunqiinnovation.open_ai_service/methods" private static let eventChannelName = "com.yunqiinnovation.open_ai_service/events" // MARK: - 属性 private var methodChannel: FlutterMethodChannel? private var eventChannel: FlutterEventChannel? private var eventSink: FlutterEventSink? private var openAIService: OpenAIService? // MARK: - 插件注册 public static func register(with registrar: FlutterPluginRegistrar) { let instance = OpenAIServicePlugin() // 初始化方法通道 let methodChannel = FlutterMethodChannel( name: methodChannelName, binaryMessenger: registrar.messenger() ) instance.methodChannel = methodChannel registrar.addMethodCallDelegate(instance, channel: methodChannel) // 初始化事件通道 let eventChannel = FlutterEventChannel( name: eventChannelName, binaryMessenger: registrar.messenger() ) instance.eventChannel = eventChannel eventChannel.setStreamHandler(instance) // 初始化OpenAI服务 instance.openAIService = OpenAIService() } // MARK: - FlutterPlugin public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { guard let service = openAIService else { result(FlutterError(code: "SERVICE_NOT_INITIALIZED", message: "OpenAI服务未初始化", details: nil)) return } switch call.method { case "initialize": handleInitialize(call: call, result: result, service: service) case "registerFunction": handleRegisterFunction(call: call, result: result, service: service) case "sendMessage": handleSendMessage(call: call, result: result, service: service) case "sendMessageStream": handleSendMessageStream(call: call, result: result, service: service) case "sendFunctionCallResult": handleSendFunctionCallResult(call: call, result: result, service: service) case "createUserMessage": handleCreateUserMessage(call: call, result: result, service: service) case "createAssistantMessage": handleCreateAssistantMessage(call: call, result: result, service: service) case "initializeMcpClient": handleInitializeMcpClient(call: call, result: result, service: service) case "isMcpInitialized": handleIsMcpInitialized(call: call, result: result, service: service) case "closeMcpClient": handleCloseMcpClient(call: call, result: result, service: service) case "handleMcpToolCall": handleMcpToolCall(call: call, result: result, service: service) default: result(FlutterMethodNotImplemented) } } // MARK: - FlutterStreamHandler public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { self.eventSink = events return nil } public func onCancel(withArguments arguments: Any?) -> FlutterError? { self.eventSink = nil return nil } // MARK: - 方法处理 private func handleInitialize(call: FlutterMethodCall, result: @escaping FlutterResult, service: OpenAIService) { guard let args = call.arguments as? [String: Any], let apiKey = args["apiKey"] as? String else { result(FlutterError(code: "INVALID_ARGUMENTS", message: "缺少必要参数", details: nil)) return } let baseUrl = args["baseUrl"] as? String ?? "" let model = args["model"] as? String ?? "" let mcpServer = args["mcpServer"] as? String ?? "" let success = service.initialize( apiKey: apiKey, baseUrl: baseUrl, model: model, mcpServer: mcpServer ) result(success) } private func handleRegisterFunction(call: FlutterMethodCall, result: @escaping FlutterResult, service: OpenAIService) { guard let args = call.arguments as? [String: Any], let name = args["name"] as? String, let description = args["description"] as? String, let parameters = args["parameters"] as? [String: Any] else { result(FlutterError(code: "INVALID_ARGUMENTS", message: "缺少必要参数", details: nil)) return } let success = service.registerFunction(name: name, description: description, parameters: parameters) result(success) } private func handleSendMessage(call: FlutterMethodCall, result: @escaping FlutterResult, service: OpenAIService) { guard let args = call.arguments as? [String: Any], let messagesArray = args["messages"] as? [[String: Any]] else { result(FlutterError(code: "INVALID_ARGUMENTS", message: "缺少消息参数", details: nil)) return } do { let response = try service.sendMessage(messages: messagesArray) result(response) } catch { result(FlutterError(code: "OPENAI_ERROR", message: error.localizedDescription, details: nil)) } } private func handleSendMessageStream(call: FlutterMethodCall, result: @escaping FlutterResult, service: OpenAIService) { guard let args = call.arguments as? [String: Any], let messagesArray = args["messages"] as? [[String: Any]] else { result(FlutterError(code: "INVALID_ARGUMENTS", message: "缺少消息参数", details: nil)) return } guard let eventSink = self.eventSink else { result(FlutterError(code: "NO_EVENT_SINK", message: "没有可用的事件流接收器", details: nil)) return } // 创建回调处理器 let callback = StreamCallbackImpl(eventSink: eventSink) // 发送流式消息 service.sendMessageStream(messages: messagesArray, callback: callback) result(true) } private func handleSendFunctionCallResult(call: FlutterMethodCall, result: @escaping FlutterResult, service: OpenAIService) { guard let args = call.arguments as? [String: Any], let messagesArray = args["messages"] as? [[String: Any]], let functionCall = args["functionCall"] as? [String: Any], let functionResult = args["functionResult"] as? String else { result(FlutterError(code: "INVALID_ARGUMENTS", message: "缺少必要参数", details: nil)) return } guard let eventSink = self.eventSink else { result(FlutterError(code: "NO_EVENT_SINK", message: "没有可用的事件流接收器", details: nil)) return } // 创建回调处理器 let callback = StreamCallbackImpl(eventSink: eventSink) // 发送函数调用结果 service.sendFunctionCallResult( messages: messagesArray, functionCall: functionCall, functionResult: functionResult, callback: callback ) result(true) } private func handleCreateUserMessage(call: FlutterMethodCall, result: @escaping FlutterResult, service: OpenAIService) { guard let args = call.arguments as? [String: Any], let content = args["content"] as? String else { result(FlutterError(code: "INVALID_ARGUMENTS", message: "缺少内容参数", details: nil)) return } let message = service.createUserMessage(content: content) result(message) } private func handleCreateAssistantMessage(call: FlutterMethodCall, result: @escaping FlutterResult, service: OpenAIService) { guard let args = call.arguments as? [String: Any], let content = args["content"] as? String else { result(FlutterError(code: "INVALID_ARGUMENTS", message: "缺少内容参数", details: nil)) return } let message = service.createAssistantMessage(content: content) result(message) } private func handleInitializeMcpClient(call: FlutterMethodCall, result: @escaping FlutterResult, service: OpenAIService) { guard let args = call.arguments as? [String: Any], let serverUrl = args["serverUrl"] as? String else { result(FlutterError(code: "INVALID_ARGUMENTS", message: "缺少服务器URL参数", details: nil)) return } let success = service.initializeMcpClient(serverUrl: serverUrl) result(success) } private func handleIsMcpInitialized(call: FlutterMethodCall, result: @escaping FlutterResult, service: OpenAIService) { let isInitialized = service.isMcpInitialized() result(isInitialized) } private func handleCloseMcpClient(call: FlutterMethodCall, result: @escaping FlutterResult, service: OpenAIService) { service.closeMcpClient() result(true) } private func handleMcpToolCall(call: FlutterMethodCall, result: @escaping FlutterResult, service: OpenAIService) { guard let args = call.arguments as? [String: Any], let functionCallJson = args["functionCall"] as? String else { result(FlutterError(code: "INVALID_ARGUMENTS", message: "缺少函数调用参数", details: nil)) return } Task { do { let toolResult = try await service.handleMcpToolCall(functionCallJson: functionCallJson) DispatchQueue.main.async { result(toolResult) } } catch { DispatchQueue.main.async { result(FlutterError(code: "MCP_TOOL_ERROR", message: "处理MCP工具调用失败: \(error.localizedDescription)", details: nil)) } } } } } // MARK: - 流式回调实现 private class StreamCallbackImpl: StreamCallback { private let eventSink: FlutterEventSink init(eventSink: @escaping FlutterEventSink) { self.eventSink = eventSink } func onToken(_ token: String) { DispatchQueue.main.async { self.eventSink(["type": "token", "content": token]) } } func onComplete() { DispatchQueue.main.async { self.eventSink(["type": "complete"]) } } func onError(_ error: Error) { DispatchQueue.main.async { self.eventSink(["type": "error", "content": error.localizedDescription]) } } func onFunctionCall(_ functionCall: [String: Any]) { DispatchQueue.main.async { if let jsonData = try? JSONSerialization.data(withJSONObject: functionCall), let jsonString = String(data: jsonData, encoding: .utf8) { self.eventSink(["type": "function_call", "content": jsonString]) } } } func onFunctionCallResult(_ functionCall: [String: Any], _ functionCallResult: [String: Any]) { DispatchQueue.main.async { if let callData = try? JSONSerialization.data(withJSONObject: functionCall), let callString = String(data: callData, encoding: .utf8), let resultData = try? JSONSerialization.data(withJSONObject: functionCallResult), let resultString = String(data: resultData, encoding: .utf8) { self.eventSink([ "type": "function_call_result", "function_call": callString, "result": resultString ]) } } } }