Skip to content

Commit

Permalink
add Tool objects
Browse files Browse the repository at this point in the history
  • Loading branch information
fumito-ito committed Oct 30, 2024
1 parent 2069387 commit 4efab18
Show file tree
Hide file tree
Showing 6 changed files with 282 additions and 0 deletions.
22 changes: 22 additions & 0 deletions Sources/AnthropicSwiftSDK/Entity/Tool/BashTool.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// BashTool.swift
// AnthropicSwiftSDK
//
// Created by 伊藤史 on 2024/10/29.
//

public struct BashTool {
public enum BashType: String, RawRepresentable, Encodable {
case bash20241022 = "bash_20241022"
}

public let type: BashType
public let name: String

public init(type: BashType = .bash20241022, name: String) {
self.type = type
self.name = name
}
}

extension BashTool: Encodable {}
34 changes: 34 additions & 0 deletions Sources/AnthropicSwiftSDK/Entity/Tool/ComputerTool.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// ComputerTool.swift
// AnthropicSwiftSDK
//
// Created by 伊藤史 on 2024/10/29.
//

public struct ComputerTool {
public enum ComputerType: String, RawRepresentable, Encodable {
case computer20241022 = "computer_20241022"
}

public let type: ComputerType
public let name: String
public let displayWidthPx: Int
public let displayHeightPx: Int
public let displayNumber: Int

public init(
type: ComputerType = .computer20241022,
name: String,
displayWidthPx: Int,
displayHeightPx: Int,
displayNumber: Int
) {
self.type = type
self.name = name
self.displayWidthPx = displayWidthPx
self.displayHeightPx = displayHeightPx
self.displayNumber = displayNumber
}
}

extension ComputerTool: Encodable {}
67 changes: 67 additions & 0 deletions Sources/AnthropicSwiftSDK/Entity/Tool/FunctionTool.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//
// FunctionTool.swift
// AnthropicSwiftSDK
//
// Created by 伊藤史 on 2024/10/29.
//

public struct FunctionTool {
public let name: String
public let description: String
public let inputSchema: InputSchema
}

extension FunctionTool: Encodable {}

public class InputSchema {
public enum SchemaType: String, Encodable {
case string
case number
case integer
case boolean
case arrray
case object
}

public let type: SchemaType
public let format: String?
public let description: String
public let nullable: Bool?
public let enumValues: [String]?
public let items: InputSchema?
public let properties: [String: InputSchema]?
public let requiredProperties: [String]?

init(
type: SchemaType,
format: String?,
description: String,
nullable: Bool?,
enumValues: [String]?,
items: InputSchema?,
properties: [String: InputSchema]?,
requiredProperties: [String]?
) {
self.type = type
self.format = format
self.description = description
self.nullable = nullable
self.enumValues = enumValues
self.items = items
self.properties = properties
self.requiredProperties = requiredProperties
}
}

extension InputSchema: Encodable {
enum CodingKeys: String, CodingKey {
case type
case format
case description
case nullable
case enumValues = "enum"
case items
case properties
case requiredProperties = "required"
}
}
22 changes: 22 additions & 0 deletions Sources/AnthropicSwiftSDK/Entity/Tool/TextEditorTool.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// TextEditorTool.swift
// AnthropicSwiftSDK
//
// Created by 伊藤史 on 2024/10/29.
//

public struct TextEditorTool {
public enum TextEditorType: String, RawRepresentable, Encodable {
case textEditor20241022 = "textEditor_20241022"
}

public let type: TextEditorType
public let name: String

public init(type: TextEditorType = .textEditor20241022, name: String) {
self.type = type
self.name = name
}
}

extension TextEditorTool: Encodable {}
15 changes: 15 additions & 0 deletions Sources/AnthropicSwiftSDK/Entity/Tool/Tool.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// Tool.swift
// AnthropicSwiftSDK
//
// Created by 伊藤史 on 2024/10/28.
//

public enum Tool {
case computer(ComputerTool)
case textEditor(TextEditorTool)
case bash(BashTool)
case function(FunctionTool)
}

extension Tool: Encodable {}
122 changes: 122 additions & 0 deletions Tests/AnthropicSwiftSDKTests/Entity/Tool/ToolTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
//
// ToolTests.swift
// AnthropicSwiftSDK
//
// Created by 伊藤史 on 2024/10/30.
//

