@antfly/embedded-linux-x64 0.0.0 → 0.3.0-rc.4

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 (70) hide show
  1. package/LICENSES/Apache-2.0.txt +202 -0
  2. package/LICENSES/source-map/apache_engine_files.txt +4 -0
  3. package/LICENSES/source-map/embedded_asset_licenses.json +91 -0
  4. package/LICENSES/source-map/source_license_roots.json +35 -0
  5. package/LICENSES/third-party/Brotli-Zig-MIT.txt +39 -0
  6. package/LICENSES/third-party/Bzip2-1.0.6.txt +42 -0
  7. package/LICENSES/third-party/HTTPX-MIT.txt +21 -0
  8. package/LICENSES/third-party/LMDB-lmdb-h-notice.txt +26 -0
  9. package/LICENSES/third-party/LMDB-mdb-c-notice.txt +26 -0
  10. package/LICENSES/third-party/LMDB-midl-c-notice.txt +11 -0
  11. package/LICENSES/third-party/LMDB-midl-h-notice.txt +11 -0
  12. package/LICENSES/third-party/NV-Codec-CUDA-MIT.txt +22 -0
  13. package/LICENSES/third-party/NV-Codec-NVIDIA-MIT.txt +22 -0
  14. package/LICENSES/third-party/OpenLDAP-2.8.txt +47 -0
  15. package/LICENSES/third-party/PacketVideo-AAC-notice.txt +2 -0
  16. package/LICENSES/third-party/PyTorch-BSD-3-Clause.txt +84 -0
  17. package/LICENSES/third-party/Roboto-Apache-2.0.txt +201 -0
  18. package/LICENSES/third-party/Roboto-COPYRIGHT.txt +1 -0
  19. package/LICENSES/third-party/SciPy-rectangular-lsap-BSD-3-Clause.txt +29 -0
  20. package/LICENSES/third-party/Tree-Sitter-Go-MIT.txt +21 -0
  21. package/LICENSES/third-party/Tree-Sitter-Python-MIT.txt +21 -0
  22. package/LICENSES/third-party/Tree-Sitter-Rust-MIT.txt +21 -0
  23. package/LICENSES/third-party/Unicode-V3.txt +39 -0
  24. package/LICENSES/third-party/WHATWG-Encoding-BSD-3-Clause.txt +28 -0
  25. package/LICENSES/third-party/XZ-Embedded-0BSD.txt +13 -0
  26. package/LICENSES/third-party/Yuku-MIT.txt +21 -0
  27. package/LICENSES/third-party/Zig-SHA256-MIT.txt +19 -0
  28. package/LICENSES/third-party/Zig-Stdlib-MIT.txt +21 -0
  29. package/LICENSES/third-party/Zig-TLS-MIT.txt +19 -0
  30. package/LICENSES/third-party/dav1d-BSD-2-Clause.txt +23 -0
  31. package/LICENSES/third-party/libvpx-BSD-3-Clause.txt +30 -0
  32. package/README.md +1 -5
  33. package/THIRD_PARTY_NOTICES.md +1253 -0
  34. package/include/antfly.h +846 -0
  35. package/lib/libantfly.so +4 -0
  36. package/lib/pkgconfig/libantfly.pc +11 -0
  37. package/package.json +13 -8
  38. package/share/licenses/libantfly/LICENSE +202 -0
  39. package/share/licenses/libantfly/LICENSES/Apache-2.0.txt +202 -0
  40. package/share/licenses/libantfly/LICENSES/third-party/Brotli-Zig-MIT.txt +39 -0
  41. package/share/licenses/libantfly/LICENSES/third-party/Bzip2-1.0.6.txt +42 -0
  42. package/share/licenses/libantfly/LICENSES/third-party/HTTPX-MIT.txt +21 -0
  43. package/share/licenses/libantfly/LICENSES/third-party/LMDB-lmdb-h-notice.txt +26 -0
  44. package/share/licenses/libantfly/LICENSES/third-party/LMDB-mdb-c-notice.txt +26 -0
  45. package/share/licenses/libantfly/LICENSES/third-party/LMDB-midl-c-notice.txt +11 -0
  46. package/share/licenses/libantfly/LICENSES/third-party/LMDB-midl-h-notice.txt +11 -0
  47. package/share/licenses/libantfly/LICENSES/third-party/NV-Codec-CUDA-MIT.txt +22 -0
  48. package/share/licenses/libantfly/LICENSES/third-party/NV-Codec-NVIDIA-MIT.txt +22 -0
  49. package/share/licenses/libantfly/LICENSES/third-party/OpenLDAP-2.8.txt +47 -0
  50. package/share/licenses/libantfly/LICENSES/third-party/PacketVideo-AAC-notice.txt +2 -0
  51. package/share/licenses/libantfly/LICENSES/third-party/PyTorch-BSD-3-Clause.txt +84 -0
  52. package/share/licenses/libantfly/LICENSES/third-party/Roboto-Apache-2.0.txt +201 -0
  53. package/share/licenses/libantfly/LICENSES/third-party/Roboto-COPYRIGHT.txt +1 -0
  54. package/share/licenses/libantfly/LICENSES/third-party/SciPy-rectangular-lsap-BSD-3-Clause.txt +29 -0
  55. package/share/licenses/libantfly/LICENSES/third-party/Tree-Sitter-Go-MIT.txt +21 -0
  56. package/share/licenses/libantfly/LICENSES/third-party/Tree-Sitter-Python-MIT.txt +21 -0
  57. package/share/licenses/libantfly/LICENSES/third-party/Tree-Sitter-Rust-MIT.txt +21 -0
  58. package/share/licenses/libantfly/LICENSES/third-party/Unicode-V3.txt +39 -0
  59. package/share/licenses/libantfly/LICENSES/third-party/WHATWG-Encoding-BSD-3-Clause.txt +28 -0
  60. package/share/licenses/libantfly/LICENSES/third-party/XZ-Embedded-0BSD.txt +13 -0
  61. package/share/licenses/libantfly/LICENSES/third-party/Yuku-MIT.txt +21 -0
  62. package/share/licenses/libantfly/LICENSES/third-party/Zig-SHA256-MIT.txt +19 -0
  63. package/share/licenses/libantfly/LICENSES/third-party/Zig-Stdlib-MIT.txt +21 -0
  64. package/share/licenses/libantfly/LICENSES/third-party/Zig-TLS-MIT.txt +19 -0
  65. package/share/licenses/libantfly/LICENSES/third-party/dav1d-BSD-2-Clause.txt +23 -0
  66. package/share/licenses/libantfly/LICENSES/third-party/libvpx-BSD-3-Clause.txt +30 -0
  67. package/share/licenses/libantfly/THIRD_PARTY_NOTICES.md +1253 -0
  68. package/share/licenses/libantfly/scripts/apache_engine_files.txt +4 -0
  69. package/share/licenses/libantfly/scripts/embedded_asset_licenses.json +91 -0
  70. package/share/licenses/libantfly/scripts/source_license_roots.json +35 -0
