react-native-nobodywho 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Nobodywho.podspec CHANGED
@@ -10,7 +10,7 @@ framework_name = "NobodywhoFramework.xcframework"
10
10
  framework_dir = File.join(__dir__, framework_name)
11
11
  zip_name = "#{framework_name}.zip"
12
12
  zip_path = File.join(__dir__, zip_name)
13
- url = "https://github.com/nobodywho-ooo/nobodywho/releases/download/nobodywho-react-native-#{version}/#{zip_name}"
13
+ url = "https://github.com/nobodywho-ooo/nobodywho/releases/download/nobodywho-react-native-v#{version}/#{zip_name}"
14
14
 
15
15
  # Always download a fresh xcframework to ensure it matches the package version.
16
16
  FileUtils.rm_rf(framework_dir) if File.exist?(framework_dir)
@@ -20,7 +20,7 @@ puts "[NobodyWho] Downloading xcframework from #{url}"
20
20
  system("curl", "-L", "-f", "-o", zip_path, url) or
21
21
  raise "Failed to download NobodyWho xcframework.\n" \
22
22
  "URL: #{url}\n" \
23
- "Check that the release exists: https://github.com/nobodywho-ooo/nobodywho/releases/tag/nobodywho-react-native-#{version}\n" \
23
+ "Check that the release exists: https://github.com/nobodywho-ooo/nobodywho/releases/tag/nobodywho-react-native-v#{version}\n" \
24
24
  "For local development, manually place the xcframework at: #{framework_dir}"
25
25
 
26
26
  puts "[NobodyWho] Extracting xcframework..."
