Skip to content

Commit 66716f8

Browse files
authored
Merge pull request #6 from elevenlabs/feat/add-support-for-agent-overrides
feat: add support for agent overrides
2 parents 4fa7270 + e3d91eb commit 66716f8

File tree

1 file changed

+109
-3
lines changed

1 file changed

+109
-3
lines changed

Sources/ElevenLabsSwift/ElevenLabsSwift.swift

+109-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import os.log
55

66
/// Main class for ElevenLabsSwift package
77
public class ElevenLabsSDK {
8-
public static let version = "1.0.0"
8+
public static let version = "1.0.1"
99

1010
private enum Constants {
1111
static let defaultApiOrigin = "wss://api.elevenlabs.io"
@@ -18,6 +18,80 @@ public class ElevenLabsSDK {
1818
static let bufferSize: AVAudioFrameCount = 1024
1919
}
2020

21+
// MARK: - Session Config Utilities
22+
23+
public enum Language: String, Codable, Sendable {
24+
case en, ja, zh, de, hi, fr, ko, pt, it, es, id, nl, tr, pl, sv, bg, ro, ar, cs, el, fi, ms, da, ta, uk, ru, hu, no, vi
25+
}
26+
27+
public struct AgentPrompt: Codable, Sendable {
28+
public var prompt: String?
29+
30+
public init(prompt: String? = nil) {
31+
self.prompt = prompt
32+
}
33+
}
34+
35+
public struct TTSConfig: Codable, Sendable {
36+
public var voiceId: String?
37+
38+
private enum CodingKeys: String, CodingKey {
39+
case voiceId = "voice_id"
40+
}
41+
42+
public init(voiceId: String? = nil) {
43+
self.voiceId = voiceId
44+
}
45+
}
46+
47+
public struct ConversationConfigOverride: Codable, Sendable {
48+
public var agent: AgentConfig?
49+
public var tts: TTSConfig?
50+
51+
public init(agent: AgentConfig? = nil, tts: TTSConfig? = nil) {
52+
self.agent = agent
53+
self.tts = tts
54+
}
55+
}
56+
57+
public struct AgentConfig: Codable, Sendable {
58+
public var prompt: AgentPrompt?
59+
public var firstMessage: String?
60+
public var language: Language?
61+
62+
private enum CodingKeys: String, CodingKey {
63+
case prompt
64+
case firstMessage = "first_message"
65+
case language
66+
}
67+
68+
public init(prompt: AgentPrompt? = nil, firstMessage: String? = nil, language: Language? = nil) {
69+
self.prompt = prompt
70+
self.firstMessage = firstMessage
71+
self.language = language
72+
}
73+
}
74+
75+
public enum LlmExtraBodyValue: Codable, Sendable {
76+
case string(String)
77+
case number(Double)
78+
case boolean(Bool)
79+
case null
80+
case array([LlmExtraBodyValue])
81+
case dictionary([String: LlmExtraBodyValue])
82+
83+
var jsonValue: Any {
84+
switch self {
85+
case let .string(str): return str
86+
case let .number(num): return num
87+
case let .boolean(bool): return bool
88+
case .null: return NSNull()
89+
case let .array(arr): return arr.map { $0.jsonValue }
90+
case let .dictionary(dict): return dict.mapValues { $0.jsonValue }
91+
}
92+
}
93+
}
94+
2195
// MARK: - Audio Utilities
2296

2397
public static func arrayBufferToBase64(_ data: Data) -> String {
@@ -113,15 +187,21 @@ public class ElevenLabsSDK {
113187
public struct SessionConfig: Sendable {
114188
public let signedUrl: String?
115189
public let agentId: String?
190+
public let overrides: ConversationConfigOverride?
191+
public let customLlmExtraBody: [String: LlmExtraBodyValue]?
116192

117-
public init(signedUrl: String) {
193+
public init(signedUrl: String, overrides: ConversationConfigOverride? = nil, customLlmExtraBody: [String: LlmExtraBodyValue]? = nil) {
118194
self.signedUrl = signedUrl
119195
agentId = nil
196+
self.overrides = overrides
197+
self.customLlmExtraBody = customLlmExtraBody
120198
}
121199

122-
public init(agentId: String) {
200+
public init(agentId: String, overrides: ConversationConfigOverride? = nil, customLlmExtraBody: [String: LlmExtraBodyValue]? = nil) {
123201
self.agentId = agentId
124202
signedUrl = nil
203+
self.overrides = overrides
204+
self.customLlmExtraBody = customLlmExtraBody
125205
}
126206
}
127207

@@ -157,6 +237,25 @@ public class ElevenLabsSDK {
157237
let socket = session.webSocketTask(with: url)
158238
socket.resume()
159239

240+
// Always send initialization event
241+
var initEvent: [String: Any] = ["type": "conversation_initiation_client_data"]
242+
243+
// Add overrides if present
244+
if let overrides = config.overrides,
245+
let overridesDict = overrides.dictionary
246+
{
247+
initEvent["conversation_config_override"] = overridesDict
248+
}
249+
250+
// Add custom body if present
251+
if let customBody = config.customLlmExtraBody {
252+
initEvent["custom_llm_extra_body"] = customBody.mapValues { $0.jsonValue }
253+
}
254+
255+
let jsonData = try JSONSerialization.data(withJSONObject: initEvent)
256+
let jsonString = String(data: jsonData, encoding: .utf8)!
257+
try await socket.send(.string(jsonString))
258+
160259
let configData = try await receiveInitialMessage(socket: socket)
161260
return Connection(socket: socket, conversationId: configData.conversationId, sampleRate: configData.sampleRate)
162261
}
@@ -1012,3 +1111,10 @@ private extension Data {
10121111
self = buffer.withUnsafeBufferPointer { Data(buffer: $0) }
10131112
}
10141113
}
1114+
1115+
extension Encodable {
1116+
var dictionary: [String: Any]? {
1117+
guard let data = try? JSONEncoder().encode(self) else { return nil }
1118+
return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)) as? [String: Any]
1119+
}
1120+
}

0 commit comments

Comments
 (0)