cactus-react-native 1.2.1 → 1.5.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.
Files changed (238) hide show
  1. package/README.md +765 -33
  2. package/android/CMakeLists.txt +4 -3
  3. package/android/src/main/java/com/margelo/nitro/cactus/HybridCactusFileSystem.kt +20 -1
  4. package/android/src/main/jniLibs/arm64-v8a/libcactus.a +0 -0
  5. package/android/src/main/jniLibs/arm64-v8a/libcactus_util.a +0 -0
  6. package/cpp/HybridCactus.cpp +231 -19
  7. package/cpp/HybridCactus.hpp +25 -3
  8. package/cpp/HybridCactusIndex.cpp +325 -0
  9. package/cpp/HybridCactusIndex.hpp +43 -0
  10. package/cpp/HybridCactusUtil.cpp +3 -3
  11. package/cpp/HybridCactusUtil.hpp +2 -1
  12. package/cpp/cactus_ffi.h +107 -2
  13. package/cpp/cactus_util.h +1 -1
  14. package/ios/HybridCactusFileSystem.swift +23 -2
  15. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus.h +2 -0
  16. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus_ffi.h +107 -2
  17. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus_telemetry.h +656 -0
  18. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/{ffi_utils.h → cactus_utils.h} +145 -18
  19. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/engine.h +135 -7
  20. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/gemma_tools.h +549 -0
  21. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/graph.h +193 -26
  22. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/kernel.h +54 -195
  23. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/kernel_utils.h +399 -140
  24. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Info.plist +0 -0
  25. package/ios/cactus.xcframework/ios-arm64/cactus.framework/cactus +0 -0
  26. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus.h +2 -0
  27. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus_ffi.h +107 -2
  28. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus_telemetry.h +656 -0
  29. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/{ffi_utils.h → cactus_utils.h} +145 -18
  30. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/engine.h +135 -7
  31. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/gemma_tools.h +549 -0
  32. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/graph.h +193 -26
  33. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/kernel.h +54 -195
  34. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/kernel_utils.h +399 -140
  35. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Info.plist +0 -0
  36. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/_CodeSignature/CodeResources +1 -1
  37. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/cactus +0 -0
  38. package/ios/cactus_util.xcframework/Info.plist +4 -4
  39. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/cactus_util.h +1 -1
  40. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/database.h +27 -0
  41. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Info.plist +0 -0
  42. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/cactus_util +0 -0
  43. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/cactus_util.h +1 -1
  44. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/database.h +27 -0
  45. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Info.plist +0 -0
  46. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/_CodeSignature/CodeResources +3 -3
  47. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/cactus_util +0 -0
  48. package/lib/module/api/Database.js +12 -95
  49. package/lib/module/api/Database.js.map +1 -1
  50. package/lib/module/classes/CactusIndex.js +45 -0
  51. package/lib/module/classes/CactusIndex.js.map +1 -0
  52. package/lib/module/classes/CactusLM.js +65 -17
  53. package/lib/module/classes/CactusLM.js.map +1 -1
  54. package/lib/module/classes/CactusSTT.js +104 -17
  55. package/lib/module/classes/CactusSTT.js.map +1 -1
  56. package/lib/module/config/CactusConfig.js +2 -0
  57. package/lib/module/config/CactusConfig.js.map +1 -1
  58. package/lib/module/constants/packageVersion.js +1 -1
  59. package/lib/module/hooks/useCactusIndex.js +175 -0
  60. package/lib/module/hooks/useCactusIndex.js.map +1 -0
  61. package/lib/module/hooks/useCactusLM.js +68 -7
  62. package/lib/module/hooks/useCactusLM.js.map +1 -1
  63. package/lib/module/hooks/useCactusSTT.js +102 -6
  64. package/lib/module/hooks/useCactusSTT.js.map +1 -1
  65. package/lib/module/index.js +2 -0
  66. package/lib/module/index.js.map +1 -1
  67. package/lib/module/models.js +336 -0
  68. package/lib/module/models.js.map +1 -0
  69. package/lib/module/native/Cactus.js +61 -13
  70. package/lib/module/native/Cactus.js.map +1 -1
  71. package/lib/module/native/CactusFileSystem.js +3 -0
  72. package/lib/module/native/CactusFileSystem.js.map +1 -1
  73. package/lib/module/native/CactusIndex.js +32 -0
  74. package/lib/module/native/CactusIndex.js.map +1 -0
  75. package/lib/module/native/CactusUtil.js +16 -3
  76. package/lib/module/native/CactusUtil.js.map +1 -1
  77. package/lib/module/native/index.js +1 -0
  78. package/lib/module/native/index.js.map +1 -1
  79. package/lib/module/specs/CactusIndex.nitro.js +4 -0
  80. package/lib/module/specs/CactusIndex.nitro.js.map +1 -0
  81. package/lib/module/telemetry/Telemetry.js +3 -1
  82. package/lib/module/telemetry/Telemetry.js.map +1 -1
  83. package/lib/module/types/CactusIndex.js +2 -0
  84. package/lib/module/types/{CactusModel.js.map → CactusIndex.js.map} +1 -1
  85. package/lib/module/types/CactusLM.js +2 -0
  86. package/lib/module/types/CactusSTT.js +2 -0
  87. package/lib/module/types/common.js +2 -0
  88. package/lib/module/types/{CactusSTTModel.js.map → common.js.map} +1 -1
  89. package/lib/typescript/src/api/Database.d.ts +4 -7
  90. package/lib/typescript/src/api/Database.d.ts.map +1 -1
  91. package/lib/typescript/src/classes/CactusIndex.d.ts +15 -0
  92. package/lib/typescript/src/classes/CactusIndex.d.ts.map +1 -0
  93. package/lib/typescript/src/classes/CactusLM.d.ts +12 -5
  94. package/lib/typescript/src/classes/CactusLM.d.ts.map +1 -1
  95. package/lib/typescript/src/classes/CactusSTT.d.ts +15 -5
  96. package/lib/typescript/src/classes/CactusSTT.d.ts.map +1 -1
  97. package/lib/typescript/src/config/CactusConfig.d.ts +1 -0
  98. package/lib/typescript/src/config/CactusConfig.d.ts.map +1 -1
  99. package/lib/typescript/src/constants/packageVersion.d.ts +1 -1
  100. package/lib/typescript/src/hooks/useCactusIndex.d.ts +14 -0
  101. package/lib/typescript/src/hooks/useCactusIndex.d.ts.map +1 -0
  102. package/lib/typescript/src/hooks/useCactusLM.d.ts +6 -4
  103. package/lib/typescript/src/hooks/useCactusLM.d.ts.map +1 -1
  104. package/lib/typescript/src/hooks/useCactusSTT.d.ts +13 -5
  105. package/lib/typescript/src/hooks/useCactusSTT.d.ts.map +1 -1
  106. package/lib/typescript/src/index.d.ts +6 -4
  107. package/lib/typescript/src/index.d.ts.map +1 -1
  108. package/lib/typescript/src/models.d.ts +6 -0
  109. package/lib/typescript/src/models.d.ts.map +1 -0
  110. package/lib/typescript/src/native/Cactus.d.ts +10 -3
  111. package/lib/typescript/src/native/Cactus.d.ts.map +1 -1
  112. package/lib/typescript/src/native/CactusFileSystem.d.ts +1 -0
  113. package/lib/typescript/src/native/CactusFileSystem.d.ts.map +1 -1
  114. package/lib/typescript/src/native/CactusIndex.d.ts +12 -0
  115. package/lib/typescript/src/native/CactusIndex.d.ts.map +1 -0
  116. package/lib/typescript/src/native/CactusUtil.d.ts.map +1 -1
  117. package/lib/typescript/src/native/index.d.ts +1 -0
  118. package/lib/typescript/src/native/index.d.ts.map +1 -1
  119. package/lib/typescript/src/specs/Cactus.nitro.d.ts +9 -2
  120. package/lib/typescript/src/specs/Cactus.nitro.d.ts.map +1 -1
  121. package/lib/typescript/src/specs/CactusFileSystem.nitro.d.ts +1 -0
  122. package/lib/typescript/src/specs/CactusFileSystem.nitro.d.ts.map +1 -1
  123. package/lib/typescript/src/specs/CactusIndex.nitro.d.ts +24 -0
  124. package/lib/typescript/src/specs/CactusIndex.nitro.d.ts.map +1 -0
  125. package/lib/typescript/src/specs/CactusUtil.nitro.d.ts +1 -1
  126. package/lib/typescript/src/specs/CactusUtil.nitro.d.ts.map +1 -1
  127. package/lib/typescript/src/types/CactusIndex.d.ts +34 -0
  128. package/lib/typescript/src/types/CactusIndex.d.ts.map +1 -0
  129. package/lib/typescript/src/types/CactusLM.d.ts +19 -0
  130. package/lib/typescript/src/types/CactusLM.d.ts.map +1 -1
  131. package/lib/typescript/src/types/CactusSTT.d.ts +21 -1
  132. package/lib/typescript/src/types/CactusSTT.d.ts.map +1 -1
  133. package/lib/typescript/src/types/common.d.ts +28 -0
  134. package/lib/typescript/src/types/common.d.ts.map +1 -0
  135. package/nitro.json +3 -0
  136. package/nitrogen/generated/android/c++/JDeviceInfo.hpp +1 -1
  137. package/nitrogen/generated/android/c++/JFunc_void_double.hpp +1 -1
  138. package/nitrogen/generated/android/c++/JHybridCactusCryptoSpec.cpp +1 -1
  139. package/nitrogen/generated/android/c++/JHybridCactusCryptoSpec.hpp +1 -1
  140. package/nitrogen/generated/android/c++/JHybridCactusDeviceInfoSpec.cpp +1 -1
  141. package/nitrogen/generated/android/c++/JHybridCactusDeviceInfoSpec.hpp +1 -1
  142. package/nitrogen/generated/android/c++/JHybridCactusFileSystemSpec.cpp +17 -1
  143. package/nitrogen/generated/android/c++/JHybridCactusFileSystemSpec.hpp +2 -1
  144. package/nitrogen/generated/android/c++/JHybridCactusImageSpec.cpp +1 -1
  145. package/nitrogen/generated/android/c++/JHybridCactusImageSpec.hpp +1 -1
  146. package/nitrogen/generated/android/cactus+autolinking.cmake +2 -1
  147. package/nitrogen/generated/android/cactus+autolinking.gradle +1 -1
  148. package/nitrogen/generated/android/cactusOnLoad.cpp +11 -1
  149. package/nitrogen/generated/android/cactusOnLoad.hpp +1 -1
  150. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/DeviceInfo.kt +1 -1
  151. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/Func_void_double.kt +1 -1
  152. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusCryptoSpec.kt +1 -1
  153. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusDeviceInfoSpec.kt +1 -1
  154. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusFileSystemSpec.kt +5 -1
  155. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusImageSpec.kt +1 -1
  156. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/cactusOnLoad.kt +1 -1
  157. package/nitrogen/generated/ios/Cactus+autolinking.rb +1 -1
  158. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Bridge.cpp +1 -1
  159. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Bridge.hpp +1 -1
  160. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Umbrella.hpp +1 -1
  161. package/nitrogen/generated/ios/CactusAutolinking.mm +11 -1
  162. package/nitrogen/generated/ios/CactusAutolinking.swift +1 -1
  163. package/nitrogen/generated/ios/c++/HybridCactusCryptoSpecSwift.cpp +1 -1
  164. package/nitrogen/generated/ios/c++/HybridCactusCryptoSpecSwift.hpp +1 -1
  165. package/nitrogen/generated/ios/c++/HybridCactusDeviceInfoSpecSwift.cpp +1 -1
  166. package/nitrogen/generated/ios/c++/HybridCactusDeviceInfoSpecSwift.hpp +1 -1
  167. package/nitrogen/generated/ios/c++/HybridCactusFileSystemSpecSwift.cpp +1 -1
  168. package/nitrogen/generated/ios/c++/HybridCactusFileSystemSpecSwift.hpp +9 -1
  169. package/nitrogen/generated/ios/c++/HybridCactusImageSpecSwift.cpp +1 -1
  170. package/nitrogen/generated/ios/c++/HybridCactusImageSpecSwift.hpp +1 -1
  171. package/nitrogen/generated/ios/swift/DeviceInfo.swift +1 -1
  172. package/nitrogen/generated/ios/swift/Func_void.swift +1 -1
  173. package/nitrogen/generated/ios/swift/Func_void_DeviceInfo.swift +1 -1
  174. package/nitrogen/generated/ios/swift/Func_void_bool.swift +1 -1
  175. package/nitrogen/generated/ios/swift/Func_void_double.swift +1 -1
  176. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +1 -1
  177. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +1 -1
  178. package/nitrogen/generated/ios/swift/Func_void_std__string.swift +1 -1
  179. package/nitrogen/generated/ios/swift/HybridCactusCryptoSpec.swift +1 -1
  180. package/nitrogen/generated/ios/swift/HybridCactusCryptoSpec_cxx.swift +1 -1
  181. package/nitrogen/generated/ios/swift/HybridCactusDeviceInfoSpec.swift +1 -1
  182. package/nitrogen/generated/ios/swift/HybridCactusDeviceInfoSpec_cxx.swift +1 -1
  183. package/nitrogen/generated/ios/swift/HybridCactusFileSystemSpec.swift +2 -1
  184. package/nitrogen/generated/ios/swift/HybridCactusFileSystemSpec_cxx.swift +20 -1
  185. package/nitrogen/generated/ios/swift/HybridCactusImageSpec.swift +1 -1
  186. package/nitrogen/generated/ios/swift/HybridCactusImageSpec_cxx.swift +1 -1
  187. package/nitrogen/generated/shared/c++/CactusIndexGetResult.hpp +84 -0
  188. package/nitrogen/generated/shared/c++/CactusIndexQueryResult.hpp +79 -0
  189. package/nitrogen/generated/shared/c++/DeviceInfo.hpp +1 -1
  190. package/nitrogen/generated/shared/c++/HybridCactusCryptoSpec.cpp +1 -1
  191. package/nitrogen/generated/shared/c++/HybridCactusCryptoSpec.hpp +1 -1
  192. package/nitrogen/generated/shared/c++/HybridCactusDeviceInfoSpec.cpp +1 -1
  193. package/nitrogen/generated/shared/c++/HybridCactusDeviceInfoSpec.hpp +1 -1
  194. package/nitrogen/generated/shared/c++/HybridCactusFileSystemSpec.cpp +2 -1
  195. package/nitrogen/generated/shared/c++/HybridCactusFileSystemSpec.hpp +2 -1
  196. package/nitrogen/generated/shared/c++/HybridCactusImageSpec.cpp +1 -1
  197. package/nitrogen/generated/shared/c++/HybridCactusImageSpec.hpp +1 -1
  198. package/nitrogen/generated/shared/c++/HybridCactusIndexSpec.cpp +27 -0
  199. package/nitrogen/generated/shared/c++/HybridCactusIndexSpec.hpp +76 -0
  200. package/nitrogen/generated/shared/c++/HybridCactusSpec.cpp +8 -1
  201. package/nitrogen/generated/shared/c++/HybridCactusSpec.hpp +11 -3
  202. package/nitrogen/generated/shared/c++/HybridCactusUtilSpec.cpp +1 -1
  203. package/nitrogen/generated/shared/c++/HybridCactusUtilSpec.hpp +2 -2
  204. package/package.json +2 -2
  205. package/src/api/Database.ts +14 -135
  206. package/src/classes/CactusIndex.ts +58 -0
  207. package/src/classes/CactusLM.ts +87 -19
  208. package/src/classes/CactusSTT.ts +134 -20
  209. package/src/config/CactusConfig.ts +3 -0
  210. package/src/constants/packageVersion.ts +1 -1
  211. package/src/hooks/useCactusIndex.ts +195 -0
  212. package/src/hooks/useCactusLM.ts +88 -8
  213. package/src/hooks/useCactusSTT.ts +119 -7
  214. package/src/index.tsx +22 -2
  215. package/src/models.ts +344 -0
  216. package/src/native/Cactus.ts +95 -13
  217. package/src/native/CactusFileSystem.ts +4 -0
  218. package/src/native/CactusIndex.ts +54 -0
  219. package/src/native/CactusUtil.ts +19 -3
  220. package/src/native/index.ts +1 -0
  221. package/src/specs/Cactus.nitro.ts +18 -2
  222. package/src/specs/CactusFileSystem.nitro.ts +2 -0
  223. package/src/specs/CactusIndex.nitro.ts +31 -0
  224. package/src/specs/CactusUtil.nitro.ts +1 -1
  225. package/src/telemetry/Telemetry.ts +1 -1
  226. package/src/types/CactusIndex.ts +40 -0
  227. package/src/types/CactusLM.ts +24 -0
  228. package/src/types/CactusSTT.ts +27 -1
  229. package/src/types/common.ts +28 -0
  230. package/android/src/main/jniLibs/arm64-v8a/libcactus_util.so +0 -0
  231. package/lib/module/types/CactusModel.js +0 -2
  232. package/lib/module/types/CactusSTTModel.js +0 -2
  233. package/lib/typescript/src/types/CactusModel.d.ts +0 -13
  234. package/lib/typescript/src/types/CactusModel.d.ts.map +0 -1
  235. package/lib/typescript/src/types/CactusSTTModel.d.ts +0 -8
  236. package/lib/typescript/src/types/CactusSTTModel.d.ts.map +0 -1
  237. package/src/types/CactusModel.ts +0 -15
  238. package/src/types/CactusSTTModel.ts +0 -10