@@ -0,0 +1,846 @@
1
+ // Copyright 2026 Antfly, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ #ifndef ANTFLY_H
17
+ #define ANTFLY_H
18
+
19
+ /* ABI implemented by this header; compare with antfly_abi_version() at runtime. */
20
+ #define ANTFLY_ABI_VERSION 3
21
+
22
+ #include <stdbool.h>
23
+ #include <stddef.h>
24
+ #include <stdint.h>
25
+
26
+ #ifdef __cplusplus
27
+ extern "C" {
28
+ #endif
29
+
30
+ typedef enum antfly_error_code {
31
+ ANTFLY_OK = 0,
32
+ ANTFLY_INVALID_ARGUMENT = 1,
33
+ ANTFLY_NOT_FOUND = 2,
34
+ ANTFLY_VERSION_CONFLICT = 3,
35
+ ANTFLY_INTENT_CONFLICT = 4,
36
+ ANTFLY_TXN_NOT_FOUND = 5,
37
+ ANTFLY_BUSY = 6,
38
+ /* The operation crossed its publication point, but crash durability could
39
+ * not be confirmed. Inspect the destination; do not retry automatically. */
40
+ ANTFLY_OUTCOME_UNKNOWN = 7,
41
+ /* The operation requires a capability unavailable on this platform or
42
+ * filesystem. Retrying unchanged will not succeed. */
43
+ ANTFLY_UNSUPPORTED = 8,
44
+ /* Derived work stalled or a worker failed. Inspect pending-work diagnostics
45
+ * and repair or reopen the database; primary-only writes may still succeed. */
46
+ ANTFLY_STALLED = 9,
47
+ /* The operation was cancelled, including a pending replacement or a
48
+ * progress/stream callback returning false. */
49
+ ANTFLY_CANCELLED = 10,
50
+ /* Stable replacement precondition failures, distinct from malformed input. */
51
+ ANTFLY_REPLACEMENT_FAILED = 11,
52
+ ANTFLY_REPLACEMENT_PENDING = 12,
53
+ ANTFLY_REPLACEMENT_CONFIGURATION_MISMATCH = 13,
54
+ ANTFLY_INTERNAL = 255,
55
+ } antfly_error_code;
56
+
57
+ /*
58
+ * C ABI conventions:
59
+ *
60
+ * - Functions return ANTFLY_OK on success. Any other antfly_error_code is an
61
+ * error and should be handled with the stable strings returned by
62
+ * antfly_error_code_name and antfly_error_code_description.
63
+ * - ANTFLY_OUTCOME_UNKNOWN is not safe to retry automatically: publication
64
+ * completed in the running process, but crash durability was not confirmed.
65
+ * Inspect the caller-supplied destination before deciding how to proceed.
66
+ * - ANTFLY_UNSUPPORTED is not transient. For file restore operations it can
67
+ * mean the source filesystem lacks required advisory locking; copy the
68
+ * archive to a supported local filesystem before retrying.
69
+ * - antfly_slice is borrowed input. The caller owns the memory and must keep it
70
+ * valid for the duration of the call.
71
+ * - antfly_buffer is owned output. On success, the caller owns the returned
72
+ * memory and must release it with antfly_buffer_free, or
73
+ * antfly_buffer_free_zero when the bytes may contain sensitive data.
74
+ * - Status, maintenance, backup, restore, check, and snapshot calls reset
75
+ * antfly_buffer outputs to {NULL, 0} before validating arguments. Other
76
+ * buffer-returning calls require a valid output pointer and only transfer
77
+ * ownership after ANTFLY_OK.
78
+ * - antfly_db handles are owned by the caller after a successful open and
79
+ * must be closed with antfly_db_close. Closing NULL, an already closed
80
+ * handle, or a handle closed concurrently is allowed.
81
+ * - Search result structs own nested allocations only after ANTFLY_OK and must
82
+ * be released with their matching *_free function.
83
+ *
84
+ * Naming: antfly_* functions are library-level and take no database handle;
85
+ * antfly_db_* functions take an antfly_db handle of any storage kind;
86
+ * antfly_lite_* functions operate on the .aflite single-file format itself,
87
+ * plus shortcuts for opening one; antfly_inference_* functions take an
88
+ * antfly_inference handle and run inference without a database.
89
+ */
90
+
91
+ /* An open database. Opaque; see antfly_db_open_with_options. */
92
+ typedef struct antfly_db antfly_db;
93
+
94
+ typedef enum antfly_txn_status {
95
+ ANTFLY_TXN_PENDING = 0,
96
+ ANTFLY_TXN_COMMITTED = 1,
97
+ ANTFLY_TXN_ABORTED = 2,
98
+ } antfly_txn_status;
99
+
100
+ typedef struct antfly_slice {
101
+ const uint8_t *ptr;
102
+ size_t len;
103
+ } antfly_slice;
104
+
105
+ typedef struct antfly_buffer {
106
+ uint8_t *ptr;
107
+ size_t len;
108
+ } antfly_buffer;
109
+
110
+ #define ANTFLY_OPEN_MODE_WRITER 0u
111
+ #define ANTFLY_OPEN_MODE_READONLY 1u
112
+ #define ANTFLY_OPEN_MODE_STATUS_ONLY 2u
113
+
114
+ #define ANTFLY_STORAGE_KIND_DIRECTORY 0u
115
+ #define ANTFLY_STORAGE_KIND_LITE 1u
116
+
117
+ #define ANTFLY_PROFILE_NATIVE 0u
118
+ #define ANTFLY_PROFILE_HOSTED 1u
119
+
120
+ #define ANTFLY_OPEN_FLAG_NO_SYNC (1u << 0)
121
+ #define ANTFLY_OPEN_FLAG_TTL_CLEANUP (1u << 1)
122
+ #define ANTFLY_OPEN_FLAG_REMOTE_PROVIDER_CONFIGURED (1u << 2)
123
+ #define ANTFLY_OPEN_FLAG_LOCAL_RUNTIME_CONFIGURED (1u << 3)
124
+ #define ANTFLY_OPEN_FLAG_GENERATED_ENRICHMENT_REPLAY (1u << 4)
125
+
126
+ /* `inference.mode` values reported by antfly_db_status_json. */
127
+ #define ANTFLY_INFERENCE_MODE_CALLER_SUPPLIED_OR_DISABLED "caller_supplied_or_disabled"
128
+ #define ANTFLY_INFERENCE_MODE_CALLER_SUPPLIED_ARTIFACTS "caller_supplied_artifacts"
129
+ #define ANTFLY_INFERENCE_MODE_REMOTE_PROVIDER "remote_provider"
130
+ #define ANTFLY_INFERENCE_MODE_LOCAL_EMBEDDED "local_embedded"
131
+ #define ANTFLY_INFERENCE_MODE_MANUAL_MAINTENANCE "manual_maintenance"
132
+ #define ANTFLY_INFERENCE_MODE_DISABLED_DEFERRED "disabled_deferred"
133
+
134
+ typedef struct antfly_open_options {
135
+ uint32_t abi_size;
136
+ uint32_t storage_kind;
137
+ uint32_t open_mode;
138
+ uint32_t profile;
139
+ uint32_t flags;
140
+ uint32_t reserved0;
141
+ uint64_t map_size;
142
+ bool ttl_cleanup_enabled;
143
+ bool ttl_cleanup_lease_owned;
144
+ uint32_t ttl_cleanup_batch_size;
145
+ antfly_slice ttl_cleanup_owner_id;
146
+ uint64_t ttl_cleanup_lease_ttl_ms;
147
+ uint64_t ttl_cleanup_interval_ms;
148
+ uint64_t ttl_cleanup_grace_period_ns;
149
+ /* Explicit embedded-inference resource-budget overrides in MiB, 0
150
+ * meaning automatic/host-detected sizing. Only consulted when `flags`
151
+ * carries ANTFLY_OPEN_FLAG_LOCAL_RUNTIME_CONFIGURED; mirror the antfly
152
+ * CLI's --inference-host-budget-mb/--inference-backend-budget-mb/
153
+ * --process-memory-budget-mb. */
154
+ uint32_t inference_host_budget_mb;
155
+ uint32_t inference_backend_budget_mb;
156
+ uint32_t inference_process_memory_budget_mb;
157
+ uint32_t inference_combined_budget_mb;
158
+ uint32_t inference_kv_budget_mb;
159
+ uint32_t inference_scratch_budget_mb;
160
+ /* Milliseconds to retry a Lite operation while another process holds the
161
+ * writer lease (ANTFLY_BUSY), like sqlite3_busy_timeout. 0 fails immediately. */
162
+ uint64_t busy_timeout_ms;
163
+ uint64_t reserved[6];
164
+ /* Optional model directory for database enrichments; empty uses default. */
165
+ antfly_slice models_dir;
166
+ } antfly_open_options;
167
+
168
+ /*
169
+ * Call antfly_open_options_init before setting fields manually. The abi_size
170
+ * field must remain the value returned by antfly_open_options_size so future
171
+ * library versions can detect the caller's struct layout.
172
+ */
173
+
174
+
175
+ typedef struct antfly_write_intent {
176
+ antfly_slice key;
177
+ antfly_slice value;
178
+ bool is_delete;
179
+ } antfly_write_intent;
180
+
181
+ typedef struct antfly_version_predicate {
182
+ antfly_slice key;
183
+ uint64_t expected_version;
184
+ } antfly_version_predicate;
185
+
186
+ typedef struct antfly_dense_search_hit {
187
+ uint8_t *id_ptr;
188
+ size_t id_len;
189
+ float score;
190
+ } antfly_dense_search_hit;
191
+
192
+ typedef struct antfly_dense_search_result {
193
+ antfly_dense_search_hit *hits_ptr;
194
+ size_t hit_count;
195
+ uint32_t total_hits;
196
+ uint64_t identity_read_generation;
197
+ } antfly_dense_search_result;
198
+
199
+ typedef struct antfly_packed_dense_search_hit {
200
+ size_t id_offset;
201
+ size_t id_len;
202
+ float score;
203
+ } antfly_packed_dense_search_hit;
204
+
205
+ typedef struct antfly_packed_dense_search_result {
206
+ antfly_packed_dense_search_hit *hits_ptr;
207
+ size_t hit_count;
208
+ uint32_t total_hits;
209
+ uint8_t *ids_ptr;
210
+ size_t ids_len;
211
+ uint64_t identity_read_generation;
212
+ } antfly_packed_dense_search_result;
213
+
214
+ typedef struct antfly_dense_search_profile {
215
+ uint64_t total_ns;
216
+ uint64_t index_lookup_ns;
217
+ uint64_t search_ns;
218
+ uint64_t hits_ns;
219
+ uint64_t fallback_ns;
220
+ uint64_t hbc_total_ns;
221
+ uint64_t hbc_setup_ns;
222
+ uint64_t hbc_root_load_ns;
223
+ uint64_t hbc_node_cache_miss_ns;
224
+ uint64_t hbc_node_cache_misses;
225
+ uint64_t hbc_quantized_cache_miss_ns;
226
+ uint64_t hbc_quantized_cache_misses;
227
+ uint64_t hbc_child_expand_ns;
228
+ uint64_t hbc_leaf_score_ns;
229
+ uint64_t hbc_rerank_ns;
230
+ uint64_t hbc_rerank_vector_load_ns;
231
+ uint64_t hbc_rerank_distance_ns;
232
+ uint64_t hbc_nodes_visited;
233
+ uint64_t hbc_leaves_explored;
234
+ uint64_t hbc_reranked_vectors;
235
+ uint32_t hit_count;
236
+ uint32_t total_hits;
237
+ bool used_fast_path;
238
+ } antfly_dense_search_profile;
239
+
240
+ typedef struct antfly_dense_wire_search_profile {
241
+ uint64_t total_ns;
242
+ uint64_t decode_ns;
243
+ uint64_t search_ns;
244
+ uint64_t resolve_ns;
245
+ uint64_t encode_ns;
246
+ uint64_t fallback_ns;
247
+ uint64_t hbc_total_ns;
248
+ uint64_t hbc_setup_ns;
249
+ uint64_t hbc_root_load_ns;
250
+ uint64_t hbc_node_cache_miss_ns;
251
+ uint64_t hbc_node_cache_misses;
252
+ uint64_t hbc_quantized_cache_miss_ns;
253
+ uint64_t hbc_quantized_cache_misses;
254
+ uint64_t hbc_child_expand_ns;
255
+ uint64_t hbc_leaf_score_ns;
256
+ uint64_t hbc_rerank_ns;
257
+ uint64_t hbc_rerank_vector_load_ns;
258
+ uint64_t hbc_rerank_distance_ns;
259
+ uint64_t hbc_nodes_visited;
260
+ uint64_t hbc_leaves_explored;
261
+ uint64_t hbc_reranked_vectors;
262
+ uint32_t hit_count;
263
+ uint32_t total_hits;
264
+ bool used_fast_path;
265
+ } antfly_dense_wire_search_profile;
266
+
267
+ typedef struct antfly_scan_hash_entry {
268
+ uint8_t *id_ptr;
269
+ size_t id_len;
270
+ uint64_t hash;
271
+ } antfly_scan_hash_entry;
272
+
273
+ typedef struct antfly_scan_hash_result {
274
+ antfly_scan_hash_entry *entries_ptr;
275
+ size_t entry_count;
276
+ } antfly_scan_hash_result;
277
+
278
+ uint32_t antfly_abi_version(void);
279
+ uint32_t antfly_open_options_size(void);
280
+ /* Borrowed thread-local detail for the last error-code-returning call. Empty
281
+ * on success or when no concrete validation detail is available. Copy before
282
+ * another call on this thread; this accessor never changes the detail. */
283
+ const char *antfly_last_error_detail(void);
284
+ /* Code associated with the retained detail; ANTFLY_OK after success. */
285
+ antfly_error_code antfly_last_error_code(void);
286
+ const char *antfly_error_code_name(antfly_error_code code);
287
+ const char *antfly_error_code_description(antfly_error_code code);
288
+ antfly_error_code antfly_open_options_init(antfly_open_options *options);
289
+
290
+ /*
291
+ * Threading contract, like sqlite3_threadsafe(). ANTFLY_THREADING_SERIALIZED
292
+ * means any thread may call any function on any handle concurrently: reads
293
+ * run in parallel, writes on one handle queue behind each other, and schema
294
+ * or admin changes wait for in-flight calls. See zig/CAPI.md "Thread Safety".
295
+ */
296
+ #define ANTFLY_THREADING_SERIALIZED 1u
297
+ /*
298
+ * Minimum native stack, in bytes, for any thread that calls into libantfly.
299
+ * The storage engine keeps sizable buffers on the stack; release builds use
300
+ * about 2 MiB at peak and debug builds more. 8 MiB is the Linux and macOS
301
+ * main-thread default, but secondary threads are often smaller (512 KiB for
302
+ * macOS pthreads, 2 MiB for Rust std threads): size them explicitly.
303
+ */
304
+ #define ANTFLY_MIN_THREAD_STACK_SIZE (8u * 1024u * 1024u)
305
+ uint32_t antfly_threading_mode(void);
306
+
307
+ /*
308
+ * Storage-neutral opens. ANTFLY_STORAGE_KIND_DIRECTORY opens a normal
309
+ * single-node Antfly directory; ANTFLY_STORAGE_KIND_LITE opens a .aflite
310
+ * single-file database. antfly_db_create_with_options has exclusive-create
311
+ * semantics for ANTFLY_STORAGE_KIND_LITE; directory storage is opened (and
312
+ * created if missing) with antfly_db_open_with_options. NULL options open
313
+ * directory storage with defaults.
314
+ */
315
+ antfly_error_code antfly_db_open(const char *path, antfly_db **out_db);
316
+ antfly_error_code antfly_db_open_with_options(
317
+ const char *path,
318
+ const antfly_open_options *options,
319
+ antfly_db **out_db
320
+ );
321
+ antfly_error_code antfly_db_create_with_options(
322
+ const char *path,
323
+ const antfly_open_options *options,
324
+ antfly_db **out_db
325
+ );
326
+ void antfly_db_close(antfly_db *db);
327
+
328
+ /*
329
+ * Shortcuts for ANTFLY_STORAGE_KIND_LITE with default options.
330
+ * antfly_lite_create* creates a new .aflite database; antfly_lite_open*
331
+ * opens an existing one and never creates a missing file or migrates a
332
+ * pre-release layout.
333
+ */
334
+ antfly_error_code antfly_lite_open(const char *path, antfly_db **out_db);
335
+ antfly_error_code antfly_lite_create(const char *path, antfly_db **out_db);
336
+ antfly_error_code antfly_lite_open_hosted(const char *path, antfly_db **out_db);
337
+ antfly_error_code antfly_lite_create_hosted(const char *path, antfly_db **out_db);
338
+ antfly_error_code antfly_lite_open_readonly(const char *path, antfly_db **out_db);
339
+ antfly_error_code antfly_lite_open_status_only(const char *path, antfly_db **out_db);
340
+
341
+ /* Storage identity, stats, pending work, inference state, and capabilities. */
342
+ antfly_error_code antfly_db_status_json(antfly_db *db, antfly_buffer *out);
343
+ antfly_error_code antfly_db_capabilities_json(antfly_db *db, antfly_buffer *out);
344
+
345
+ /*
346
+ * Portable .afb backups work across storage kinds: a backup of either kind
347
+ * restores or imports into either kind. antfly_db_import_backup requires an
348
+ * empty database with no open table handles, SQL sessions, or cursors.
349
+ * Archives contain the complete catalog and every live table namespace.
350
+ * Backup/import require the database handle. antfly_restore_backup_json and
351
+ * antfly_restore_backup_file_json create a new database at dest_path whose
352
+ * storage kind comes from `options` (NULL means directory storage); other
353
+ * option fields apply when the restored database is opened. `replace`
354
+ * atomically replaces an existing destination.
355
+ */
356
+ antfly_error_code antfly_db_backup(antfly_db *db, antfly_buffer *out);
357
+ /** Portable backup with optional {"tables":["default","healthy"]} scope.
358
+ * Explicit scope includes default and exactly the named tables. Full backup
359
+ * fails closed if any table is unavailable; it never silently omits data. */
360
+ antfly_error_code antfly_db_backup_json(antfly_db *db, antfly_slice options_json, antfly_buffer *out);
361
+ antfly_error_code antfly_db_import_backup(antfly_db *db, antfly_slice backup);
362
+ antfly_error_code antfly_restore_backup_json(
363
+ const char *dest_path,
364
+ const antfly_open_options *options,
365
+ antfly_slice backup,
366
+ bool replace,
367
+ antfly_buffer *out
368
+ );
369
+ antfly_error_code antfly_restore_backup_file_json(
370
+ const char *dest_path,
371
+ const antfly_open_options *options,
372
+ const char *backup_path,
373
+ bool replace,
374
+ antfly_buffer *out
375
+ );
376
+
377
+ /* Operations on the .aflite file format. */
378
+ antfly_error_code antfly_lite_check_json(antfly_db *db, antfly_buffer *out);
379
+ antfly_error_code antfly_lite_check_file_json(const char *path, antfly_buffer *out);
380
+ antfly_error_code antfly_lite_copy_stable_snapshot_json(
381
+ antfly_db *db,
382
+ const char *dest_path,
383
+ bool replace,
384
+ antfly_buffer *out
385
+ );
386
+ antfly_error_code antfly_lite_copy_stable_snapshot_file_json(
387
+ const char *src_path,
388
+ const char *dest_path,
389
+ bool replace,
390
+ antfly_buffer *out
391
+ );
392
+ antfly_error_code antfly_lite_compact_json(antfly_db *db, antfly_buffer *out);
393
+ antfly_error_code antfly_lite_vacuum_json(antfly_db *db, antfly_buffer *out);
394
+
395
+ void antfly_buffer_free(antfly_buffer *buffer);
396
+ void antfly_buffer_free_zero(antfly_buffer *buffer);
397
+ void antfly_dense_search_result_free(antfly_dense_search_result *result);
398
+ void antfly_packed_dense_search_result_free(antfly_packed_dense_search_result *result);
399
+ void antfly_scan_hash_result_free(antfly_scan_hash_result *result);
400
+
401
+ antfly_error_code antfly_db_batch(
402
+ antfly_db *db,
403
+ const antfly_write_intent *writes,
404
+ size_t write_count,
405
+ const antfly_version_predicate *predicates,
406
+ size_t predicate_count,
407
+ uint64_t timestamp_ns,
408
+ uint8_t sync_level
409
+ );
410
+ antfly_error_code antfly_db_batch_json(
411
+ antfly_db *db,
412
+ antfly_slice request_json,
413
+ antfly_buffer *out
414
+ );
415
+ antfly_error_code antfly_db_begin_transaction_with_id(
416
+ antfly_db *db,
417
+ const uint8_t (*txn_id)[16],
418
+ uint64_t timestamp_ns,
419
+ const antfly_slice *participants,
420
+ size_t participant_count
421
+ );
422
+ antfly_error_code antfly_db_write_transaction(
423
+ antfly_db *db,
424
+ const uint8_t (*txn_id)[16],
425
+ const antfly_write_intent *writes,
426
+ size_t write_count,
427
+ const antfly_version_predicate *predicates,
428
+ size_t predicate_count
429
+ );
430
+ antfly_error_code antfly_db_resolve_intents(
431
+ antfly_db *db,
432
+ const uint8_t (*txn_id)[16],
433
+ uint8_t status,
434
+ uint64_t commit_version
435
+ );
436
+ antfly_error_code antfly_db_get_transaction_status(
437
+ antfly_db *db,
438
+ const uint8_t (*txn_id)[16],
439
+ uint8_t *out_status
440
+ );
441
+ antfly_error_code antfly_db_get_commit_version(
442
+ antfly_db *db,
443
+ const uint8_t (*txn_id)[16],
444
+ uint64_t *out_commit_version
445
+ );
446
+ antfly_error_code antfly_db_get_timestamp(antfly_db *db, antfly_slice key, uint64_t *out_timestamp);
447
+ antfly_error_code antfly_db_lookup_json(antfly_db *db, antfly_slice key, antfly_buffer *out);
448
+ antfly_error_code antfly_db_get_raw(antfly_db *db, antfly_slice key, antfly_buffer *out);
449
+ antfly_error_code antfly_db_get_schema_json(antfly_db *db, antfly_buffer *out);
450
+ antfly_error_code antfly_db_set_schema_json(antfly_db *db, antfly_slice schema_json);
451
+ antfly_error_code antfly_db_run_until_idle(antfly_db *db);
452
+ antfly_error_code antfly_db_run_until_idle_json(antfly_db *db, antfly_buffer *out);
453
+ antfly_error_code antfly_db_pending_work_stats_json(antfly_db *db, antfly_buffer *out);
454
+ antfly_error_code antfly_db_replay_generated_enrichments_json(antfly_db *db, antfly_buffer *out);
455
+ antfly_error_code antfly_db_list_indexes_json(antfly_db *db, antfly_buffer *out);
456
+ /** Render a durable resolver's key without writes. Mention JSON: {"text","label"}.
457
+ * Returns {"minted_key","key","table","config_generation"}; key follows configured aliases.
458
+ * Free output with antfly_buffer_free. ANN matching is not performed. */
459
+ antfly_error_code antfly_db_render_resolver_key_json(antfly_db *db, antfly_slice resolver_name, antfly_slice mention_json, antfly_buffer *out_json);
460
+
461
+ /* Resolve {"text":"..."} through the resolver's configured asset extractor, or
462
+ * {"extraction":{"entities":[...]}} through the same resolver. Includes aliases,
463
+ * mention embeddings, ANN candidates and scoring. Returns {extraction,resolution}
464
+ * with canonical doc_refs and decisions. Does not write documents or artifacts.
465
+ * Requires an asset-scoped resolver; text requires an extractor producer. */
466
+ /** Execute the native memory/v1 contract on a named space. Request includes
467
+ * action, body and idempotency_key for mutations. The embedded database owner
468
+ * is the authority; principal is local attribution, never a remote identity. */
469
+ antfly_error_code antfly_db_memory_json(antfly_db *db, antfly_slice space, antfly_slice request_json, antfly_buffer *out_json);
470
+ antfly_error_code antfly_db_resolve_query_json(antfly_db *db, antfly_slice resolver_name, antfly_slice request_json, antfly_buffer *out_json);
471
+ /** Merge fully rendered keys: {"key":"concept/old","target":"concept/new"}.
472
+ * Durable and idempotent. Cycles/redirect replacement are rejected. Drain with
473
+ * antfly_db_run_until_idle to re-resolve existing artifacts and replace mention edges.
474
+ * Promotion-enabled resolvers also reconcile entity documents. Arbitrary application
475
+ * references and manually supplied graph edges are not rewritten.
476
+ * May return ANTFLY_BUSY during replay/promotion; retry with bounded backoff. */
477
+ // Merge accepts {from,to,replace?,pin_distinct?}; {key,target} remains supported.
478
+ antfly_error_code antfly_db_merge_resolver_keys_json(antfly_db *db, antfly_slice resolver_name, antfly_slice merge_json);
479
+ // Durable, idempotent curation; responses include changed, revision and replay sequence.
480
+ antfly_error_code antfly_db_unmerge_resolver_key_json(antfly_db *db, antfly_slice resolver_name, antfly_slice request_json, antfly_buffer *out);
481
+ // Atomic set edit: {add:{keys?,texts?},remove:{keys?,texts?},expected_revision?}.
482
+ antfly_error_code antfly_db_suppress_resolver_keys_json(antfly_db *db, antfly_slice resolver_name, antfly_slice request_json, antfly_buffer *out);
483
+ antfly_error_code antfly_db_unsuppress_resolver_key_json(antfly_db *db, antfly_slice resolver_name, antfly_slice request_json, antfly_buffer *out);
484
+ // Empty resolver_name lists active and retired identities with curation state.
485
+ antfly_error_code antfly_db_resolver_reviews_json(antfly_db *db, antfly_slice request_json, antfly_buffer *out);
486
+ /** Persistent entity proposal queue. Create is idempotent on action/key/into.
487
+ * List takes {state?,action?,cursor?,limit?}; decisions take {accept,options?,
488
+ * pin_distinct?,actor?,reason?}. Accept commits with per-resolver receipts;
489
+ * complete=false means retry the same decision to resume the fanout. */
490
+ antfly_error_code antfly_db_propose_curation_json(antfly_db *db, antfly_slice entity_table, antfly_slice request_json, antfly_buffer *out);
491
+ antfly_error_code antfly_db_list_curation_proposals_json(antfly_db *db, antfly_slice entity_table, antfly_slice request_json, antfly_buffer *out);
492
+ antfly_error_code antfly_db_get_curation_proposal_json(antfly_db *db, antfly_slice entity_table, antfly_slice proposal_id, antfly_buffer *out);
493
+ antfly_error_code antfly_db_decide_curation_proposal_json(antfly_db *db, antfly_slice entity_table, antfly_slice proposal_id, antfly_slice request_json, antfly_buffer *out);
494
+ antfly_error_code antfly_db_curate_entity_json(antfly_db *db, antfly_slice entity_table, antfly_slice entity_key, antfly_slice request_json, antfly_buffer *out);
495
+ antfly_error_code antfly_db_entity_merge_json(antfly_db *db, antfly_slice entity_table, antfly_slice entity_key, antfly_slice request_json, antfly_buffer *out);
496
+ antfly_error_code antfly_db_entity_unmerge_json(antfly_db *db, antfly_slice entity_table, antfly_slice entity_key, antfly_slice request_json, antfly_buffer *out);
497
+ antfly_error_code antfly_db_entity_suppress_json(antfly_db *db, antfly_slice entity_table, antfly_slice entity_key, antfly_slice request_json, antfly_buffer *out);
498
+ antfly_error_code antfly_db_entity_unsuppress_json(antfly_db *db, antfly_slice entity_table, antfly_slice entity_key, antfly_slice request_json, antfly_buffer *out);
499
+ antfly_error_code antfly_db_entity_redirects_json(antfly_db *db, antfly_slice entity_table, antfly_slice entity_key, antfly_slice request_json, antfly_buffer *out);
500
+ antfly_error_code antfly_db_resolver_curation_json(antfly_db *db, antfly_slice resolver_name, antfly_buffer *out);
501
+
502
+ /* Lists active and retired identities, including durable merges. */
503
+ antfly_error_code antfly_db_list_resolver_identities_json(antfly_db *db, antfly_buffer *out);
504
+ /* Drops a retired identity and its merges; rejects an active identity.
505
+ * Existing resolution artifacts and promoted documents remain. Delete source
506
+ * documents to remove their artifacts; delete canonical rows explicitly only
507
+ * after checking other resolvers/application references.
508
+ * May return ANTFLY_BUSY during replay/promotion; retry with bounded backoff. */
509
+ antfly_error_code antfly_db_drop_resolver_identity(antfly_db *db, antfly_slice resolver_name, bool *out_deleted);
510
+ /** Set {table,key_template} and choose reset_merges:true (clears inline aliases too,
511
+ * unless an explicit replacement aliases array is supplied) or
512
+ * key_map:[{key,target},...] mapping every inline/durable alias endpoint.
513
+ * A durable fence rejects stale inline namespaces/aliases even after reset.
514
+ * Validates atomically; drain to reconcile resolver-owned artifacts and edges.
515
+ * Application-owned documents/references are not renamed.
516
+ * May return ANTFLY_BUSY during replay/promotion; retry with bounded backoff. */
517
+ antfly_error_code antfly_db_set_resolver_namespace_json(antfly_db *db, antfly_slice resolver_name, antfly_slice request_json);
518
+
519
+ /* Schema admission (add, replaces, delete, namespace changes and identity drop)
520
+ * may return ANTFLY_BUSY before mutation when replay/promotion is active for
521
+ * approximately 100 ms. Retry the identical request with bounded backoff.
522
+ * replaces registers a hidden resumable shadow and returns; the old graph
523
+ * serves until background activation. Identical requests are idempotent.
524
+ * This preserves the old generation's indexed contents; it does not turn an
525
+ * earlier write-only batch receipt into an index-visibility guarantee. Use
526
+ * sync_level:"full_index" when a subsequent graph read must see that batch.
527
+ * Acts as add when the old index is absent. Optional wait:{timeout_ms:N}
528
+ * waits for activation; deadline BUSY leaves the accepted shadow running.
529
+ * Waiting releases admission between work quanta and remains bound to the
530
+ * admitted generation. Cancellation or target-name reuse returns ANTFLY_CANCELLED;
531
+ * a different generation under the same name never completes the original wait.
532
+ * Precondition failures are ANTFLY_REPLACEMENT_FAILED,
533
+ * ANTFLY_REPLACEMENT_PENDING or ANTFLY_REPLACEMENT_CONFIGURATION_MISMATCH.
534
+ * pending_work_stats_json reports progress, retry_count, retry_after_ns and
535
+ * last_error. Consecutive transient failures retry four times with persisted
536
+ * backoff; durable forward progress resets the consecutive budget. A separate
537
+ * lifetime ceiling permits at most 64 retries (total_retry_count/max_total_retries
538
+ * in status). Backward-clock deadlines are clamped to at most 3.2 seconds.
539
+ * ANTFLY_CANCELLED also covers interrupted IO/mutex admission; interruption of
540
+ * a call does not cancel accepted work. Inspect state if completion raced it. */
541
+ antfly_error_code antfly_db_add_index_json(antfly_db *db, antfly_slice config_json);
542
+ /* May return ANTFLY_BUSY during replay/promotion; retry with bounded backoff. */
543
+ antfly_error_code antfly_db_delete_index(antfly_db *db, antfly_slice name, bool *out_deleted);
544
+ /** Cancel a running or failed shadow by its new name; idempotent. Leaves the
545
+ * serving index intact and schedules bounded shadow-artifact cleanup. Failed
546
+ * jobs do not retry or pin replay; cancel before registering a fresh attempt.
547
+ * delete_index on either name also cancels dependent replacements. */
548
+ antfly_error_code antfly_db_cancel_replacement(antfly_db *db, antfly_slice name, bool *out_cancelled);
549
+ antfly_error_code antfly_db_list_enrichments_json(antfly_db *db, antfly_buffer *out);
550
+ antfly_error_code antfly_db_add_enrichment_json(antfly_db *db, antfly_slice config_json);
551
+ antfly_error_code antfly_db_delete_enrichment(
552
+ antfly_db *db,
553
+ antfly_slice kind,
554
+ antfly_slice name,
555
+ bool *out_deleted
556
+ );
557
+ antfly_error_code antfly_db_scan_json(antfly_db *db, antfly_slice request_json, antfly_buffer *out);
558
+ antfly_error_code antfly_db_scan_hashes(
559
+ antfly_db *db,
560
+ antfly_slice request_json,
561
+ antfly_scan_hash_result *out_result
562
+ );
563
+ antfly_error_code antfly_db_stats_json(antfly_db *db, antfly_buffer *out);
564
+ antfly_error_code antfly_db_search_json(antfly_db *db, antfly_slice request_json, antfly_buffer *out);
565
+ /* Database SQL; uses statement/parameters/limit and optional session_id.
566
+ * Logical tables are resolved from the durable database catalog.
567
+ * Always free a nonempty out buffer, including SQL diagnostics on error. */
568
+ antfly_error_code antfly_db_sql_json(antfly_db *db, antfly_slice request_json, antfly_buffer *out);
569
+
570
+ /* Logical tables have independent schemas, indexes, and document identities.
571
+ * Dropped table IDs are never reused. The root document table is "default". */
572
+ antfly_error_code antfly_db_create_table_json(antfly_db *db, antfly_slice table_name, antfly_slice schema_json);
573
+ /* A table handle supports the document/schema/index/enrichment APIs. Close it
574
+ * with antfly_db_close. Database close invalidates all its table handles. DROP
575
+ * requires its table handles and SQL cursors to be closed first. */
576
+ antfly_error_code antfly_db_open_table(antfly_db *db, antfly_slice table_name, antfly_db **out_table);
577
+ antfly_error_code antfly_db_drop_table(antfly_db *db, antfly_slice table_name);
578
+ antfly_error_code antfly_db_list_tables_json(antfly_db *db, antfly_buffer *out);
579
+
580
+ /* Describe binds without executing; returns columns and parameter_types. */
581
+ antfly_error_code antfly_db_sql_describe_json(antfly_db *db, antfly_slice request_json, antfly_buffer *out);
582
+
583
+ /* Sessions are connection-local; close abandons staged writes and cursors.
584
+ * BEGIN ISOLATION LEVEL READ COMMITTED is supported, with savepoints.
585
+ * Stronger isolation is rejected. COMMIT uses a durable native decision. */
586
+ antfly_error_code antfly_db_sql_session_open(antfly_db *db, uint64_t *out_session);
587
+ antfly_error_code antfly_db_sql_session_close(antfly_db *db, uint64_t session);
588
+
589
+ /* Cursors belong to db. Requests contain statement and parameters. Fetch
590
+ * returns {"result": <SQL result>, "exhausted": bool}. Fetch sizes are 1..4096.
591
+ * Explicit close releases snapshots; database close releases every cursor.
592
+ * Error buffers contain SQLSTATE diagnostics and must also be freed. */
593
+ antfly_error_code antfly_db_sql_open_cursor_json(antfly_db *db, antfly_slice request_json, uint64_t *out_cursor, antfly_buffer *out_error);
594
+ antfly_error_code antfly_db_sql_fetch_cursor_json(antfly_db *db, uint64_t cursor, uint32_t rows, antfly_buffer *out);
595
+ antfly_error_code antfly_db_sql_close_cursor(antfly_db *db, uint64_t cursor);
596
+ antfly_error_code antfly_db_search_dense(
597
+ antfly_db *db,
598
+ antfly_slice index_name,
599
+ const float *vector_ptr,
600
+ size_t vector_len,
601
+ uint32_t k,
602
+ uint32_t limit,
603
+ uint32_t offset,
604
+ antfly_packed_dense_search_result *out_result
605
+ );
606
+ antfly_error_code antfly_db_search_dense_profile(
607
+ antfly_db *db,
608
+ antfly_slice index_name,
609
+ const float *vector_ptr,
610
+ size_t vector_len,
611
+ uint32_t k,
612
+ uint32_t limit,
613
+ uint32_t offset,
614
+ antfly_dense_search_profile *out_profile
615
+ );
616
+ antfly_error_code antfly_db_search_dense_wire(
617
+ antfly_db *db,
618
+ antfly_slice request_buf,
619
+ antfly_buffer *out
620
+ );
621
+ antfly_error_code antfly_db_search_dense_wire_profile(
622
+ antfly_db *db,
623
+ antfly_slice request_buf,
624
+ antfly_buffer *out,
625
+ antfly_dense_wire_search_profile *out_profile
626
+ );
627
+ antfly_error_code antfly_db_search_text_match(
628
+ antfly_db *db,
629
+ antfly_slice index_name,
630
+ antfly_slice field,
631
+ antfly_slice text,
632
+ uint32_t limit,
633
+ uint32_t offset,
634
+ antfly_dense_search_result *out_result
635
+ );
636
+ antfly_error_code antfly_db_search_text_match_wire(antfly_db *db, antfly_slice request_buf, antfly_buffer *out);
637
+ antfly_error_code antfly_db_search_text_term_wire(antfly_db *db, antfly_slice request_buf, antfly_buffer *out);
638
+ antfly_error_code antfly_db_search_text_match_phrase_wire(antfly_db *db, antfly_slice request_buf, antfly_buffer *out);
639
+ antfly_error_code antfly_db_search_hits_json(
640
+ antfly_db *db,
641
+ antfly_slice request_json,
642
+ antfly_dense_search_result *out_result
643
+ );
644
+ antfly_error_code antfly_db_aggregate_hits_json(antfly_db *db, antfly_slice request_json, antfly_buffer *out);
645
+ antfly_error_code antfly_db_lookup_artifact_json(antfly_db *db, antfly_slice artifact_id_b64, antfly_buffer *out);
646
+ antfly_error_code antfly_decode_artifact_id_json(antfly_slice artifact_id_b64, antfly_buffer *out);
647
+ antfly_error_code antfly_db_extract_enrichments_json(antfly_db *db, antfly_slice request_json, antfly_buffer *out);
648
+ antfly_error_code antfly_db_compute_enrichments_json(antfly_db *db, antfly_slice request_json, antfly_buffer *out);
649
+
650
+ /* `direction` values for antfly_db_get_edges_json and
651
+ * antfly_db_get_neighbors_json. */
652
+ #define ANTFLY_GRAPH_DIRECTION_OUT 0u
653
+ #define ANTFLY_GRAPH_DIRECTION_IN 1u
654
+ #define ANTFLY_GRAPH_DIRECTION_BOTH 2u
655
+ antfly_error_code antfly_db_get_edges_json(
656
+ antfly_db *db,
657
+ antfly_slice index_name,
658
+ antfly_slice key,
659
+ antfly_slice edge_type,
660
+ uint8_t direction,
661
+ antfly_buffer *out
662
+ );
663
+ antfly_error_code antfly_db_traverse_edges_json(antfly_db *db, antfly_slice request_json, antfly_buffer *out);
664
+ antfly_error_code antfly_db_execute_graph_queries_json(antfly_db *db, antfly_slice request_json, antfly_buffer *out);
665
+ antfly_error_code antfly_db_get_neighbors_json(
666
+ antfly_db *db,
667
+ antfly_slice index_name,
668
+ antfly_slice key,
669
+ antfly_slice edge_type,
670
+ uint8_t direction,
671
+ antfly_buffer *out
672
+ );
673
+ antfly_error_code antfly_db_find_shortest_path_json(antfly_db *db, antfly_slice request_json, antfly_buffer *out);
674
+ antfly_error_code antfly_db_find_k_shortest_paths_json(antfly_db *db, antfly_slice request_json, antfly_buffer *out);
675
+ antfly_error_code antfly_db_match_pattern_json(antfly_db *db, antfly_slice request_json, antfly_buffer *out);
676
+
677
+ /*
678
+ * Embedded inference without a database.
679
+ *
680
+ * An antfly_inference handle owns an inference runtime: models load on first
681
+ * use and stay cached until the handle closes. Each call takes the request
682
+ * JSON and returns the response JSON of the matching /ai/v1 route of the
683
+ * Antfly inference HTTP API (see specs/openapi/inference/api.yaml): embed,
684
+ * rerank, chunk, generate, generate/batch, rewrite, decide, extract, read (OCR),
685
+ * transcribe, and models. Binary inputs such as images and audio are passed inline, as base64
686
+ * or data: URIs. The _json calls return complete responses: a generate
687
+ * request with "stream": true fails with ANTFLY_INVALID_ARGUMENT; use
688
+ * antfly_inference_generate_stream_json to stream.
689
+ *
690
+ * Every call resets *out, then fills it with the response body whether or
691
+ * not the call succeeds, so a failure carries the runtime's JSON error
692
+ * ({"error": ..., "message": ...}); release it with antfly_buffer_free
693
+ * either way. An HTTP 4xx maps to ANTFLY_INVALID_ARGUMENT, 404 (such as a
694
+ * model that is not installed) to ANTFLY_NOT_FOUND, 429/503/504 and an
695
+ * elapsed call_timeout_ms to ANTFLY_BUSY, and 501 or 507 (the model does not
696
+ * fit the memory budgets) to ANTFLY_UNSUPPORTED.
697
+ *
698
+ * Models are not downloaded automatically; install them with
699
+ * `antfly inference pull <owner/name>` or antfly_inference_pull_json.
700
+ * antfly_inference_open returns ANTFLY_UNSUPPORTED when this build does not
701
+ * link the inference runtime or the runtime cannot start.
702
+ *
703
+ * Models run in the calling process on every backend, including Metal, CUDA,
704
+ * and ONNX. Those backends cannot interrupt a call once it reaches the device
705
+ * or driver: call_timeout_ms and closing the handle take effect only when the
706
+ * call returns, and a driver fault terminates the process. (The antfly server
707
+ * instead runs them in a worker process it can kill and restart.)
708
+ *
709
+ * Handles have the same safety as antfly_db handles: any thread may call
710
+ * concurrently, close waits for in-flight calls, and a closed or foreign
711
+ * handle is rejected with ANTFLY_INVALID_ARGUMENT.
712
+ */
713
+ typedef struct antfly_inference antfly_inference;
714
+
715
+ typedef struct antfly_inference_options {
716
+ uint32_t abi_size;
717
+ /* No flags are defined yet; must be zero. */
718
+ uint32_t flags;
719
+ /* Models directory. Empty uses $ANTFLY_INFERENCE_MODELS_DIR, else
720
+ * ~/.antfly/inference/models. */
721
+ antfly_slice models_dir;
722
+ /* Resource budgets in MiB, 0 meaning automatic; the same knobs as the
723
+ * inference_*_budget_mb fields of antfly_open_options. */
724
+ uint32_t host_budget_mb;
725
+ uint32_t backend_budget_mb;
726
+ uint32_t process_memory_budget_mb;
727
+ uint32_t combined_budget_mb;
728
+ uint32_t kv_budget_mb;
729
+ uint32_t scratch_budget_mb;
730
+ /* Deadline for each call in milliseconds; 0 means none. */
731
+ uint64_t call_timeout_ms;
732
+ uint64_t reserved[8];
733
+ } antfly_inference_options;
734
+
735
+ uint32_t antfly_inference_options_size(void);
736
+ antfly_error_code antfly_inference_options_init(antfly_inference_options *options);
737
+ /* options may be NULL for defaults. */
738
+ antfly_error_code antfly_inference_open(
739
+ const antfly_inference_options *options,
740
+ antfly_inference **out_inference
741
+ );
742
+ void antfly_inference_close(antfly_inference *inference);
743
+
744
+ antfly_error_code antfly_inference_embed_json(antfly_inference *inference, antfly_slice request_json, antfly_buffer *out);
745
+ antfly_error_code antfly_inference_rerank_json(antfly_inference *inference, antfly_slice request_json, antfly_buffer *out);
746
+ antfly_error_code antfly_inference_chunk_json(antfly_inference *inference, antfly_slice request_json, antfly_buffer *out);
747
+ antfly_error_code antfly_inference_generate_json(antfly_inference *inference, antfly_slice request_json, antfly_buffer *out);
748
+ /* Receives one streamed chunk: the JSON of a "chat.completion.chunk", valid
749
+ * only during the call. Return true to continue, false to stop generating. */
750
+ typedef bool (*antfly_inference_stream_fn)(void *context, antfly_slice chunk_json);
751
+
752
+ /*
753
+ * Streams a generate request (the same body as antfly_inference_generate_json;
754
+ * "stream" is set for you). on_chunk is called on the calling thread for each
755
+ * chunk, as the model produces tokens; generation waits for each call to
756
+ * return. Returns ANTFLY_OK once generation
757
+ * finishes, or ANTFLY_CANCELLED when on_chunk returned false. A request
758
+ * rejected before generation starts (such as a missing model) fails as
759
+ * antfly_inference_generate_json does, with the JSON error in *out; a failure
760
+ * mid-stream returns ANTFLY_INTERNAL with {"error": "STREAM_FAILED", ...}.
761
+ */
762
+ antfly_error_code antfly_inference_generate_stream_json(
763
+ antfly_inference *inference,
764
+ antfly_slice request_json,
765
+ antfly_inference_stream_fn on_chunk,
766
+ void *chunk_context,
767
+ antfly_buffer *out
768
+ );
769
+
770
+ /* Up to 128 non-streaming generate requests in one call; per-item failures
771
+ * are reported in the response. */
772
+ antfly_error_code antfly_inference_generate_batch_json(antfly_inference *inference, antfly_slice request_json, antfly_buffer *out);
773
+ antfly_error_code antfly_inference_rewrite_json(antfly_inference *inference, antfly_slice request_json, antfly_buffer *out);
774
+ /* Named choice, ordinal score, and Boolean questions. Uses DecideRequest and
775
+ * DecideResponse from specs/openapi/inference/api.yaml; no database required. */
776
+ antfly_error_code antfly_inference_decide_json(antfly_inference *inference, antfly_slice request_json, antfly_buffer *out);
777
+ antfly_error_code antfly_inference_extract_json(antfly_inference *inference, antfly_slice request_json, antfly_buffer *out);
778
+ antfly_error_code antfly_inference_read_json(antfly_inference *inference, antfly_slice request_json, antfly_buffer *out);
779
+ antfly_error_code antfly_inference_transcribe_json(antfly_inference *inference, antfly_slice request_json, antfly_buffer *out);
780
+ /* The installed models, as returned by GET /ai/v1/models. */
781
+ antfly_error_code antfly_inference_list_models_json(antfly_inference *inference, antfly_buffer *out);
782
+
783
+ /* One report to an antfly_inference_pull_json progress callback. The slices
784
+ * are valid only during the callback. Check abi_size before reading fields
785
+ * added in later versions. */
786
+ typedef struct antfly_inference_pull_progress {
787
+ uint32_t abi_size;
788
+ uint32_t reserved0;
789
+ /* The model reference this report is for: one per requested variant, or
790
+ * a companion model the requested one needs (such as the speculative
791
+ * decoding assistant of a Gemma 4 QAT checkpoint), whose files are
792
+ * counted separately. */
793
+ antfly_slice model;
794
+ antfly_slice file;
795
+ uint64_t bytes_downloaded;
796
+ /* 0 when unknown. */
797
+ uint64_t total_bytes;
798
+ uint64_t files_done;
799
+ uint64_t files_total;
800
+ /* The file was already present and verified; nothing was downloaded. */
801
+ bool cached;
802
+ } antfly_inference_pull_progress;
803
+
804
+ /* Return true to continue, false to cancel the pull. */
805
+ typedef bool (*antfly_inference_pull_progress_fn)(
806
+ void *context,
807
+ const antfly_inference_pull_progress *progress
808
+ );
809
+
810
+ /*
811
+ * Downloads a model from the Hugging Face Hub into the handle's models
812
+ * directory, like `antfly inference pull`. request_json:
813
+ *
814
+ * {"model": "owner/name[:variant]", required
815
+ * "variants": ["q8_0", ...], pull model:variant for each
816
+ * "token": "...", private or gated models; default $HF_TOKEN
817
+ * "tasks": [...], "capabilities": [...], override the model manifest
818
+ * "projector": "auto" | "none" | "match",
819
+ * "max_artifact_bytes": N, "max_model_bytes": N}
820
+ *
821
+ * progress (may be NULL) is called on the calling thread as each file
822
+ * starts, every 16 MiB, and as it completes; the download waits for each
823
+ * call to return. Returning false cancels: the call returns ANTFLY_CANCELLED
824
+ * and the model is not installed, even if that was the last report.
825
+ * Completed files stay staged, so pulling the same model again resumes
826
+ * rather than restarts.
827
+ *
828
+ * On success *out is {"models": [...], "models_dir": "..."}; on failure it is
829
+ * {"error": ..., "message": ...}. A model missing from the hub returns
830
+ * ANTFLY_NOT_FOUND, a bad request or a model over the size limits
831
+ * ANTFLY_INVALID_ARGUMENT, and a network or hub failure ANTFLY_BUSY.
832
+ * antfly_inference_close waits for a pull in progress.
833
+ */
834
+ antfly_error_code antfly_inference_pull_json(
835
+ antfly_inference *inference,
836
+ antfly_slice request_json,
837
+ antfly_inference_pull_progress_fn progress,
838
+ void *progress_context,
839
+ antfly_buffer *out
840
+ );
841
+
842
+ #ifdef __cplusplus
843
+ }
844
+ #endif
845
+
846
+ #endif