package/README.md CHANGED
@@ -119,14 +119,14 @@ See the [Sampling documentation](https://docs.nobodywho.ooo/react-native/samplin
119
119
 
120
120
  ---
121
121
 
122
- ## Vision
122
+ ## Vision & Hearing
123
123
 
124
- Vision support lets you include images in your prompts, so the model can analyze and describe visual content alongside text.
124
+ Provide image and audio information to your LLM.
125
125
 
126
126
  To enable this, you need two model files:
127
127
 
128
- - A **vision-language LLM** (usually has `VL` in the name)
129
- - A matching **projection model** that converts images into tokens the LLM can process (usually has `mmproj` in the name)
128
+ - A multimodal LLM, so the LLM can consume image-tokens or/and audio-tokens
129
+ - A matching projection model, which converts images to image-tokens or/and audio to audio-tokens (usually has `mmproj` in the name)
130
130
 
131
131
  Pass the projection model when loading your model, then use `Prompt` to compose prompts that mix text and images:
132
132
 
@@ -135,17 +135,20 @@ import { Chat, Prompt } from "react-native-nobodywho";
135
135
 
136
136
  const chat = await Chat.fromPath({
137
137
  modelPath: "/path/to/vision-model.gguf",
138
- imageModelPath: "/path/to/mmproj.gguf",
138
+ projectionModelPath: "/path/to/mmproj.gguf",
139
139
  });
140
140
 
141
- const prompt = new Prompt([
142
- Prompt.Text("What do you see in this image?"),
143
- Prompt.Image("/path/to/photo.png"),
144
- ]);
145
-
146
- const response = await chat.ask(prompt).completed();
141
+ const response = await chat
142
+ .ask(
143
+ new Prompt([
144
+ Prompt.Text("Tell me what you see in the image and what you hear in the audio."),
145
+ Prompt.Image("/path/to/dog.png"),
146
+ Prompt.Audio("/path/to/sound.mp3"),
147
+ ]),
148
+ )
149
+ .completed();
147
150
  ```
148
151
 
149
- You can pass multiple images and interleave text between them. If the model performs poorly, try reordering the text and image parts — this can make a noticeable difference. If images consume too much context, increase `contextSize` or preprocess images with compression.
152
+ You can pass multiple images/audio files and interleave text between them. If the model performs poorly, try reordering the text, audio and image parts — this can make a noticeable difference. If images consume too much context, increase `contextSize` or preprocess images with compression.
150
153
 
151
- See the [Vision documentation](https://docs.nobodywho.ooo/react-native/vision/) for model recommendations and advanced tips.
154
+ See the [Vision & Hearing documentation](https://docs.nobodywho.ooo/react-native/vision/) for model recommendations and advanced tips.
@@ -95,9 +95,18 @@ typedef struct UniffiForeignFutureResultVoid {
95
95
  } UniffiForeignFutureResultVoid;
96
96
  typedef void (*UniffiForeignFutureCompleteVoid)(
97
97
  uint64_t callback_data, UniffiForeignFutureResultVoid result);
98
+ typedef void (*UniffiCallbackInterfaceRustDownloadProgressCallbackMethod0)(
99
+ uint64_t uniffi_handle, uint64_t downloaded, uint64_t total,
100
+ void *uniffi_out_return, RustCallStatus *rust_call_status);
98
101
  typedef void (*UniffiCallbackInterfaceRustToolCallbackMethod0)(
99
102
  uint64_t uniffi_handle, RustBuffer arguments_json,
100
103
  RustBuffer *uniffi_out_return, RustCallStatus *rust_call_status);
104
+ typedef struct UniffiVTableCallbackInterfaceRustDownloadProgressCallback {
105
+ UniffiCallbackInterfaceFree uniffi_free;
106
+ UniffiCallbackInterfaceClone uniffi_clone;
107
+ UniffiCallbackInterfaceRustDownloadProgressCallbackMethod0
108
+ on_download_progress;
109
+ } UniffiVTableCallbackInterfaceRustDownloadProgressCallback;
101
110
  typedef struct UniffiVTableCallbackInterfaceRustToolCallback {
102
111
  UniffiCallbackInterfaceFree uniffi_free;
103
112
  UniffiCallbackInterfaceClone uniffi_clone;
@@ -253,12 +262,15 @@ uniffi_nobodywho_uniffi_fn_constructor_samplerconfig_from_json(
253
262
  RustBuffer json_str, RustCallStatus *uniffi_out_err);
254
263
  RustBuffer uniffi_nobodywho_uniffi_fn_method_samplerconfig_to_json(
255
264
  /*handle*/ uint64_t ptr, RustCallStatus *uniffi_out_err);
265
+ void uniffi_nobodywho_uniffi_fn_init_callback_vtable_rustdownloadprogresscallback(
266
+ UniffiVTableCallbackInterfaceRustDownloadProgressCallback *vtable);
256
267
  void uniffi_nobodywho_uniffi_fn_init_callback_vtable_rusttoolcallback(
257
268
  UniffiVTableCallbackInterfaceRustToolCallback *vtable);
258
269
  float uniffi_nobodywho_uniffi_fn_func_cosine_similarity(
259
270
  RustBuffer a, RustBuffer b, RustCallStatus *uniffi_out_err);
260
271
  /*handle*/ uint64_t uniffi_nobodywho_uniffi_fn_func_load_model(
261
- RustBuffer model_path, int8_t use_gpu, RustBuffer projection_model_path);
272
+ RustBuffer model_path, int8_t use_gpu, RustBuffer projection_model_path,
273
+ RustBuffer on_download_progress);
262
274
  /*handle*/ uint64_t uniffi_nobodywho_uniffi_fn_func_sampler_preset_default(
263
275
  RustCallStatus *uniffi_out_err);
264
276
  /*handle*/ uint64_t uniffi_nobodywho_uniffi_fn_func_sampler_preset_dry(
@@ -452,6 +464,8 @@ uint16_t uniffi_nobodywho_uniffi_checksum_constructor_rusttool_new();
452
464
  uint16_t uniffi_nobodywho_uniffi_checksum_constructor_rusttool_new_async();
453
465
  uint16_t uniffi_nobodywho_uniffi_checksum_constructor_samplerbuilder_new();
454
466
  uint16_t uniffi_nobodywho_uniffi_checksum_constructor_samplerconfig_from_json();
467
+ uint16_t
468
+ uniffi_nobodywho_uniffi_checksum_method_rustdownloadprogresscallback_on_download_progress();
455
469
  uint16_t uniffi_nobodywho_uniffi_checksum_method_rusttoolcallback_call();
456
470
  uint32_t ffi_nobodywho_uniffi_uniffi_contract_version();
457
471
  }
@@ -890,6 +904,119 @@ static void cleanup() {
890
904
  } // namespace uniffi::nobodywho::cb::foreignfuturedroppedcallback
891
905
  // Implementation of free callback function CallbackInterfaceFree
892
906
 
907
+ // Callback function:
908
+ // uniffi::nobodywho::st::vtablecallbackinterfacerustdownloadprogresscallback::vtablecallbackinterfacerustdownloadprogresscallback::free::UniffiCallbackInterfaceFree
909
+ //
910
+ // We have the following constraints:
911
+ // - we need to pass a function pointer to Rust.
912
+ // - we need a jsi::Runtime and jsi::Function to call into JS.
913
+ // - function pointers can't store state, so we can't use a lamda.
914
+ //
915
+ // For this, we store a lambda as a global, as `rsLambda`. The `callback`
916
+ // function calls the lambda, which itself calls the `body` which then calls
917
+ // into JS.
918
+ //
919
+ // We then give the `callback` function pointer to Rust which will call the
920
+ // lambda sometime in the future.
921
+ namespace uniffi::nobodywho::st::
922
+ vtablecallbackinterfacerustdownloadprogresscallback::
923
+ vtablecallbackinterfacerustdownloadprogresscallback::free {
924
+ using namespace facebook;
925
+
926
+ // We need to store a lambda in a global so we can call it from
927
+ // a function pointer. The function pointer is passed to Rust.
928
+ static std::function<void(uint64_t)> rsLambda = nullptr;
929
+
930
+ // This is the main body of the callback. It's called from the lambda,
931
+ // which itself is called from the callback function which is passed to Rust.
932
+ static void body(jsi::Runtime &rt,
933
+ std::shared_ptr<uniffi_runtime::UniffiCallInvoker> callInvoker,
934
+ std::shared_ptr<jsi::Value> callbackValue,
935
+ uint64_t rs_handle) {
936
+
937
+ // Convert the arguments from Rust, into jsi::Values.
938
+ // We'll use the Bridging class to do this…
939
+ auto js_handle =
940
+ uniffi_jsi::Bridging<uint64_t>::toJs(rt, callInvoker, rs_handle);
941
+
942
+ // Now we are ready to call the callback.
943
+ // We are already on the JS thread, because this `body` function was
944
+ // invoked from the CallInvoker.
945
+ try {
946
+ // Getting the callback function
947
+ auto cb = callbackValue->asObject(rt).asFunction(rt);
948
+ auto uniffiResult = cb.call(rt, js_handle);
949
+
950
+ } catch (const jsi::JSError &error) {
951
+ std::cout << "Error in callback UniffiCallbackInterfaceFree: "
952
+ << error.what() << std::endl;
953
+ throw error;
954
+ }
955
+ }
956
+
957
+ static void callback(uint64_t rs_handle) {
958
+ // If the runtime has shutdown, then there is no point in trying to
959
+ // call into Javascript. BUT how do we tell if the runtime has shutdown?
960
+ //
961
+ // Answer: the module destructor calls into callback `cleanup` method,
962
+ // which nulls out the rsLamda.
963
+ //
964
+ // If rsLamda is null, then there is no runtime to call into.
965
+ if (rsLambda == nullptr) {
966
+ // This only occurs when destructors are calling into Rust free/drop,
967
+ // which causes the JS callback to be dropped.
968
+ return;
969
+ }
970
+
971
+ // The runtime, the actual callback jsi::funtion, and the callInvoker
972
+ // are all in the lambda.
973
+ rsLambda(rs_handle);
974
+ }
975
+
976
+ [[maybe_unused]] static UniffiCallbackInterfaceFree
977
+ makeCallbackFunction( // uniffi::nobodywho::st::vtablecallbackinterfacerustdownloadprogresscallback::vtablecallbackinterfacerustdownloadprogresscallback::free
978
+ jsi::Runtime &rt,
979
+ std::shared_ptr<uniffi_runtime::UniffiCallInvoker> callInvoker,
980
+ const jsi::Value &value) {
981
+ if (rsLambda != nullptr) {
982
+ // `makeCallbackFunction` is called in two circumstances:
983
+ //
984
+ // 1. at startup, when initializing callback interface vtables.
985
+ // 2. when polling futures. This happens at least once per future that is
986
+ // exposed to Javascript. We know that this is always the same function,
987
+ // `uniffiFutureContinuationCallback` in `async-rust-calls.ts`.
988
+ //
989
+ // We can therefore return the callback function without making anything
990
+ // new if we've been initialized already.
991
+ return callback;
992
+ }
993
+ auto callbackFunction = value.asObject(rt).asFunction(rt);
994
+ auto callbackValue = std::make_shared<jsi::Value>(rt, callbackFunction);
995
+ rsLambda = [&rt, callInvoker, callbackValue](uint64_t rs_handle) {
996
+ // We immediately make a lambda which will do the work of transforming the
997
+ // arguments into JSI values and calling the callback.
998
+ uniffi_runtime::UniffiCallFunc jsLambda =
999
+ [callInvoker, callbackValue, rs_handle](jsi::Runtime &rt) mutable {
1000
+ body(rt, callInvoker, callbackValue, rs_handle);
1001
+ };
1002
+ // We'll then call that lambda from the callInvoker which will
1003
+ // look after calling it on the correct thread.
1004
+
1005
+ callInvoker->invokeNonBlocking(rt, jsLambda);
1006
+ };
1007
+ return callback;
1008
+ }
1009
+
1010
+ // This method is called from the destructor of NativeNobodywho, which only
1011
+ // happens when the jsi::Runtime is being destroyed.
1012
+ static void cleanup() {
1013
+ // The lambda holds a reference to the the Runtime, so when this is nulled
1014
+ // out, then the pointer will no longer be left dangling.
1015
+ rsLambda = nullptr;
1016
+ }
1017
+ } // namespace
1018
+ // uniffi::nobodywho::st::vtablecallbackinterfacerustdownloadprogresscallback::vtablecallbackinterfacerustdownloadprogresscallback::free
1019
+
893
1020
  // Callback function:
894
1021
  // uniffi::nobodywho::st::vtablecallbackinterfacerusttoolcallback::vtablecallbackinterfacerusttoolcallback::free::UniffiCallbackInterfaceFree
895
1022
  //
@@ -1822,6 +1949,314 @@ template <> struct Bridging<UniffiForeignFutureCompleteVoid> {
1822
1949
  return jsi::Value::undefined();
1823
1950
  }
1824
1951
  };
1952
+ } // namespace uniffi::nobodywho
1953
+ // Implementation of CallbackInterfaceClone for vtable field uniffi_clone in
1954
+ // VTableCallbackInterfaceRustDownloadProgressCallback
1955
+
1956
+ // Callback function:
1957
+ // uniffi::nobodywho::cb::callbackinterfaceclone::vtablecallbackinterfacerustdownloadprogresscallback::UniffiCallbackInterfaceClone
1958
+ //
1959
+ // We have the following constraints:
1960
+ // - we need to pass a function pointer to Rust.
1961
+ // - we need a jsi::Runtime and jsi::Function to call into JS.
1962
+ // - function pointers can't store state, so we can't use a lamda.
1963
+ //
1964
+ // For this, we store a lambda as a global, as `rsLambda`. The `callback`
1965
+ // function calls the lambda, which itself calls the `body` which then calls
1966
+ // into JS.
1967
+ //
1968
+ // We then give the `callback` function pointer to Rust which will call the
1969
+ // lambda sometime in the future.
1970
+ namespace uniffi::nobodywho::cb::callbackinterfaceclone::
1971
+ vtablecallbackinterfacerustdownloadprogresscallback {
1972
+ using namespace facebook;
1973
+
1974
+ // We need to store a lambda in a global so we can call it from
1975
+ // a function pointer. The function pointer is passed to Rust.
1976
+ static std::function<void(uint64_t, uint64_t *)> rsLambda = nullptr;
1977
+
1978
+ // This is the main body of the callback. It's called from the lambda,
1979
+ // which itself is called from the callback function which is passed to Rust.
1980
+ static void body(jsi::Runtime &rt,
1981
+ std::shared_ptr<uniffi_runtime::UniffiCallInvoker> callInvoker,
1982
+ std::shared_ptr<jsi::Value> callbackValue, uint64_t rs_handle,
1983
+ uint64_t *uniffi_direct_return) {
1984
+
1985
+ // Convert the arguments from Rust, into jsi::Values.
1986
+ // We'll use the Bridging class to do this…
1987
+ auto js_handle =
1988
+ uniffi_jsi::Bridging<uint64_t>::toJs(rt, callInvoker, rs_handle);
1989
+
1990
+ // Now we are ready to call the callback.
1991
+ // We are already on the JS thread, because this `body` function was
1992
+ // invoked from the CallInvoker.
1993
+ try {
1994
+ // Getting the callback function
1995
+ auto cb = callbackValue->asObject(rt).asFunction(rt);
1996
+ auto uniffiResult = cb.call(rt, js_handle);
1997
+
1998
+ // Write the direct return value back to the caller.
1999
+ if (uniffi_direct_return != nullptr) {
2000
+ *uniffi_direct_return =
2001
+ uniffi_jsi::Bridging<uint64_t>::fromJs(rt, callInvoker, uniffiResult);
2002
+ }
2003
+ } catch (const jsi::JSError &error) {
2004
+ std::cout << "Error in callback UniffiCallbackInterfaceClone: "
2005
+ << error.what() << std::endl;
2006
+ throw error;
2007
+ }
2008
+ }
2009
+
2010
+ static uint64_t callback(uint64_t rs_handle) {
2011
+ // If the runtime has shutdown, then there is no point in trying to
2012
+ // call into Javascript. BUT how do we tell if the runtime has shutdown?
2013
+ //
2014
+ // Answer: the module destructor calls into callback `cleanup` method,
2015
+ // which nulls out the rsLamda.
2016
+ //
2017
+ // If rsLamda is null, then there is no runtime to call into.
2018
+ if (rsLambda == nullptr) {
2019
+ // This only occurs when destructors are calling into Rust free/drop,
2020
+ // which causes the JS callback to be dropped.
2021
+ return 0;
2022
+ }
2023
+ uint64_t uniffi_result = 0;
2024
+
2025
+ // The runtime, the actual callback jsi::funtion, and the callInvoker
2026
+ // are all in the lambda.
2027
+ rsLambda(rs_handle, &uniffi_result);
2028
+ return uniffi_result;
2029
+ }
2030
+
2031
+ [[maybe_unused]] static UniffiCallbackInterfaceClone
2032
+ makeCallbackFunction( // uniffi::nobodywho::cb::callbackinterfaceclone::vtablecallbackinterfacerustdownloadprogresscallback
2033
+ jsi::Runtime &rt,
2034
+ std::shared_ptr<uniffi_runtime::UniffiCallInvoker> callInvoker,
2035
+ const jsi::Value &value) {
2036
+ if (rsLambda != nullptr) {
2037
+ // `makeCallbackFunction` is called in two circumstances:
2038
+ //
2039
+ // 1. at startup, when initializing callback interface vtables.
2040
+ // 2. when polling futures. This happens at least once per future that is
2041
+ // exposed to Javascript. We know that this is always the same function,
2042
+ // `uniffiFutureContinuationCallback` in `async-rust-calls.ts`.
2043
+ //
2044
+ // We can therefore return the callback function without making anything
2045
+ // new if we've been initialized already.
2046
+ return callback;
2047
+ }
2048
+ auto callbackFunction = value.asObject(rt).asFunction(rt);
2049
+ auto callbackValue = std::make_shared<jsi::Value>(rt, callbackFunction);
2050
+ rsLambda = [&rt, callInvoker, callbackValue](uint64_t rs_handle,
2051
+ uint64_t *uniffi_direct_return) {
2052
+ // We immediately make a lambda which will do the work of transforming the
2053
+ // arguments into JSI values and calling the callback.
2054
+ uniffi_runtime::UniffiCallFunc jsLambda =
2055
+ [callInvoker, callbackValue, rs_handle,
2056
+ uniffi_direct_return](jsi::Runtime &rt) mutable {
2057
+ body(rt, callInvoker, callbackValue, rs_handle, uniffi_direct_return);
2058
+ };
2059
+ // We'll then call that lambda from the callInvoker which will
2060
+ // look after calling it on the correct thread.
2061
+ callInvoker->invokeBlocking(rt, jsLambda);
2062
+ };
2063
+ return callback;
2064
+ }
2065
+
2066
+ // This method is called from the destructor of NativeNobodywho, which only
2067
+ // happens when the jsi::Runtime is being destroyed.
2068
+ static void cleanup() {
2069
+ // The lambda holds a reference to the the Runtime, so when this is nulled
2070
+ // out, then the pointer will no longer be left dangling.
2071
+ rsLambda = nullptr;
2072
+ }
2073
+ } // namespace
2074
+ // uniffi::nobodywho::cb::callbackinterfaceclone::vtablecallbackinterfacerustdownloadprogresscallback
2075
+ // Implementation of CallbackInterfaceRustDownloadProgressCallbackMethod0 for
2076
+ // vtable field on_download_progress in
2077
+ // VTableCallbackInterfaceRustDownloadProgressCallback
2078
+
2079
+ // Callback function:
2080
+ // uniffi::nobodywho::cb::callbackinterfacerustdownloadprogresscallbackmethod0::vtablecallbackinterfacerustdownloadprogresscallback::UniffiCallbackInterfaceRustDownloadProgressCallbackMethod0
2081
+ //
2082
+ // We have the following constraints:
2083
+ // - we need to pass a function pointer to Rust.
2084
+ // - we need a jsi::Runtime and jsi::Function to call into JS.
2085
+ // - function pointers can't store state, so we can't use a lamda.
2086
+ //
2087
+ // For this, we store a lambda as a global, as `rsLambda`. The `callback`
2088
+ // function calls the lambda, which itself calls the `body` which then calls
2089
+ // into JS.
2090
+ //
2091
+ // We then give the `callback` function pointer to Rust which will call the
2092
+ // lambda sometime in the future.
2093
+ namespace uniffi::nobodywho::cb::
2094
+ callbackinterfacerustdownloadprogresscallbackmethod0::
2095
+ vtablecallbackinterfacerustdownloadprogresscallback {
2096
+ using namespace facebook;
2097
+
2098
+ // We need to store a lambda in a global so we can call it from
2099
+ // a function pointer. The function pointer is passed to Rust.
2100
+ static std::function<void(uint64_t, uint64_t, uint64_t, void *,
2101
+ RustCallStatus *)>
2102
+ rsLambda = nullptr;
2103
+
2104
+ // This is the main body of the callback. It's called from the lambda,
2105
+ // which itself is called from the callback function which is passed to Rust.
2106
+ static void body(jsi::Runtime &rt,
2107
+ std::shared_ptr<uniffi_runtime::UniffiCallInvoker> callInvoker,
2108
+ std::shared_ptr<jsi::Value> callbackValue,
2109
+ uint64_t rs_uniffiHandle, uint64_t rs_downloaded,
2110
+ uint64_t rs_total, void *rs_uniffiOutReturn,
2111
+ RustCallStatus *uniffi_call_status) {
2112
+
2113
+ // Convert the arguments from Rust, into jsi::Values.
2114
+ // We'll use the Bridging class to do this…
2115
+ auto js_uniffiHandle =
2116
+ uniffi_jsi::Bridging<uint64_t>::toJs(rt, callInvoker, rs_uniffiHandle);
2117
+ auto js_downloaded =
2118
+ uniffi_jsi::Bridging<uint64_t>::toJs(rt, callInvoker, rs_downloaded);
2119
+ auto js_total =
2120
+ uniffi_jsi::Bridging<uint64_t>::toJs(rt, callInvoker, rs_total);
2121
+
2122
+ // Now we are ready to call the callback.
2123
+ // We are already on the JS thread, because this `body` function was
2124
+ // invoked from the CallInvoker.
2125
+ try {
2126
+ // Getting the callback function
2127
+ auto cb = callbackValue->asObject(rt).asFunction(rt);
2128
+ auto uniffiResult = cb.call(rt, js_uniffiHandle, js_downloaded, js_total);
2129
+
2130
+ // Now copy the result back from JS into the RustCallStatus object.
2131
+ uniffi::nobodywho::Bridging<RustCallStatus>::copyFromJs(
2132
+ rt, callInvoker, uniffiResult, uniffi_call_status);
2133
+
2134
+ if (uniffi_call_status->code != UNIFFI_CALL_STATUS_OK) {
2135
+ // The JS callback finished abnormally, so we cannot retrieve the return
2136
+ // value.
2137
+ return;
2138
+ }
2139
+
2140
+ } catch (const jsi::JSError &error) {
2141
+ std::cout << "Error in callback "
2142
+ "UniffiCallbackInterfaceRustDownloadProgressCallbackMethod0: "
2143
+ << error.what() << std::endl;
2144
+ throw error;
2145
+ }
2146
+ }
2147
+
2148
+ static void callback(uint64_t rs_uniffiHandle, uint64_t rs_downloaded,
2149
+ uint64_t rs_total, void *rs_uniffiOutReturn,
2150
+ RustCallStatus *uniffi_call_status) {
2151
+ // If the runtime has shutdown, then there is no point in trying to
2152
+ // call into Javascript. BUT how do we tell if the runtime has shutdown?
2153
+ //
2154
+ // Answer: the module destructor calls into callback `cleanup` method,
2155
+ // which nulls out the rsLamda.
2156
+ //
2157
+ // If rsLamda is null, then there is no runtime to call into.
2158
+ if (rsLambda == nullptr) {
2159
+ // This only occurs when destructors are calling into Rust free/drop,
2160
+ // which causes the JS callback to be dropped.
2161
+ return;
2162
+ }
2163
+
2164
+ // The runtime, the actual callback jsi::funtion, and the callInvoker
2165
+ // are all in the lambda.
2166
+ rsLambda(rs_uniffiHandle, rs_downloaded, rs_total, rs_uniffiOutReturn,
2167
+ uniffi_call_status);
2168
+ }
2169
+
2170
+ [[maybe_unused]] static UniffiCallbackInterfaceRustDownloadProgressCallbackMethod0
2171
+ makeCallbackFunction( // uniffi::nobodywho::cb::callbackinterfacerustdownloadprogresscallbackmethod0::vtablecallbackinterfacerustdownloadprogresscallback
2172
+ jsi::Runtime &rt,
2173
+ std::shared_ptr<uniffi_runtime::UniffiCallInvoker> callInvoker,
2174
+ const jsi::Value &value) {
2175
+ if (rsLambda != nullptr) {
2176
+ // `makeCallbackFunction` is called in two circumstances:
2177
+ //
2178
+ // 1. at startup, when initializing callback interface vtables.
2179
+ // 2. when polling futures. This happens at least once per future that is
2180
+ // exposed to Javascript. We know that this is always the same function,
2181
+ // `uniffiFutureContinuationCallback` in `async-rust-calls.ts`.
2182
+ //
2183
+ // We can therefore return the callback function without making anything
2184
+ // new if we've been initialized already.
2185
+ return callback;
2186
+ }
2187
+ auto callbackFunction = value.asObject(rt).asFunction(rt);
2188
+ auto callbackValue = std::make_shared<jsi::Value>(rt, callbackFunction);
2189
+ rsLambda = [&rt, callInvoker,
2190
+ callbackValue](uint64_t rs_uniffiHandle, uint64_t rs_downloaded,
2191
+ uint64_t rs_total, void *rs_uniffiOutReturn,
2192
+ RustCallStatus *uniffi_call_status) {
2193
+ // We immediately make a lambda which will do the work of transforming the
2194
+ // arguments into JSI values and calling the callback.
2195
+ uniffi_runtime::UniffiCallFunc jsLambda =
2196
+ [callInvoker, callbackValue, rs_uniffiHandle, rs_downloaded, rs_total,
2197
+ rs_uniffiOutReturn, uniffi_call_status](jsi::Runtime &rt) mutable {
2198
+ body(rt, callInvoker, callbackValue, rs_uniffiHandle, rs_downloaded,
2199
+ rs_total, rs_uniffiOutReturn, uniffi_call_status);
2200
+ };
2201
+ // We'll then call that lambda from the callInvoker which will
2202
+ // look after calling it on the correct thread.
2203
+ callInvoker->invokeBlocking(rt, jsLambda);
2204
+ };
2205
+ return callback;
2206
+ }
2207
+
2208
+ // This method is called from the destructor of NativeNobodywho, which only
2209
+ // happens when the jsi::Runtime is being destroyed.
2210
+ static void cleanup() {
2211
+ // The lambda holds a reference to the the Runtime, so when this is nulled
2212
+ // out, then the pointer will no longer be left dangling.
2213
+ rsLambda = nullptr;
2214
+ }
2215
+ } // namespace
2216
+ // uniffi::nobodywho::cb::callbackinterfacerustdownloadprogresscallbackmethod0::vtablecallbackinterfacerustdownloadprogresscallback
2217
+ namespace uniffi::nobodywho {
2218
+ using namespace facebook;
2219
+ using CallInvoker = uniffi_runtime::UniffiCallInvoker;
2220
+
2221
+ template <>
2222
+ struct Bridging<UniffiVTableCallbackInterfaceRustDownloadProgressCallback> {
2223
+ static UniffiVTableCallbackInterfaceRustDownloadProgressCallback
2224
+ fromJs(jsi::Runtime &rt, std::shared_ptr<CallInvoker> callInvoker,
2225
+ const jsi::Value &jsValue) {
2226
+ // Check if the input is an object
2227
+ if (!jsValue.isObject()) {
2228
+ throw jsi::JSError(
2229
+ rt, "Expected an object for "
2230
+ "UniffiVTableCallbackInterfaceRustDownloadProgressCallback");
2231
+ }
2232
+
2233
+ // Get the object from the jsi::Value
2234
+ auto jsObject = jsValue.getObject(rt);
2235
+
2236
+ // Create the vtable struct
2237
+ UniffiVTableCallbackInterfaceRustDownloadProgressCallback rsObject;
2238
+
2239
+ // Create the vtable from the js callbacks.
2240
+ rsObject.uniffi_free = uniffi::nobodywho::st::
2241
+ vtablecallbackinterfacerustdownloadprogresscallback::
2242
+ vtablecallbackinterfacerustdownloadprogresscallback::free::
2243
+ makeCallbackFunction(rt, callInvoker,
2244
+ jsObject.getProperty(rt, "uniffiFree"));
2245
+ rsObject.uniffi_clone = uniffi::nobodywho::cb::callbackinterfaceclone::
2246
+ vtablecallbackinterfacerustdownloadprogresscallback::
2247
+ makeCallbackFunction(rt, callInvoker,
2248
+ jsObject.getProperty(rt, "uniffiClone"));
2249
+ rsObject.on_download_progress = uniffi::nobodywho::cb::
2250
+ callbackinterfacerustdownloadprogresscallbackmethod0::
2251
+ vtablecallbackinterfacerustdownloadprogresscallback::
2252
+ makeCallbackFunction(
2253
+ rt, callInvoker,
2254
+ jsObject.getProperty(rt, "onDownloadProgress"));
2255
+
2256
+ return rsObject;
2257
+ }
2258
+ };
2259
+
1825
2260
  } // namespace uniffi::nobodywho
1826
2261
  // Implementation of CallbackInterfaceClone for vtable field uniffi_clone in
1827
2262
  // VTableCallbackInterfaceRustToolCallback
@@ -2886,6 +3321,19 @@ NativeNobodywho::NativeNobodywho(
2886
3321
  ->cpp_uniffi_nobodywho_uniffi_fn_method_samplerconfig_to_json(
2887
3322
  rt, thisVal, args, count);
2888
3323
  });
3324
+ props["ubrn_uniffi_nobodywho_uniffi_fn_init_callback_vtable_"
3325
+ "rustdownloadprogresscallback"] = jsi::Function::createFromHostFunction(
3326
+ rt,
3327
+ jsi::PropNameID::forAscii(rt,
3328
+ "ubrn_uniffi_nobodywho_uniffi_fn_init_callback_"
3329
+ "vtable_rustdownloadprogresscallback"),
3330
+ 1,
3331
+ [this](jsi::Runtime &rt, const jsi::Value &thisVal,
3332
+ const jsi::Value *args, size_t count) -> jsi::Value {
3333
+ return this
3334
+ ->cpp_uniffi_nobodywho_uniffi_fn_init_callback_vtable_rustdownloadprogresscallback(
3335
+ rt, thisVal, args, count);
3336
+ });
2889
3337
  props["ubrn_uniffi_nobodywho_uniffi_fn_init_callback_vtable_"
2890
3338
  "rusttoolcallback"] = jsi::Function::createFromHostFunction(
2891
3339
  rt,
@@ -2914,7 +3362,7 @@ NativeNobodywho::NativeNobodywho(
2914
3362
  rt,
2915
3363
  jsi::PropNameID::forAscii(
2916
3364
  rt, "ubrn_uniffi_nobodywho_uniffi_fn_func_load_model"),
2917
- 3,
3365
+ 4,
2918
3366
  [this](jsi::Runtime &rt, const jsi::Value &thisVal,
2919
3367
  const jsi::Value *args, size_t count) -> jsi::Value {
2920
3368
  return this->cpp_uniffi_nobodywho_uniffi_fn_func_load_model(
@@ -4188,6 +4636,20 @@ NativeNobodywho::NativeNobodywho(
4188
4636
  ->cpp_uniffi_nobodywho_uniffi_checksum_constructor_samplerconfig_from_json(
4189
4637
  rt, thisVal, args, count);
4190
4638
  });
4639
+ props["ubrn_uniffi_nobodywho_uniffi_checksum_method_"
4640
+ "rustdownloadprogresscallback_on_download_progress"] =
4641
+ jsi::Function::createFromHostFunction(
4642
+ rt,
4643
+ jsi::PropNameID::forAscii(
4644
+ rt, "ubrn_uniffi_nobodywho_uniffi_checksum_method_"
4645
+ "rustdownloadprogresscallback_on_download_progress"),
4646
+ 0,
4647
+ [this](jsi::Runtime &rt, const jsi::Value &thisVal,
4648
+ const jsi::Value *args, size_t count) -> jsi::Value {
4649
+ return this
4650
+ ->cpp_uniffi_nobodywho_uniffi_checksum_method_rustdownloadprogresscallback_on_download_progress(
4651
+ rt, thisVal, args, count);
4652
+ });
4191
4653
  props["ubrn_uniffi_nobodywho_uniffi_checksum_method_rusttoolcallback_call"] =
4192
4654
  jsi::Function::createFromHostFunction(
4193
4655
  rt,
@@ -4352,8 +4814,14 @@ NativeNobodywho::~NativeNobodywho() {
4352
4814
  // Cleanup for callback function ForeignFutureDroppedCallback
4353
4815
  uniffi::nobodywho::cb::foreignfuturedroppedcallback::cleanup();
4354
4816
  // Cleanup for "free" callback function CallbackInterfaceFree
4817
+ uniffi::nobodywho::st::vtablecallbackinterfacerustdownloadprogresscallback::
4818
+ vtablecallbackinterfacerustdownloadprogresscallback::free::cleanup();
4355
4819
  uniffi::nobodywho::st::vtablecallbackinterfacerusttoolcallback::
4356
4820
  vtablecallbackinterfacerusttoolcallback::free::cleanup();
4821
+ uniffi::nobodywho::cb::callbackinterfaceclone::
4822
+ vtablecallbackinterfacerustdownloadprogresscallback::cleanup();
4823
+ uniffi::nobodywho::cb::callbackinterfacerustdownloadprogresscallbackmethod0::
4824
+ vtablecallbackinterfacerustdownloadprogresscallback::cleanup();
4357
4825
  uniffi::nobodywho::cb::callbackinterfaceclone::
4358
4826
  vtablecallbackinterfacerusttoolcallback::cleanup();
4359
4827
  uniffi::nobodywho::cb::callbackinterfacerusttoolcallbackmethod0::
@@ -5395,6 +5863,21 @@ NativeNobodywho::cpp_uniffi_nobodywho_uniffi_fn_method_samplerconfig_to_json(
5395
5863
 
5396
5864
  return uniffi::nobodywho::Bridging<RustBuffer>::toJs(rt, callInvoker, value);
5397
5865
  }
5866
+ jsi::Value NativeNobodywho::
5867
+ cpp_uniffi_nobodywho_uniffi_fn_init_callback_vtable_rustdownloadprogresscallback(
5868
+ jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args,
5869
+ size_t count) {
5870
+ auto vtableInstance = uniffi::nobodywho::Bridging<
5871
+ UniffiVTableCallbackInterfaceRustDownloadProgressCallback>::
5872
+ fromJs(rt, callInvoker, args[0]);
5873
+
5874
+ std::lock_guard<std::mutex> lock(uniffi::nobodywho::registry::vtableMutex);
5875
+ uniffi_nobodywho_uniffi_fn_init_callback_vtable_rustdownloadprogresscallback(
5876
+ uniffi::nobodywho::registry::putTable(
5877
+ "UniffiVTableCallbackInterfaceRustDownloadProgressCallback",
5878
+ vtableInstance));
5879
+ return jsi::Value::undefined();
5880
+ }
5398
5881
  jsi::Value NativeNobodywho::
5399
5882
  cpp_uniffi_nobodywho_uniffi_fn_init_callback_vtable_rusttoolcallback(
5400
5883
  jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args,
@@ -5430,8 +5913,9 @@ jsi::Value NativeNobodywho::cpp_uniffi_nobodywho_uniffi_fn_func_load_model(
5430
5913
  auto value = uniffi_nobodywho_uniffi_fn_func_load_model(
5431
5914
  uniffi::nobodywho::Bridging<RustBuffer>::fromJs(rt, callInvoker, args[0]),
5432
5915
  uniffi_jsi::Bridging<int8_t>::fromJs(rt, callInvoker, args[1]),
5916
+ uniffi::nobodywho::Bridging<RustBuffer>::fromJs(rt, callInvoker, args[2]),
5433
5917
  uniffi::nobodywho::Bridging<RustBuffer>::fromJs(rt, callInvoker,
5434
- args[2]));
5918
+ args[3]));
5435
5919
 
5436
5920
  return uniffi_jsi::Bridging</*handle*/ uint64_t>::toJs(rt, callInvoker,
5437
5921
  value);
@@ -6539,6 +7023,15 @@ jsi::Value NativeNobodywho::
6539
7023
 
6540
7024
  return uniffi_jsi::Bridging<uint16_t>::toJs(rt, callInvoker, value);
6541
7025
  }
7026
+ jsi::Value NativeNobodywho::
7027
+ cpp_uniffi_nobodywho_uniffi_checksum_method_rustdownloadprogresscallback_on_download_progress(
7028
+ jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args,
7029
+ size_t count) {
7030
+ auto value =
7031
+ uniffi_nobodywho_uniffi_checksum_method_rustdownloadprogresscallback_on_download_progress();
7032
+
7033
+ return uniffi_jsi::Bridging<uint16_t>::toJs(rt, callInvoker, value);
7034
+ }
6542
7035
  jsi::Value NativeNobodywho::
6543
7036
  cpp_uniffi_nobodywho_uniffi_checksum_method_rusttoolcallback_call(
6544
7037
  jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args,