|
1
|
// Copyright 2026 Splitfire AB (Onde Inference). All rights reserved. |
|
2
|
// SPDX-License-Identifier: MIT OR Apache-2.0 |
|
3
|
|
|
4
|
import ExpoModulesCore |
|
5
|
import Foundation |
|
6
|
|
|
7
|
private let ondeAppGroupIdentifier = "group.com.ondeinference.apps" |
|
8
|
|
|
9
|
// MARK: - Rust C FFI declarations |
|
10
|
|
|
11
|
// Engine lifecycle |
|
12
|
@_silgen_name("onde_engine_create") |
|
13
|
func onde_engine_create() -> UnsafeMutableRawPointer? |
|
14
|
|
|
15
|
@_silgen_name("onde_engine_destroy") |
|
16
|
func onde_engine_destroy(_ engine: UnsafeMutableRawPointer) |
|
17
|
|
|
18
|
// Model loading / unloading |
|
19
|
@_silgen_name("onde_engine_load_default_model") |
|
20
|
func onde_engine_load_default_model( |
|
21
|
_ engine: UnsafeMutableRawPointer, |
|
22
|
_ systemPrompt: UnsafePointer<CChar>?, |
|
23
|
_ samplingJson: UnsafePointer<CChar>? |
|
24
|
) -> UnsafeMutablePointer<CChar>? |
|
25
|
|
|
26
|
@_silgen_name("onde_engine_load_model") |
|
27
|
func onde_engine_load_model( |
|
28
|
_ engine: UnsafeMutableRawPointer, |
|
29
|
_ configJson: UnsafePointer<CChar>, |
|
30
|
_ systemPrompt: UnsafePointer<CChar>?, |
|
31
|
_ samplingJson: UnsafePointer<CChar>? |
|
32
|
) -> UnsafeMutablePointer<CChar>? |
|
33
|
|
|
34
|
@_silgen_name("onde_engine_load_uqff_model") |
|
35
|
func onde_engine_load_uqff_model( |
|
36
|
_ engine: UnsafeMutableRawPointer, |
|
37
|
_ configJson: UnsafePointer<CChar>, |
|
38
|
_ systemPrompt: UnsafePointer<CChar>?, |
|
39
|
_ samplingJson: UnsafePointer<CChar>? |
|
40
|
) -> UnsafeMutablePointer<CChar>? |
|
41
|
|
|
42
|
@_silgen_name("onde_engine_unload_model") |
|
43
|
func onde_engine_unload_model(_ engine: UnsafeMutableRawPointer) -> UnsafeMutablePointer<CChar>? |
|
44
|
|
|
45
|
@_silgen_name("onde_engine_is_loaded") |
|
46
|
func onde_engine_is_loaded(_ engine: UnsafeMutableRawPointer) -> Bool |
|
47
|
|
|
48
|
// Engine info |
|
49
|
@_silgen_name("onde_engine_info") |
|
50
|
func onde_engine_info(_ engine: UnsafeMutableRawPointer) -> UnsafeMutablePointer<CChar>? |
|
51
|
|
|
52
|
// System prompt |
|
53
|
@_silgen_name("onde_engine_set_system_prompt") |
|
54
|
func onde_engine_set_system_prompt( |
|
55
|
_ engine: UnsafeMutableRawPointer, _ prompt: UnsafePointer<CChar>) |
|
56
|
|
|
57
|
@_silgen_name("onde_engine_clear_system_prompt") |
|
58
|
func onde_engine_clear_system_prompt(_ engine: UnsafeMutableRawPointer) |
|
59
|
|
|
60
|
// Sampling |
|
61
|
@_silgen_name("onde_engine_set_sampling") |
|
62
|
func onde_engine_set_sampling( |
|
63
|
_ engine: UnsafeMutableRawPointer, _ samplingJson: UnsafePointer<CChar>) |
|
64
|
|
|
65
|
// History |
|
66
|
@_silgen_name("onde_engine_history") |
|
67
|
func onde_engine_history(_ engine: UnsafeMutableRawPointer) -> UnsafeMutablePointer<CChar>? |
|
68
|
|
|
69
|
@_silgen_name("onde_engine_clear_history") |
|
70
|
func onde_engine_clear_history(_ engine: UnsafeMutableRawPointer) -> UInt64 |
|
71
|
|
|
72
|
@_silgen_name("onde_engine_push_history") |
|
73
|
func onde_engine_push_history( |
|
74
|
_ engine: UnsafeMutableRawPointer, _ messageJson: UnsafePointer<CChar>) |
|
75
|
|
|
76
|
// Inference |
|
77
|
@_silgen_name("onde_engine_send_message") |
|
78
|
func onde_engine_send_message( |
|
79
|
_ engine: UnsafeMutableRawPointer, |
|
80
|
_ message: UnsafePointer<CChar> |
|
81
|
) -> UnsafeMutablePointer<CChar>? |
|
82
|
|
|
83
|
@_silgen_name("onde_engine_generate") |
|
84
|
func onde_engine_generate( |
|
85
|
_ engine: UnsafeMutableRawPointer, |
|
86
|
_ messagesJson: UnsafePointer<CChar>, |
|
87
|
_ samplingJson: UnsafePointer<CChar>? |
|
88
|
) -> UnsafeMutablePointer<CChar>? |
|
89
|
|
|
90
|
// Model config free functions |
|
91
|
@_silgen_name("onde_default_model_config") |
|
92
|
func onde_default_model_config() -> UnsafeMutablePointer<CChar>? |
|
93
|
|
|
94
|
@_silgen_name("onde_uqff_model_config") |
|
95
|
func onde_uqff_model_config( |
|
96
|
_ modelId: UnsafePointer<CChar>, |
|
97
|
_ filesJson: UnsafePointer<CChar>, |
|
98
|
_ displayName: UnsafePointer<CChar>, |
|
99
|
_ approxMemory: UnsafePointer<CChar>, |
|
100
|
_ chatTemplate: UnsafePointer<CChar>? |
|
101
|
) -> UnsafeMutablePointer<CChar>? |
|
102
|
|
|
103
|
@_silgen_name("onde_qwen25_1_5b_config") |
|
104
|
func onde_qwen25_1_5b_config() -> UnsafeMutablePointer<CChar>? |
|
105
|
|
|
106
|
@_silgen_name("onde_qwen25_3b_config") |
|
107
|
func onde_qwen25_3b_config() -> UnsafeMutablePointer<CChar>? |
|
108
|
|
|
109
|
@_silgen_name("onde_qwen3_0_6b_config") |
|
110
|
func onde_qwen3_0_6b_config() -> UnsafeMutablePointer<CChar>? |
|
111
|
|
|
112
|
@_silgen_name("onde_qwen3_1_7b_config") |
|
113
|
func onde_qwen3_1_7b_config() -> UnsafeMutablePointer<CChar>? |
|
114
|
|
|
115
|
@_silgen_name("onde_qwen3_4b_config") |
|
116
|
func onde_qwen3_4b_config() -> UnsafeMutablePointer<CChar>? |
|
117
|
|
|
118
|
@_silgen_name("onde_qwen3_8b_config") |
|
119
|
func onde_qwen3_8b_config() -> UnsafeMutablePointer<CChar>? |
|
120
|
|
|
121
|
@_silgen_name("onde_qwen3_14b_config") |
|
122
|
func onde_qwen3_14b_config() -> UnsafeMutablePointer<CChar>? |
|
123
|
|
|
124
|
@_silgen_name("onde_qwen3_32b_config") |
|
125
|
func onde_qwen3_32b_config() -> UnsafeMutablePointer<CChar>? |
|
126
|
|
|
127
|
@_silgen_name("onde_qwen3_4b_instruct_2507_config") |
|
128
|
func onde_qwen3_4b_instruct_2507_config() -> UnsafeMutablePointer<CChar>? |
|
129
|
|
|
130
|
@_silgen_name("onde_qwen3_4b_thinking_2507_config") |
|
131
|
func onde_qwen3_4b_thinking_2507_config() -> UnsafeMutablePointer<CChar>? |
|
132
|
|
|
133
|
@_silgen_name("onde_qwen3_30b_a3b_instruct_2507_config") |
|
134
|
func onde_qwen3_30b_a3b_instruct_2507_config() -> UnsafeMutablePointer<CChar>? |
|
135
|
|
|
136
|
// Sampling config free functions |
|
137
|
@_silgen_name("onde_default_sampling_config") |
|
138
|
func onde_default_sampling_config() -> UnsafeMutablePointer<CChar>? |
|
139
|
|
|
140
|
@_silgen_name("onde_deterministic_sampling_config") |
|
141
|
func onde_deterministic_sampling_config() -> UnsafeMutablePointer<CChar>? |
|
142
|
|
|
143
|
@_silgen_name("onde_mobile_sampling_config") |
|
144
|
func onde_mobile_sampling_config() -> UnsafeMutablePointer<CChar>? |
|
145
|
|
|
146
|
// Memory management |
|
147
|
@_silgen_name("onde_free_string") |
|
148
|
func onde_free_string(_ ptr: UnsafeMutablePointer<CChar>?) |
|
149
|
|
|
150
|
// MARK: - Error types |
|
151
|
|
|
152
|
enum OndeError: Error, CustomStringConvertible { |
|
153
|
case engineNotInitialized |
|
154
|
case invalidResponse |
|
155
|
case inferenceError(String) |
|
156
|
|
|
157
|
var description: String { |
|
158
|
switch self { |
|
159
|
case .engineNotInitialized: |
|
160
|
return "Onde engine is not initialized" |
|
161
|
case .invalidResponse: |
|
162
|
return "Invalid response from Onde engine" |
|
163
|
case .inferenceError(let message): |
|
164
|
return "Onde inference error: \(message)" |
|
165
|
} |
|
166
|
} |
|
167
|
} |
|
168
|
|
|
169
|
// MARK: - Expo Module |
|
170
|
|
|
171
|
public class OndeInferenceModule: Module { |
|
172
|
private var enginePtr: UnsafeMutableRawPointer? |
|
173
|
|
|
174
|
// MARK: Helpers |
|
175
|
|
|
176
|
private func configureApplicationFilesystem() throws { |
|
177
|
let fileManager = FileManager.default |
|
178
|
|
|
179
|
let containerDirectory: URL |
|
180
|
if let appGroupDirectory = fileManager.containerURL( |
|
181
|
forSecurityApplicationGroupIdentifier: ondeAppGroupIdentifier |
|
182
|
) { |
|
183
|
containerDirectory = appGroupDirectory |
|
184
|
} else { |
|
185
|
containerDirectory = try fileManager.url( |
|
186
|
for: .applicationSupportDirectory, |
|
187
|
in: .userDomainMask, |
|
188
|
appropriateFor: nil, |
|
189
|
create: true |
|
190
|
) |
|
191
|
} |
|
192
|
|
|
193
|
let hfHomeDirectory = containerDirectory.appendingPathComponent("models", isDirectory: true) |
|
194
|
let hfHubCacheDirectory = hfHomeDirectory.appendingPathComponent("hub", isDirectory: true) |
|
195
|
let tempDirectory = containerDirectory.appendingPathComponent("tmp", isDirectory: true) |
|
196
|
|
|
197
|
try fileManager.createDirectory(at: hfHomeDirectory, withIntermediateDirectories: true) |
|
198
|
try fileManager.createDirectory(at: hfHubCacheDirectory, withIntermediateDirectories: true) |
|
199
|
try fileManager.createDirectory(at: tempDirectory, withIntermediateDirectories: true) |
|
200
|
|
|
201
|
setenv("HF_HOME", hfHomeDirectory.path, 1) |
|
202
|
setenv("HF_HUB_CACHE", hfHubCacheDirectory.path, 1) |
|
203
|
setenv("HUGGINGFACE_HUB_CACHE", hfHubCacheDirectory.path, 1) |
|
204
|
setenv("TMPDIR", tempDirectory.path, 1) |
|
205
|
} |
|
206
|
|
|
207
|
/// Consume a Rust-allocated C string: copy it into a Swift `String`, then |
|
208
|
/// free the original allocation via `onde_free_string`. |
|
209
|
private func consumeRustString(_ ptr: UnsafeMutablePointer<CChar>?) -> String? { |
|
210
|
guard let ptr = ptr else { return nil } |
|
211
|
let str = String(cString: ptr) |
|
212
|
onde_free_string(ptr) |
|
213
|
return str |
|
214
|
} |
|
215
|
|
|
216
|
/// Validate a JSON string returned by the Rust FFI. |
|
217
|
/// If the JSON contains an `"error"` key, throw an `OndeError.inferenceError`. |
|
218
|
/// Otherwise return the original JSON string unchanged so the TypeScript |
|
219
|
/// wrapper can parse it consistently. |
|
220
|
private func validateJsonResult(_ json: String?) throws -> String { |
|
221
|
guard let json = json, |
|
222
|
let data = json.data(using: .utf8), |
|
223
|
let dict = try JSONSerialization.jsonObject(with: data) as? [String: Any] |
|
224
|
else { |
|
225
|
throw OndeError.invalidResponse |
|
226
|
} |
|
227
|
if let error = dict["error"] as? String { |
|
228
|
throw OndeError.inferenceError(error) |
|
229
|
} |
|
230
|
return json |
|
231
|
} |
|
232
|
|
|
233
|
/// Validate that a JSON string is an array payload and return it unchanged. |
|
234
|
private func validateJsonArray(_ json: String?) throws -> String { |
|
235
|
guard let json = json, |
|
236
|
let data = json.data(using: .utf8), |
|
237
|
(try JSONSerialization.jsonObject(with: data) as? [[String: Any]]) != nil |
|
238
|
else { |
|
239
|
throw OndeError.invalidResponse |
|
240
|
} |
|
241
|
return json |
|
242
|
} |
|
243
|
|
|
244
|
// MARK: Module definition |
|
245
|
|
|
246
|
public func definition() -> ModuleDefinition { |
|
247
|
Name("OndeInference") |
|
248
|
|
|
249
|
OnCreate { |
|
250
|
do { |
|
251
|
try self.configureApplicationFilesystem() |
|
252
|
self.enginePtr = onde_engine_create() |
|
253
|
} catch { |
|
254
|
self.enginePtr = nil |
|
255
|
} |
|
256
|
} |
|
257
|
|
|
258
|
OnDestroy { |
|
259
|
if let ptr = self.enginePtr { |
|
260
|
onde_engine_destroy(ptr) |
|
261
|
self.enginePtr = nil |
|
262
|
} |
|
263
|
} |
|
264
|
|
|
265
|
// MARK: Sync functions |
|
266
|
|
|
267
|
Function("isLoaded") { () -> Bool in |
|
268
|
guard let ptr = self.enginePtr else { return false } |
|
269
|
return onde_engine_is_loaded(ptr) |
|
270
|
} |
|
271
|
|
|
272
|
Function("setSystemPrompt") { (prompt: String) in |
|
273
|
guard let ptr = self.enginePtr else { return } |
|
274
|
prompt.withCString { cPrompt in |
|
275
|
onde_engine_set_system_prompt(ptr, cPrompt) |
|
276
|
} |
|
277
|
} |
|
278
|
|
|
279
|
Function("clearSystemPrompt") { () in |
|
280
|
guard let ptr = self.enginePtr else { return } |
|
281
|
onde_engine_clear_system_prompt(ptr) |
|
282
|
} |
|
283
|
|
|
284
|
Function("setSampling") { (samplingJson: String) in |
|
285
|
guard let ptr = self.enginePtr else { return } |
|
286
|
samplingJson.withCString { cJson in |
|
287
|
onde_engine_set_sampling(ptr, cJson) |
|
288
|
} |
|
289
|
} |
|
290
|
|
|
291
|
Function("clearHistory") { () -> Int in |
|
292
|
guard let ptr = self.enginePtr else { return 0 } |
|
293
|
return Int(onde_engine_clear_history(ptr)) |
|
294
|
} |
|
295
|
|
|
296
|
Function("pushHistory") { (messageJson: String) in |
|
297
|
guard let ptr = self.enginePtr else { return } |
|
298
|
messageJson.withCString { cJson in |
|
299
|
onde_engine_push_history(ptr, cJson) |
|
300
|
} |
|
301
|
} |
|
302
|
|
|
303
|
// MARK: Config free functions (no engine needed) |
|
304
|
|
|
305
|
Function("defaultModelConfig") { () -> String in |
|
306
|
let result = self.consumeRustString(onde_default_model_config()) |
|
307
|
return try self.validateJsonResult(result) |
|
308
|
} |
|
309
|
|
|
310
|
Function("uqffModelConfig") { |
|
311
|
( |
|
312
|
modelId: String, |
|
313
|
filesJson: String, |
|
314
|
displayName: String, |
|
315
|
approxMemory: String, |
|
316
|
chatTemplate: String? |
|
317
|
) -> String in |
|
318
|
let result = modelId.withCString { cModelId in |
|
319
|
filesJson.withCString { cFilesJson in |
|
320
|
displayName.withCString { cDisplayName in |
|
321
|
approxMemory.withCString { cApproxMemory in |
|
322
|
if let chatTemplate = chatTemplate { |
|
323
|
return chatTemplate.withCString { cChatTemplate in |
|
324
|
self.consumeRustString( |
|
325
|
onde_uqff_model_config( |
|
326
|
cModelId, |
|
327
|
cFilesJson, |
|
328
|
cDisplayName, |
|
329
|
cApproxMemory, |
|
330
|
cChatTemplate |
|
331
|
)) |
|
332
|
} |
|
333
|
} else { |
|
334
|
return self.consumeRustString( |
|
335
|
onde_uqff_model_config( |
|
336
|
cModelId, |
|
337
|
cFilesJson, |
|
338
|
cDisplayName, |
|
339
|
cApproxMemory, |
|
340
|
nil |
|
341
|
)) |
|
342
|
} |
|
343
|
} |
|
344
|
} |
|
345
|
} |
|
346
|
} |
|
347
|
return try self.validateJsonResult(result) |
|
348
|
} |
|
349
|
|
|
350
|
Function("qwen251_5bConfig") { () -> String in |
|
351
|
let result = self.consumeRustString(onde_qwen25_1_5b_config()) |
|
352
|
return try self.validateJsonResult(result) |
|
353
|
} |
|
354
|
|
|
355
|
Function("qwen253bConfig") { () -> String in |
|
356
|
let result = self.consumeRustString(onde_qwen25_3b_config()) |
|
357
|
return try self.validateJsonResult(result) |
|
358
|
} |
|
359
|
|
|
360
|
Function("qwen3_0_6bConfig") { () -> String in |
|
361
|
try self.validateJsonResult(self.consumeRustString(onde_qwen3_0_6b_config())) |
|
362
|
} |
|
363
|
|
|
364
|
Function("qwen3_1_7bConfig") { () -> String in |
|
365
|
try self.validateJsonResult(self.consumeRustString(onde_qwen3_1_7b_config())) |
|
366
|
} |
|
367
|
|
|
368
|
Function("qwen3_4bConfig") { () -> String in |
|
369
|
try self.validateJsonResult(self.consumeRustString(onde_qwen3_4b_config())) |
|
370
|
} |
|
371
|
|
|
372
|
Function("qwen3_8bConfig") { () -> String in |
|
373
|
try self.validateJsonResult(self.consumeRustString(onde_qwen3_8b_config())) |
|
374
|
} |
|
375
|
|
|
376
|
Function("qwen3_14bConfig") { () -> String in |
|
377
|
try self.validateJsonResult(self.consumeRustString(onde_qwen3_14b_config())) |
|
378
|
} |
|
379
|
|
|
380
|
Function("qwen3_32bConfig") { () -> String in |
|
381
|
try self.validateJsonResult(self.consumeRustString(onde_qwen3_32b_config())) |
|
382
|
} |
|
383
|
|
|
384
|
Function("qwen3_4bInstruct2507Config") { () -> String in |
|
385
|
try self.validateJsonResult( |
|
386
|
self.consumeRustString(onde_qwen3_4b_instruct_2507_config())) |
|
387
|
} |
|
388
|
|
|
389
|
Function("qwen3_4bThinking2507Config") { () -> String in |
|
390
|
try self.validateJsonResult( |
|
391
|
self.consumeRustString(onde_qwen3_4b_thinking_2507_config())) |
|
392
|
} |
|
393
|
|
|
394
|
Function("qwen3_30bA3bInstruct2507Config") { () -> String in |
|
395
|
try self.validateJsonResult( |
|
396
|
self.consumeRustString(onde_qwen3_30b_a3b_instruct_2507_config())) |
|
397
|
} |
|
398
|
|
|
399
|
Function("defaultSamplingConfig") { () -> String in |
|
400
|
let result = self.consumeRustString(onde_default_sampling_config()) |
|
401
|
return try self.validateJsonResult(result) |
|
402
|
} |
|
403
|
|
|
404
|
Function("deterministicSamplingConfig") { () -> String in |
|
405
|
let result = self.consumeRustString(onde_deterministic_sampling_config()) |
|
406
|
return try self.validateJsonResult(result) |
|
407
|
} |
|
408
|
|
|
409
|
Function("mobileSamplingConfig") { () -> String in |
|
410
|
let result = self.consumeRustString(onde_mobile_sampling_config()) |
|
411
|
return try self.validateJsonResult(result) |
|
412
|
} |
|
413
|
|
|
414
|
// MARK: Async functions |
|
415
|
|
|
416
|
AsyncFunction("loadDefaultModel") { |
|
417
|
(systemPrompt: String?, samplingJson: String?) -> String in |
|
418
|
try self.configureApplicationFilesystem() |
|
419
|
guard let ptr = self.enginePtr else { |
|
420
|
throw OndeError.engineNotInitialized |
|
421
|
} |
|
422
|
let result: String? |
|
423
|
if let sp = systemPrompt, let sj = samplingJson { |
|
424
|
result = sp.withCString { cSp in |
|
425
|
sj.withCString { cSj in |
|
426
|
self.consumeRustString(onde_engine_load_default_model(ptr, cSp, cSj)) |
|
427
|
} |
|
428
|
} |
|
429
|
} else if let sp = systemPrompt { |
|
430
|
result = sp.withCString { cSp in |
|
431
|
self.consumeRustString(onde_engine_load_default_model(ptr, cSp, nil)) |
|
432
|
} |
|
433
|
} else if let sj = samplingJson { |
|
434
|
result = sj.withCString { cSj in |
|
435
|
self.consumeRustString(onde_engine_load_default_model(ptr, nil, cSj)) |
|
436
|
} |
|
437
|
} else { |
|
438
|
result = self.consumeRustString(onde_engine_load_default_model(ptr, nil, nil)) |
|
439
|
} |
|
440
|
return try self.validateJsonResult(result) |
|
441
|
} |
|
442
|
|
|
443
|
AsyncFunction("loadModel") { |
|
444
|
(configJson: String, systemPrompt: String?, samplingJson: String?) -> String in |
|
445
|
try self.configureApplicationFilesystem() |
|
446
|
guard let ptr = self.enginePtr else { |
|
447
|
throw OndeError.engineNotInitialized |
|
448
|
} |
|
449
|
let result: String? = configJson.withCString { cConfig in |
|
450
|
if let sp = systemPrompt, let sj = samplingJson { |
|
451
|
return sp.withCString { cSp in |
|
452
|
sj.withCString { cSj in |
|
453
|
self.consumeRustString(onde_engine_load_model(ptr, cConfig, cSp, cSj)) |
|
454
|
} |
|
455
|
} |
|
456
|
} else if let sp = systemPrompt { |
|
457
|
return sp.withCString { cSp in |
|
458
|
self.consumeRustString(onde_engine_load_model(ptr, cConfig, cSp, nil)) |
|
459
|
} |
|
460
|
} else if let sj = samplingJson { |
|
461
|
return sj.withCString { cSj in |
|
462
|
self.consumeRustString(onde_engine_load_model(ptr, cConfig, nil, cSj)) |
|
463
|
} |
|
464
|
} else { |
|
465
|
return self.consumeRustString(onde_engine_load_model(ptr, cConfig, nil, nil)) |
|
466
|
} |
|
467
|
} |
|
468
|
return try self.validateJsonResult(result) |
|
469
|
} |
|
470
|
|
|
471
|
AsyncFunction("loadUqffModel") { |
|
472
|
(configJson: String, systemPrompt: String?, samplingJson: String?) -> String in |
|
473
|
try self.configureApplicationFilesystem() |
|
474
|
guard let ptr = self.enginePtr else { |
|
475
|
throw OndeError.engineNotInitialized |
|
476
|
} |
|
477
|
let result: String? = configJson.withCString { cConfig in |
|
478
|
if let sp = systemPrompt, let sj = samplingJson { |
|
479
|
return sp.withCString { cSp in |
|
480
|
sj.withCString { cSj in |
|
481
|
self.consumeRustString( |
|
482
|
onde_engine_load_uqff_model(ptr, cConfig, cSp, cSj)) |
|
483
|
} |
|
484
|
} |
|
485
|
} else if let sp = systemPrompt { |
|
486
|
return sp.withCString { cSp in |
|
487
|
self.consumeRustString(onde_engine_load_uqff_model(ptr, cConfig, cSp, nil)) |
|
488
|
} |
|
489
|
} else if let sj = samplingJson { |
|
490
|
return sj.withCString { cSj in |
|
491
|
self.consumeRustString(onde_engine_load_uqff_model(ptr, cConfig, nil, cSj)) |
|
492
|
} |
|
493
|
} else { |
|
494
|
return self.consumeRustString( |
|
495
|
onde_engine_load_uqff_model(ptr, cConfig, nil, nil)) |
|
496
|
} |
|
497
|
} |
|
498
|
return try self.validateJsonResult(result) |
|
499
|
} |
|
500
|
|
|
501
|
AsyncFunction("unloadModel") { () -> String in |
|
502
|
guard let ptr = self.enginePtr else { |
|
503
|
throw OndeError.engineNotInitialized |
|
504
|
} |
|
505
|
let result = self.consumeRustString(onde_engine_unload_model(ptr)) |
|
506
|
return try self.validateJsonResult(result) |
|
507
|
} |
|
508
|
|
|
509
|
AsyncFunction("info") { () -> String in |
|
510
|
guard let ptr = self.enginePtr else { |
|
511
|
throw OndeError.engineNotInitialized |
|
512
|
} |
|
513
|
let result = self.consumeRustString(onde_engine_info(ptr)) |
|
514
|
return try self.validateJsonResult(result) |
|
515
|
} |
|
516
|
|
|
517
|
AsyncFunction("history") { () -> String in |
|
518
|
guard let ptr = self.enginePtr else { return "[]" } |
|
519
|
let result = self.consumeRustString(onde_engine_history(ptr)) |
|
520
|
return try self.validateJsonArray(result) |
|
521
|
} |
|
522
|
|
|
523
|
AsyncFunction("sendMessage") { (message: String) -> String in |
|
524
|
guard let ptr = self.enginePtr else { |
|
525
|
throw OndeError.engineNotInitialized |
|
526
|
} |
|
527
|
let result = message.withCString { cMessage in |
|
528
|
self.consumeRustString(onde_engine_send_message(ptr, cMessage)) |
|
529
|
} |
|
530
|
return try self.validateJsonResult(result) |
|
531
|
} |
|
532
|
|
|
533
|
AsyncFunction("generate") { |
|
534
|
(messagesJson: String, samplingJson: String?) -> String in |
|
535
|
guard let ptr = self.enginePtr else { |
|
536
|
throw OndeError.engineNotInitialized |
|
537
|
} |
|
538
|
let result: String? = messagesJson.withCString { cMessages in |
|
539
|
if let sj = samplingJson { |
|
540
|
return sj.withCString { cSj in |
|
541
|
self.consumeRustString(onde_engine_generate(ptr, cMessages, cSj)) |
|
542
|
} |
|
543
|
} else { |
|
544
|
return self.consumeRustString(onde_engine_generate(ptr, cMessages, nil)) |
|
545
|
} |
|
546
|
} |
|
547
|
return try self.validateJsonResult(result) |
|
548
|
} |
|
549
|
} |
|
550
|
} |