Skip to main content

foundation_models/ffi/
mod.rs

1//! Raw FFI declarations matching the Swift `@_cdecl` exports in
2//! `swift-bridge/Sources/FoundationModelsBridge`.
3//!
4//! These are intentionally opaque (`*mut c_void`) and unsafe; safe wrappers
5//! live in the parent modules.
6
7use core::ffi::{c_char, c_void};
8
9/// Plain-old-data carrier for [`crate::GenerationOptions`], lowered into
10/// scalar arguments at the Swift FFI boundary because `@_cdecl` cannot
11/// accept Swift struct pointer parameters.
12///
13/// `temperature == NaN` signals "leave default";
14/// `maximum_response_tokens == 0` signals "no limit".
15#[derive(Copy, Clone, Debug)]
16pub struct FFIGenerationOptions {
17    pub temperature: f64,
18    pub maximum_response_tokens: i32,
19    pub sampling_mode: i32,
20    pub top_k: i32,
21    pub top_p: f64,
22}
23
24pub type FmRespondCallback = unsafe extern "C" fn(
25    context: *mut c_void,
26    response: *mut c_char,
27    error: *mut c_char,
28    status: i32,
29);
30
31pub type FmStreamCallback =
32    unsafe extern "C" fn(context: *mut c_void, chunk: *mut c_char, done: bool, status: i32);
33
34extern "C" {
35    pub fn fm_string_dup(s: *const c_char) -> *mut c_char;
36    pub fn fm_string_free(s: *mut c_char);
37    pub fn fm_object_release(ptr: *mut c_void);
38
39    pub fn fm_system_model_is_available() -> bool;
40    pub fn fm_system_model_availability_code() -> i32;
41
42    pub fn fm_session_create(instructions: *const c_char) -> *mut c_void;
43
44    pub fn fm_session_respond(
45        session: *mut c_void,
46        prompt: *const c_char,
47        temperature: f64,
48        max_tokens: i32,
49        sampling_mode: i32,
50        top_k: i32,
51        top_p: f64,
52        context: *mut c_void,
53        callback: FmRespondCallback,
54    );
55
56    pub fn fm_session_respond_with_schema(
57        session: *mut c_void,
58        prompt: *const c_char,
59        schema_json: *const c_char,
60        include_schema_in_prompt: bool,
61        temperature: f64,
62        max_tokens: i32,
63        sampling_mode: i32,
64        top_k: i32,
65        top_p: f64,
66        context: *mut c_void,
67        callback: FmRespondCallback,
68    );
69
70    pub fn fm_session_stream_response(
71        session: *mut c_void,
72        prompt: *const c_char,
73        temperature: f64,
74        max_tokens: i32,
75        sampling_mode: i32,
76        top_k: i32,
77        top_p: f64,
78        context: *mut c_void,
79        callback: FmStreamCallback,
80    );
81
82    /// Pre-warm the model. Apple loads weights + initialises the
83    /// inference engine so the next `respond` call is faster.
84    pub fn fm_session_prewarm(session: *mut c_void);
85
86    /// Returns `true` if `session` is currently producing a response.
87    pub fn fm_session_is_responding(session: *mut c_void) -> bool;
88}
89
90/// Status codes mirrored 1:1 from the `FM_*` constants in
91/// `swift-bridge/Sources/FoundationModelsBridge/FoundationModels.swift`.
92pub mod status {
93    pub const OK: i32 = 0;
94    pub const INVALID_ARGUMENT: i32 = -1;
95    pub const MODEL_UNAVAILABLE: i32 = -2;
96    pub const CANCELLED: i32 = -3;
97    pub const GUARDRAIL_VIOLATION: i32 = -4;
98    pub const CONTEXT_WINDOW_EXCEEDED: i32 = -5;
99    pub const UNSUPPORTED_LANGUAGE: i32 = -6;
100    pub const ASSETS_UNAVAILABLE: i32 = -7;
101    pub const RATE_LIMITED: i32 = -8;
102    pub const DECODING_FAILURE: i32 = -9;
103    pub const REFUSAL: i32 = -10;
104    pub const CONCURRENT_REQUESTS: i32 = -11;
105    pub const UNSUPPORTED_GUIDE: i32 = -12;
106    pub const UNKNOWN: i32 = -99;
107}