@@ -0,0 +1,549 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+ #include <vector>
5
+ #include <algorithm>
6
+ #include <cctype>
7
+ #include <map>
8
+ #include <set>
9
+
10
+ namespace gemma {
11
+
12
+ inline std::string to_upper(const std::string& s) {
13
+ std::string result = s;
14
+ for (auto& c : result) c = std::toupper(c);
15
+ return result;
16
+ }
17
+
18
+ inline std::string escape(const std::string& s) {
19
+ return "<escape>" + s + "<escape>";
20
+ }
21
+
22
+ inline void skip_whitespace(const std::string& json, size_t& pos) {
23
+ while (pos < json.length() && std::isspace(json[pos])) pos++;
24
+ }
25
+
26
+ inline std::string extract_json_string(const std::string& json, size_t& pos) {
27
+ std::string value;
28
+ while (pos < json.length() && json[pos] != '"') {
29
+ if (json[pos] == '\\' && pos + 1 < json.length()) {
30
+ pos++;
31
+ if (json[pos] == 'n') value += '\n';
32
+ else if (json[pos] == 't') value += '\t';
33
+ else if (json[pos] == 'r') value += '\r';
34
+ else if (json[pos] == '"') value += '"';
35
+ else if (json[pos] == '\\') value += '\\';
36
+ else value += json[pos];
37
+ } else {
38
+ value += json[pos];
39
+ }
40
+ pos++;
41
+ }
42
+ if (pos < json.length()) pos++;
43
+ return value;
44
+ }
45
+
46
+ std::string format_argument(const std::string& json, size_t& pos, bool escape_keys);
47
+ std::string format_parameters(const std::string& properties_json, const std::string& /*required_json*/);
48
+
49
+ inline std::string format_argument(const std::string& json, size_t& pos, bool escape_keys = true) {
50
+ skip_whitespace(json, pos);
51
+ if (pos >= json.length()) return "";
52
+
53
+ char c = json[pos];
54
+
55
+ if (c == '"') {
56
+ std::string value = extract_json_string(json, pos);
57
+ return escape(value);
58
+ } else if (c == '{') {
59
+ std::string result = "{";
60
+ pos++;
61
+ bool first = true;
62
+
63
+ while (pos < json.length()) {
64
+ skip_whitespace(json, pos);
65
+ if (pos >= json.length() || json[pos] == '}') { pos++; break; }
66
+ if (json[pos] == ',') { pos++; continue; }
67
+
68
+ if (json[pos] != '"') break;
69
+ pos++;
70
+ std::string key = extract_json_string(json, pos);
71
+
72
+ skip_whitespace(json, pos);
73
+ if (pos < json.length() && json[pos] == ':') pos++;
74
+
75
+ std::string value = format_argument(json, pos, escape_keys);
76
+
77
+ if (!first) result += ",";
78
+ first = false;
79
+ if (escape_keys) {
80
+ result += escape(key) + ":" + value;
81
+ } else {
82
+ result += key + ":" + value;
83
+ }
84
+ }
85
+ result += "}";
86
+ return result;
87
+ } else if (c == '[') {
88
+ std::string result = "[";
89
+ pos++;
90
+ bool first = true;
91
+
92
+ while (pos < json.length()) {
93
+ skip_whitespace(json, pos);
94
+ if (pos >= json.length() || json[pos] == ']') { pos++; break; }
95
+ if (json[pos] == ',') { pos++; continue; }
96
+
97
+ std::string value = format_argument(json, pos, escape_keys);
98
+
99
+ if (!first) result += ",";
100
+ first = false;
101
+ result += value;
102
+ }
103
+ result += "]";
104
+ return result;
105
+ } else if (json.compare(pos, 4, "true") == 0) {
106
+ pos += 4;
107
+ return "true";
108
+ } else if (json.compare(pos, 5, "false") == 0) {
109
+ pos += 5;
110
+ return "false";
111
+ } else if (json.compare(pos, 4, "null") == 0) {
112
+ pos += 4;
113
+ return "null";
114
+ } else {
115
+ size_t start = pos;
116
+ while (pos < json.length() && (std::isdigit(json[pos]) || json[pos] == '.' ||
117
+ json[pos] == '-' || json[pos] == '+' || json[pos] == 'e' || json[pos] == 'E')) {
118
+ pos++;
119
+ }
120
+ return json.substr(start, pos - start);
121
+ }
122
+ }
123
+
124
+ inline std::map<std::string, std::string> parse_json_object_raw(const std::string& json, size_t& pos) {
125
+ std::map<std::string, std::string> result;
126
+ skip_whitespace(json, pos);
127
+ if (pos >= json.length() || json[pos] != '{') return result;
128
+ pos++;
129
+
130
+ while (pos < json.length()) {
131
+ skip_whitespace(json, pos);
132
+ if (pos >= json.length() || json[pos] == '}') { pos++; break; }
133
+ if (json[pos] == ',') { pos++; continue; }
134
+
135
+ if (json[pos] != '"') break;
136
+ pos++;
137
+ std::string key = extract_json_string(json, pos);
138
+
139
+ skip_whitespace(json, pos);
140
+ if (pos < json.length() && json[pos] == ':') pos++;
141
+ skip_whitespace(json, pos);
142
+
143
+ size_t value_start = pos;
144
+ if (json[pos] == '"') {
145
+ pos++;
146
+ while (pos < json.length() && json[pos] != '"') {
147
+ if (json[pos] == '\\') pos++;
148
+ pos++;
149
+ }
150
+ pos++;
151
+ } else if (json[pos] == '{') {
152
+ int depth = 1;
153
+ pos++;
154
+ while (pos < json.length() && depth > 0) {
155
+ if (json[pos] == '{') depth++;
156
+ else if (json[pos] == '}') depth--;
157
+ else if (json[pos] == '"') {
158
+ pos++;
159
+ while (pos < json.length() && json[pos] != '"') {
160
+ if (json[pos] == '\\') pos++;
161
+ pos++;
162
+ }
163
+ }
164
+ pos++;
165
+ }
166
+ } else if (json[pos] == '[') {
167
+ int depth = 1;
168
+ pos++;
169
+ while (pos < json.length() && depth > 0) {
170
+ if (json[pos] == '[') depth++;
171
+ else if (json[pos] == ']') depth--;
172
+ else if (json[pos] == '"') {
173
+ pos++;
174
+ while (pos < json.length() && json[pos] != '"') {
175
+ if (json[pos] == '\\') pos++;
176
+ pos++;
177
+ }
178
+ }
179
+ pos++;
180
+ }
181
+ } else {
182
+ while (pos < json.length() && json[pos] != ',' && json[pos] != '}') pos++;
183
+ }
184
+ result[key] = json.substr(value_start, pos - value_start);
185
+ }
186
+ return result;
187
+ }
188
+
189
+ inline std::string get_json_string_value(const std::string& json, size_t pos) {
190
+ skip_whitespace(json, pos);
191
+ if (pos < json.length() && json[pos] == '"') {
192
+ pos++;
193
+ return extract_json_string(json, pos);
194
+ }
195
+ return "";
196
+ }
197
+
198
+ inline std::string format_parameters(const std::string& properties_json, const std::string& /*required_json*/) {
199
+ static const std::set<std::string> standard_keys = {"description", "type", "properties", "required", "nullable"};
200
+
201
+ size_t pos = 0;
202
+ auto properties = parse_json_object_raw(properties_json, pos);
203
+
204
+ std::string result;
205
+ bool first = true;
206
+
207
+ for (const auto& [key, value_json] : properties) {
208
+ if (standard_keys.count(key)) continue;
209
+
210
+ if (!first) result += ",";
211
+ first = false;
212
+
213
+ size_t prop_pos = 0;
214
+ auto prop_obj = parse_json_object_raw(value_json, prop_pos);
215
+
216
+ result += key + ":{";
217
+
218
+ if (prop_obj.count("description")) {
219
+ std::string desc = get_json_string_value(prop_obj["description"], 0);
220
+ result += "description:" + escape(desc);
221
+ }
222
+
223
+ std::string type_val;
224
+ if (prop_obj.count("type")) {
225
+ type_val = get_json_string_value(prop_obj["type"], 0);
226
+ }
227
+
228
+ if (to_upper(type_val) == "STRING") {
229
+ if (prop_obj.count("enum")) {
230
+ size_t enum_pos = 0;
231
+ std::string enum_formatted = format_argument(prop_obj["enum"], enum_pos, true);
232
+ result += ",enum:" + enum_formatted;
233
+ }
234
+ } else if (to_upper(type_val) == "OBJECT") {
235
+ if (prop_obj.count("properties")) {
236
+ std::string nested_required;
237
+ if (prop_obj.count("required")) {
238
+ nested_required = prop_obj["required"];
239
+ }
240
+ result += ",properties:{" + format_parameters(prop_obj["properties"], nested_required) + "}";
241
+ }
242
+ if (prop_obj.count("required")) {
243
+ result += ",required:[";
244
+ size_t req_pos = 0;
245
+ skip_whitespace(prop_obj["required"], req_pos);
246
+ if (req_pos < prop_obj["required"].length() && prop_obj["required"][req_pos] == '[') {
247
+ req_pos++;
248
+ bool req_first = true;
249
+ while (req_pos < prop_obj["required"].length()) {
250
+ skip_whitespace(prop_obj["required"], req_pos);
251
+ if (prop_obj["required"][req_pos] == ']') break;
252
+ if (prop_obj["required"][req_pos] == ',') { req_pos++; continue; }
253
+ if (prop_obj["required"][req_pos] == '"') {
254
+ req_pos++;
255
+ std::string req_item = extract_json_string(prop_obj["required"], req_pos);
256
+ if (!req_first) result += ",";
257
+ req_first = false;
258
+ result += escape(req_item);
259
+ }
260
+ }
261
+ }
262
+ result += "]";
263
+ }
264
+ } else if (to_upper(type_val) == "ARRAY") {
265
+ if (prop_obj.count("items")) {
266
+ result += ",items:{";
267
+ size_t items_pos = 0;
268
+ auto items_obj = parse_json_object_raw(prop_obj["items"], items_pos);
269
+ bool items_first = true;
270
+
271
+ for (const auto& [item_key, item_value] : items_obj) {
272
+ if (!items_first) result += ",";
273
+ items_first = false;
274
+
275
+ if (item_key == "properties") {
276
+ std::string items_required;
277
+ if (items_obj.count("required")) {
278
+ items_required = items_obj["required"];
279
+ }
280
+ result += "properties:{" + format_parameters(item_value, items_required) + "}";
281
+ } else if (item_key == "required") {
282
+ result += "required:[";
283
+ size_t req_pos = 0;
284
+ skip_whitespace(item_value, req_pos);
285
+ if (req_pos < item_value.length() && item_value[req_pos] == '[') {
286
+ req_pos++;
287
+ bool req_first = true;
288
+ while (req_pos < item_value.length()) {
289
+ skip_whitespace(item_value, req_pos);
290
+ if (item_value[req_pos] == ']') break;
291
+ if (item_value[req_pos] == ',') { req_pos++; continue; }
292
+ if (item_value[req_pos] == '"') {
293
+ req_pos++;
294
+ std::string req_item = extract_json_string(item_value, req_pos);
295
+ if (!req_first) result += ",";
296
+ req_first = false;
297
+ result += escape(req_item);
298
+ }
299
+ }
300
+ }
301
+ result += "]";
302
+ } else if (item_key == "type") {
303
+ std::string item_type = get_json_string_value(item_value, 0);
304
+ result += "type:" + escape(to_upper(item_type));
305
+ } else {
306
+ size_t val_pos = 0;
307
+ result += item_key + ":" + format_argument(item_value, val_pos, true);
308
+ }
309
+ }
310
+ result += "}";
311
+ }
312
+ }
313
+
314
+ if (!type_val.empty()) {
315
+ result += ",type:" + escape(to_upper(type_val));
316
+ }
317
+
318
+ result += "}";
319
+ }
320
+
321
+ return result;
322
+ }
323
+
324
+ inline std::string format_function_declaration(const std::string& name,
325
+ const std::string& description,
326
+ const std::string& params_json) {
327
+ std::string result = "declaration:" + name + "{";
328
+ result += "description:" + escape(description);
329
+
330
+ if (!params_json.empty()) {
331
+ result += ",parameters:{";
332
+
333
+ size_t pos = 0;
334
+ auto params = parse_json_object_raw(params_json, pos);
335
+
336
+ if (params.count("properties")) {
337
+ std::string required_json;
338
+ if (params.count("required")) {
339
+ required_json = params["required"];
340
+ }
341
+ result += "properties:{" + format_parameters(params["properties"], required_json) + "}";
342
+ }
343
+
344
+ if (params.count("required")) {
345
+ result += ",required:[";
346
+ size_t req_pos = 0;
347
+ skip_whitespace(params["required"], req_pos);
348
+ if (req_pos < params["required"].length() && params["required"][req_pos] == '[') {
349
+ req_pos++;
350
+ bool first = true;
351
+ while (req_pos < params["required"].length()) {
352
+ skip_whitespace(params["required"], req_pos);
353
+ if (params["required"][req_pos] == ']') break;
354
+ if (params["required"][req_pos] == ',') { req_pos++; continue; }
355
+ if (params["required"][req_pos] == '"') {
356
+ req_pos++;
357
+ std::string item = extract_json_string(params["required"], req_pos);
358
+ if (!first) result += ",";
359
+ first = false;
360
+ result += escape(item);
361
+ }
362
+ }
363
+ }
364
+ result += "]";
365
+ }
366
+
367
+ if (params.count("type")) {
368
+ std::string type_val = get_json_string_value(params["type"], 0);
369
+ result += ",type:" + escape(to_upper(type_val));
370
+ }
371
+
372
+ result += "}";
373
+ }
374
+
375
+ result += "}";
376
+ return result;
377
+ }
378
+
379
+ template<typename ToolFunction>
380
+ inline std::string format_tools(const std::vector<ToolFunction>& tools) {
381
+ if (tools.empty()) return "";
382
+
383
+ std::string result;
384
+ for (const auto& tool : tools) {
385
+ result += "<start_function_declaration>";
386
+ std::string params_json;
387
+ auto it = tool.parameters.find("schema");
388
+ if (it != tool.parameters.end()) {
389
+ params_json = it->second;
390
+ }
391
+
392
+ result += format_function_declaration(tool.name, tool.description, params_json);
393
+ result += "<end_function_declaration>";
394
+ }
395
+ return result;
396
+ }
397
+
398
+
399
+ inline std::string unescape(const std::string& s) {
400
+ const std::string ESCAPE_TAG = "<escape>";
401
+ std::string result = s;
402
+ size_t pos = 0;
403
+ while ((pos = result.find(ESCAPE_TAG, pos)) != std::string::npos) {
404
+ result.erase(pos, ESCAPE_TAG.length());
405
+ }
406
+ return result;
407
+ }
408
+
409
+ inline std::string args_to_json(const std::string& args_content) {
410
+ std::string result = "{";
411
+ size_t pos = 0;
412
+ bool first = true;
413
+
414
+ if (!args_content.empty() && args_content[0] == '{') pos = 1;
415
+
416
+ while (pos < args_content.length()) {
417
+ while (pos < args_content.length() && std::isspace(args_content[pos])) pos++;
418
+ if (pos >= args_content.length() || args_content[pos] == '}') break;
419
+ if (args_content[pos] == ',') { pos++; continue; }
420
+
421
+ size_t key_start = pos;
422
+ while (pos < args_content.length() && args_content[pos] != ':') pos++;
423
+ std::string key = args_content.substr(key_start, pos - key_start);
424
+ if (pos < args_content.length()) pos++;
425
+
426
+ std::string value;
427
+ while (pos < args_content.length() && std::isspace(args_content[pos])) pos++;
428
+
429
+ if (pos < args_content.length()) {
430
+ if (args_content.compare(pos, 8, "<escape>") == 0) {
431
+ pos += 8;
432
+ size_t val_end = args_content.find("<escape>", pos);
433
+ if (val_end != std::string::npos) {
434
+ value = "\"" + args_content.substr(pos, val_end - pos) + "\"";
435
+ pos = val_end + 8;
436
+ }
437
+ } else if (args_content[pos] == '{') {
438
+ int depth = 1;
439
+ size_t start = pos;
440
+ pos++;
441
+ while (pos < args_content.length() && depth > 0) {
442
+ if (args_content[pos] == '{') depth++;
443
+ else if (args_content[pos] == '}') depth--;
444
+ pos++;
445
+ }
446
+ value = args_to_json(args_content.substr(start, pos - start));
447
+ } else if (args_content[pos] == '[') {
448
+ int depth = 1;
449
+ size_t start = pos;
450
+ pos++;
451
+ while (pos < args_content.length() && depth > 0) {
452
+ if (args_content[pos] == '[') depth++;
453
+ else if (args_content[pos] == ']') depth--;
454
+ pos++;
455
+ }
456
+ std::string arr_content = args_content.substr(start + 1, pos - start - 2);
457
+ value = "[";
458
+ size_t arr_pos = 0;
459
+ bool first_item = true;
460
+ while (arr_pos < arr_content.length()) {
461
+ while (arr_pos < arr_content.length() && (std::isspace(arr_content[arr_pos]) || arr_content[arr_pos] == ',')) arr_pos++;
462
+ if (arr_pos >= arr_content.length()) break;
463
+
464
+ if (!first_item) value += ",";
465
+ first_item = false;
466
+
467
+ if (arr_content.compare(arr_pos, 8, "<escape>") == 0) {
468
+ arr_pos += 8;
469
+ size_t end = arr_content.find("<escape>", arr_pos);
470
+ if (end != std::string::npos) {
471
+ value += "\"" + arr_content.substr(arr_pos, end - arr_pos) + "\"";
472
+ arr_pos = end + 8;
473
+ }
474
+ } else {
475
+ size_t end = arr_content.find_first_of(",]", arr_pos);
476
+ if (end == std::string::npos) end = arr_content.length();
477
+ value += arr_content.substr(arr_pos, end - arr_pos);
478
+ arr_pos = end;
479
+ }
480
+ }
481
+ value += "]";
482
+ } else {
483
+ size_t val_start = pos;
484
+ while (pos < args_content.length() && args_content[pos] != ',' && args_content[pos] != '}') {
485
+ pos++;
486
+ }
487
+ value = args_content.substr(val_start, pos - val_start);
488
+ while (!value.empty() && std::isspace(value.back())) value.pop_back();
489
+ }
490
+ }
491
+
492
+ if (!first) result += ",";
493
+ first = false;
494
+ result += "\"" + key + "\":" + value;
495
+ }
496
+
497
+ result += "}";
498
+ return result;
499
+ }
500
+
501
+ inline void parse_function_calls(std::string& response, std::vector<std::string>& function_calls) {
502
+ const std::string CALL_START = "<start_function_call>";
503
+ const std::string CALL_END = "<end_function_call>";
504
+ size_t pos = 0;
505
+
506
+ while ((pos = response.find(CALL_START, pos)) != std::string::npos) {
507
+ size_t content_start = pos + CALL_START.length();
508
+ size_t call_end_pos = response.find(CALL_END, content_start);
509
+
510
+ size_t content_end = (call_end_pos != std::string::npos) ? call_end_pos : response.length();
511
+ std::string call_content = response.substr(content_start, content_end - content_start);
512
+
513
+ if (call_content.compare(0, 5, "call:") == 0) {
514
+ size_t brace_pos = call_content.find('{');
515
+
516
+ if (brace_pos == std::string::npos) {
517
+ size_t sep_pos = call_content.find_first_of(", ", 5);
518
+ if (sep_pos != std::string::npos) {
519
+ std::string func_name = call_content.substr(5, sep_pos - 5);
520
+ size_t args_start = sep_pos + 1;
521
+ while (args_start < call_content.length() &&
522
+ (call_content[args_start] == ' ' || call_content[args_start] == ',')) {
523
+ args_start++;
524
+ }
525
+ std::string args_content = "{" + call_content.substr(args_start);
526
+ if (args_content.back() != '}') args_content += "}";
527
+
528
+ std::string args_json = args_to_json(args_content);
529
+ std::string json_call = "{\"name\":\"" + func_name + "\",\"arguments\":" + args_json + "}";
530
+ function_calls.push_back(json_call);
531
+ }
532
+ } else {
533
+ std::string func_name = call_content.substr(5, brace_pos - 5);
534
+ std::string args_content = call_content.substr(brace_pos);
535
+ if (args_content.back() != '}') args_content += "}";
536
+
537
+ std::string args_json = args_to_json(args_content);
538
+ std::string json_call = "{\"name\":\"" + func_name + "\",\"arguments\":" + args_json + "}";
539
+ function_calls.push_back(json_call);
540
+ }
541
+ }
542
+
543
+ size_t erase_end = (call_end_pos != std::string::npos) ?
544
+ call_end_pos + CALL_END.length() : response.length();
545
+ response.erase(pos, erase_end - pos);
546
+ }
547
+ }
548
+
549
+ } // namespace gemma