1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
//! Workflow opaque objects: `WorkflowBuilder` and `Workflow`. Each async
//! method exposes both a `_blocking` C entry point and a future-returning
//! variant.
//!
//! ## Ownership conventions
//!
//! - `blazen_workflow_builder_new` returns a caller-owned `*mut BlazenWorkflowBuilder`.
//! Free with [`blazen_workflow_builder_free`] unless it has been consumed
//! by [`blazen_workflow_builder_build`], which transfers ownership of the
//! inner builder into the resulting `Workflow` (the original handle stays
//! alive but its inner builder slot is empty — subsequent method calls on
//! the same handle will fail with `Validation`).
//! - `blazen_workflow_builder_build` writes a caller-owned `*mut BlazenWorkflow`
//! into `out_workflow` on success. Free that with [`blazen_workflow_free`].
//! - The `*_blocking` and future-returning `_run` wrappers both produce
//! caller-owned values. `_blocking` writes a `*mut BlazenWorkflowResult` into
//! `out_result`; the future variant hands the result through
//! [`blazen_future_take_workflow_result`].
//! - String accessors that produce `*mut c_char` (e.g.
//! [`blazen_workflow_step_names_get`]) return caller-owned heap strings;
//! free with [`crate::string::blazen_string_free`].
//! - Errors flow through `*mut *mut BlazenError` out-params on fallible calls;
//! the future-returning variants instead funnel the error through
//! `blazen_future_take_*`.
//!
//! `WorkflowBuilder::step` requires the `StepHandler` callback trampoline and
//! is deferred to Phase R5 (see the doc comment at the bottom of this file).
use c_char;
use Arc;
use BlazenError as InnerError;
use ;
use crateBlazenError;
use crateBlazenFuture;
use crateruntime;
use crate;
use crateBlazenWorkflowResult;
// ---------------------------------------------------------------------------
// Shared error-out helpers
// ---------------------------------------------------------------------------
/// Writes `e` to the out-param if non-null and returns `-1`. Centralises the
/// fallible-call epilogue so the per-method bodies stay focused on the happy
/// path.
///
/// # Safety
///
/// `out_err` must be null OR a valid destination for a single
/// `*mut BlazenError` write (typically a caller's stack-local
/// `*mut BlazenError` initialised to null).
unsafe
/// Writes a synthesised `Internal` error to the out-param and returns `-1`.
/// Used for null-pointer / UTF-8 input failures where there isn't an
/// originating `InnerError`.
///
/// # Safety
///
/// Same contract as [`write_error`]: `out_err` is null OR points at a single
/// writable `*mut BlazenError` slot.
unsafe
// ---------------------------------------------------------------------------
// BlazenWorkflowBuilder
// ---------------------------------------------------------------------------
/// Opaque wrapper around `blazen_uniffi::workflow::WorkflowBuilder`.
///
/// The inner `Arc` matches the `self: Arc<Self>` shape of the underlying
/// builder methods — the methods reach through an internal `Mutex<Option<_>>`
/// to consume + replace the in-progress core builder, so cloning the `Arc`
/// here is sound and lets each C entry point hand a fresh ref into the
/// inner method.
);
/// Construct a new builder with the given UTF-8 `name`. Returns null on a
/// null pointer or non-UTF-8 input.
///
/// # Ownership
///
/// Returned pointer is caller-owned. Free with
/// [`blazen_workflow_builder_free`] unless it has been consumed by
/// [`blazen_workflow_builder_build`].
///
/// # Safety
///
/// `name` must be null OR a valid NUL-terminated UTF-8 buffer that remains
/// live for the duration of the call.
pub unsafe extern "C"
/// Sets the per-step timeout in milliseconds. Returns `0` on success or `-1`
/// on failure (writing the inner error to `out_err`).
///
/// # Safety
///
/// `builder` must be a valid pointer to a `BlazenWorkflowBuilder` previously
/// produced by [`blazen_workflow_builder_new`] (and not yet freed). `out_err`
/// is null OR a valid destination for one `*mut BlazenError` write.
pub unsafe extern "C"
/// Sets the workflow-wide timeout in milliseconds. Returns `0` on success or
/// `-1` on failure (writing the inner error to `out_err`).
///
/// # Safety
///
/// Same as [`blazen_workflow_builder_step_timeout_ms`].
pub unsafe extern "C"
/// Consumes the in-progress builder and produces a runnable `Workflow`,
/// writing the caller-owned `*mut BlazenWorkflow` into `out_workflow` on
/// success. Returns `0` on success or `-1` on failure.
///
/// On the success path the `BlazenWorkflowBuilder` handle remains live but
/// its internal builder slot is now empty; subsequent calls on the same
/// handle will fail with a `Validation` error. The handle itself must still
/// be released with [`blazen_workflow_builder_free`].
///
/// # Safety
///
/// `builder` must be a valid pointer to a `BlazenWorkflowBuilder` previously
/// produced by [`blazen_workflow_builder_new`] (and not yet freed).
/// `out_workflow` is null OR a valid destination for one `*mut BlazenWorkflow`
/// write. `out_err` is null OR a valid destination for one `*mut BlazenError`
/// write.
pub unsafe extern "C"
/// Frees a `BlazenWorkflowBuilder` handle previously produced by the cabi
/// surface. No-op on a null pointer.
///
/// # Safety
///
/// `builder` must be null OR a pointer previously produced by
/// [`blazen_workflow_builder_new`]. Calling this twice on the same non-null
/// pointer is a double-free.
pub unsafe extern "C"
// ---------------------------------------------------------------------------
// BlazenWorkflow
// ---------------------------------------------------------------------------
/// Opaque wrapper around `blazen_uniffi::workflow::Workflow`. The inner `Arc`
/// supports `self: Arc<Self>` async methods on the inner type.
);
/// Synchronously runs the workflow with the given JSON `input_json` payload.
/// Blocks the calling thread on the cabi tokio runtime. Returns `0` on
/// success (writing a caller-owned `*mut BlazenWorkflowResult` to
/// `out_result`) or `-1` on failure (writing the inner error to `out_err`).
///
/// # Safety
///
/// `wf` must be a valid pointer to a `BlazenWorkflow`. `input_json` must be a
/// valid NUL-terminated UTF-8 buffer. `out_result` is null OR a valid
/// destination for one `*mut BlazenWorkflowResult` write. `out_err` is null
/// OR a valid destination for one `*mut BlazenError` write.
pub unsafe extern "C"
/// Runs the workflow asynchronously, returning an opaque future handle
/// immediately. The caller waits via `blazen_future_wait` / `blazen_future_fd`
/// / `blazen_future_poll`, then takes the result via
/// [`blazen_future_take_workflow_result`].
///
/// Returns null if `wf` or `input_json` is null, or if `input_json` is not
/// valid UTF-8. Errors that surface during the async run are delivered
/// through `blazen_future_take_workflow_result`'s `err` out-param.
///
/// # Safety
///
/// `wf` must be a valid pointer to a `BlazenWorkflow`. `input_json` must be a
/// valid NUL-terminated UTF-8 buffer that remains valid for the duration of
/// this call (the buffer is copied before this function returns).
pub unsafe extern "C"
/// Returns the number of registered steps in this workflow. Returns `0` if
/// `wf` is null.
///
/// Used together with [`blazen_workflow_step_names_get`] to iterate step
/// names without round-tripping a heap-allocated array across the FFI.
///
/// # Safety
///
/// `wf` must be null OR a valid pointer to a `BlazenWorkflow` previously
/// produced by the cabi surface.
pub unsafe extern "C"
/// Returns the step name at position `idx` as a heap-allocated NUL-terminated
/// UTF-8 C string. Returns null if `wf` is null or `idx` is out of bounds.
///
/// # Ownership
///
/// Caller frees with [`crate::string::blazen_string_free`].
///
/// # Safety
///
/// `wf` must be null OR a valid pointer to a `BlazenWorkflow` previously
/// produced by the cabi surface.
pub unsafe extern "C"
/// Frees a `BlazenWorkflow` handle previously produced by the cabi surface.
/// No-op on a null pointer.
///
/// # Safety
///
/// `wf` must be null OR a pointer previously produced by
/// [`blazen_workflow_builder_build`] (or any other cabi function documenting
/// `BlazenWorkflow` ownership-transfer-to-caller semantics). Calling this
/// twice on the same non-null pointer is a double-free.
pub unsafe extern "C"
// ---------------------------------------------------------------------------
// Typed future-take for WorkflowResult
// ---------------------------------------------------------------------------
/// Pops the `WorkflowResult` out of a future produced by any of the
/// workflow-result-returning cabi async wrappers (`blazen_workflow_run`,
/// `blazen_pipeline_run`, and — once R5 lands — `blazen_peer_client_run_remote_workflow`).
/// Returns `0` on success or `-1` on error.
///
/// On success, `out` receives a caller-owned `*mut BlazenWorkflowResult` (free
/// with [`crate::workflow_records::blazen_workflow_result_free`]). On error,
/// `err` receives a caller-owned `*mut BlazenError` (free with
/// [`crate::error::blazen_error_free`]).
///
/// # Safety
///
/// All three pointers must follow the cabi-future contract: `fut` is a live
/// future produced by `blazen_workflow_run` / `blazen_pipeline_run` /
/// `blazen_peer_client_run_remote_workflow`, observed completed via
/// `blazen_future_poll` / `_wait` / `_fd`. `out` and `err` are valid
/// destinations for a single `*mut` write (typically stack `*mut BlazenX`
/// locals — can be null to discard).
pub unsafe extern "C"
// ---------------------------------------------------------------------------
// Deferred surface
// ---------------------------------------------------------------------------
// `blazen_workflow_builder_step` is intentionally **not** exposed here.
// Registering a step requires a foreign-language `StepHandler` trampoline —
// a callback that the Rust workflow engine can invoke from arbitrary tokio
// worker threads, with the foreign-language method coupled to a
// `BlazenStepOutput` return value. That trampoline lands in Phase R5
// alongside the `blazen_agent_*` tool-handler bridge; until then, the cabi
// surface is consumer-only (build a Workflow with no steps, run it, observe
// the result).