import XCTest
@testable import AnthropicSwiftSDK

import XCTest
@testable import AnthropicSwiftSDK

final class ToolTests: XCTestCase {
func testBashToolEncoding() throws {
let tool = BashTool(type: .bash20241022, name: "bash")
let encoded = try anthropicJSONEncoder.encode(tool)
let decoded = try JSONSerialization.jsonObject(with: encoded) as? [String: Any]

XCTAssertEqual(decoded?["type"] as? String, "bash_20241022")
XCTAssertEqual(decoded?["name"] as? String, "bash")
}

func testComputerToolEncoding() throws {
let tool = ComputerTool(
type: .computer20241022,
name: "computer",
displayWidthPx: 1024,
displayHeightPx: 768,
displayNumber: 1
)
let encoded = try anthropicJSONEncoder.encode(tool)
let decoded = try JSONSerialization.jsonObject(with: encoded) as? [String: Any]

XCTAssertEqual(decoded?["type"] as? String, "computer_20241022")
XCTAssertEqual(decoded?["name"] as? String, "computer")
XCTAssertEqual(decoded?["display_width_px"] as? Int, 1024)
XCTAssertEqual(decoded?["display_height_px"] as? Int, 768)
XCTAssertEqual(decoded?["display_number"] as? Int, 1)
}

func testTextEditorToolEncoding() throws {
let tool = TextEditorTool(type: .textEditor20241022, name: "str_replace_editor")
let encoded = try anthropicJSONEncoder.encode(tool)
let decoded = try JSONSerialization.jsonObject(with: encoded) as? [String: Any]

XCTAssertEqual(decoded?["type"] as? String, "textEditor_20241022")
XCTAssertEqual(decoded?["name"] as? String, "str_replace_editor")
}

func testFunctionToolEncoding() throws {
let locationSchema = InputSchema(
type: .string,
format: nil,
description: "The city and state, e.g. San Francisco, CA",
nullable: nil,
enumValues: nil,
items: nil,
properties: nil,
requiredProperties: nil
)

let unitSchema = InputSchema(
type: .string,
format: nil,
description: "The unit of temperature, either 'celsius' or 'fahrenheit'",
nullable: nil,
enumValues: ["celsius", "fahrenheit"],
items: nil,
properties: nil,
requiredProperties: nil
)

let rootSchema = InputSchema(
type: .object,
format: nil,
description: "",
nullable: nil,
enumValues: nil,
items: nil,
properties: [
"location": locationSchema,
"unit": unitSchema
],
requiredProperties: ["location"]
)

let tool = FunctionTool(
name: "get_weather",
description: "Get the current weather in a given location",
inputSchema: rootSchema
)

let encoded = try anthropicJSONEncoder.encode(tool)
let decoded = try JSONSerialization.jsonObject(with: encoded) as? [String: Any]

XCTAssertEqual(decoded?["name"] as? String, "get_weather")
XCTAssertEqual(decoded?["description"] as? String, "Get the current weather in a given location")

let inputSchema = decoded?["input_schema"] as? [String: Any]
XCTAssertEqual(inputSchema?["type"] as? String, "object")
XCTAssertEqual(inputSchema?["description"] as? String, "")

let properties = inputSchema?["properties"] as? [String: Any]
let location = properties?["location"] as? [String: Any]
XCTAssertEqual(location?["type"] as? String, "string")
XCTAssertEqual(location?["description"] as? String, "The city and state, e.g. San Francisco, CA")

let unit = properties?["unit"] as? [String: Any]
XCTAssertEqual(unit?["type"] as? String, "string")
XCTAssertEqual(unit?["description"] as? String, "The unit of temperature, either 'celsius' or 'fahrenheit'")
XCTAssertEqual(unit?["enum"] as? [String], ["celsius", "fahrenheit"])

XCTAssertEqual(inputSchema?["required"] as? [String], ["location"])
}

func testDefaultToolTypes() {
XCTAssertEqual(BashTool.BashType.bash20241022.rawValue, "bash_20241022")
XCTAssertEqual(ComputerTool.ComputerType.computer20241022.rawValue, "computer_20241022")
XCTAssertEqual(TextEditorTool.TextEditorType.textEditor20241022.rawValue, "textEditor_20241022")
}
}

0 comments on commit 4efab18

Please sign in to comment.