Skip to content

Commit b0869f1

Browse files
committed
Transform Role to a struct
1 parent 4b33006 commit b0869f1

File tree

3 files changed

+57
-12
lines changed

3 files changed

+57
-12
lines changed

Sources/BedrockServiceError.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ public enum BedrockLibraryError: Error {
6666
case .invalidSDKResponse(let message):
6767
return "Invalid SDK response: \(message)"
6868
case .invalidSDKResponseBody(let value):
69-
return "Invalid SDK response body: \(String(describing: value))"
69+
let valueAsString = value != nil ? String(data: value!, encoding: .utf8) ?? "" : "nil"
70+
return "Invalid SDK response body: \(valueAsString)"
7071
case .completionNotFound(let message):
7172
return "Completion not found: \(message)"
7273
case .encodingError(let message):

Sources/Converse/Role.swift

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@
1616
@preconcurrency import AWSBedrockRuntime
1717
import Foundation
1818

19-
public enum Role: String, Codable, Sendable {
20-
case user
21-
case assistant
19+
public struct Role: Codable, Sendable, Equatable {
20+
private enum RoleType: Codable, Sendable, Equatable {
21+
case user
22+
case assistant
23+
}
24+
25+
private let type: RoleType
2226

2327
public init(from sdkConversationRole: BedrockRuntimeClientTypes.ConversationRole) throws {
2428
switch sdkConversationRole {
25-
case .user: self = .user
26-
case .assistant: self = .assistant
29+
case .user: self.type = .user
30+
case .assistant: self.type = .assistant
2731
case .sdkUnknown(let unknownRole):
2832
throw BedrockLibraryError.notImplemented(
2933
"Role \(unknownRole) is not implemented by BedrockRuntimeClientTypes"
@@ -32,9 +36,47 @@ public enum Role: String, Codable, Sendable {
3236
}
3337

3438
public func getSDKConversationRole() -> BedrockRuntimeClientTypes.ConversationRole {
35-
switch self {
39+
switch self.type {
3640
case .user: return .user
3741
case .assistant: return .assistant
3842
}
3943
}
44+
45+
// custom encoding and decoding to handle string value with a "type" field
46+
/*
47+
"message":{
48+
"content":[
49+
{"text":"This is the textcompletion for: This is a test"}
50+
],
51+
"role":"assistant"
52+
}},
53+
*/
54+
public init(from decoder: any Decoder) throws {
55+
let container = try decoder.singleValueContainer()
56+
let role = try container.decode(String.self)
57+
switch role {
58+
case "user": self.type = .user
59+
case "assistant": self.type = .assistant
60+
default:
61+
throw BedrockLibraryError.decodingError(
62+
"Role \(role) is not a valid role"
63+
)
64+
}
65+
}
66+
public func encode(to encoder: any Encoder) throws {
67+
var container = encoder.singleValueContainer()
68+
switch self.type {
69+
case .user: try container.encode("user")
70+
case .assistant: try container.encode("assistant")
71+
}
72+
}
73+
/// Returns the type of the role as a string.
74+
public static func == (lhs: Role, rhs: Role) -> Bool {
75+
lhs.type == rhs.type
76+
}
77+
private init(_ type: RoleType) {
78+
self.type = type
79+
}
80+
public static let user = Role(.user)
81+
public static let assistant = Role(.assistant)
4082
}

Tests/InvokeModel/TextGenerationTests.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@ extension BedrockServiceTests {
2727
arguments: NovaTestConstants.textCompletionModels
2828
)
2929
func completeTextWithValidModel(model: BedrockModel) async throws {
30-
let completion: TextCompletion = try await bedrock.completeText(
31-
"This is a test",
32-
with: model
33-
)
34-
#expect(completion.completion == "This is the textcompletion for: This is a test")
30+
await #expect(throws: Never.self) {
31+
let completion: TextCompletion = try await bedrock.completeText(
32+
"This is a test",
33+
with: model
34+
)
35+
#expect(completion.completion == "This is the textcompletion for: This is a test")
36+
}
3537
}
3638

3739
@Test(

0 commit comments

Comments
 (0)