58 lines
1.9 KiB
Swift
58 lines
1.9 KiB
Swift
// Copyright © 2025 Apple Inc.
|
|
|
|
import Foundation
|
|
|
|
public struct ToolCall: Hashable, Codable, Sendable {
|
|
/// Represents the function details for a tool call
|
|
public struct Function: Hashable, Codable, Sendable {
|
|
/// The name of the function
|
|
public let name: String
|
|
|
|
/// The arguments passed to the function
|
|
public let arguments: [String: JSONValue]
|
|
|
|
public init(name: String, arguments: [String: any Sendable]) {
|
|
self.name = name
|
|
self.arguments = arguments.mapValues { JSONValue.from($0) }
|
|
}
|
|
}
|
|
|
|
/// The function to be called
|
|
public let function: Function
|
|
|
|
public init(function: Function) {
|
|
self.function = function
|
|
}
|
|
}
|
|
|
|
extension ToolCall {
|
|
public func execute<Input, Output>(with tool: Tool<Input, Output>) async throws -> Output {
|
|
// Check that the tool name matches the function name
|
|
guard tool.name == function.name else {
|
|
throw ToolError.nameMismatch(toolName: tool.name, functionName: function.name)
|
|
}
|
|
|
|
// Convert the JSONValue arguments dictionary to a JSON-encoded Data object
|
|
let jsonObject = function.arguments.mapValues { $0.anyValue }
|
|
let jsonData = try JSONSerialization.data(withJSONObject: jsonObject)
|
|
|
|
// Decode the Input type from the JSON data
|
|
let input = try JSONDecoder().decode(Input.self, from: jsonData)
|
|
|
|
// Execute the tool's handler with the decoded input
|
|
return try await tool.handler(input)
|
|
}
|
|
}
|
|
|
|
// Define Tool-related errors
|
|
public enum ToolError: Error, LocalizedError {
|
|
case nameMismatch(toolName: String, functionName: String)
|
|
|
|
public var errorDescription: String? {
|
|
switch self {
|
|
case .nameMismatch(let toolName, let functionName):
|
|
return "Tool name mismatch: expected '\(toolName)' but got '\(functionName)'"
|
|
}
|
|
}
|
|
}
|