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
//! Shared logic for FFI bindings (NAPI, PyO3).
//!
//! Pure Rust functions that accept JSON strings and return `Result<String, String>`.
//! Each FFI crate wraps these with its own error type (napi::Error, PyErr).
/// Wire protocol version this binding speaks to the daemon (the
/// `server.handshake` negotiation value). Re-exported from `car-proto` so
/// the NAPI/PyO3 bindings can surface it to JS/Python consumers without a
/// direct `car-proto` dependency — and so there is exactly one source of
/// truth for the constant across the proxy, the daemon, and the bindings.
pub use PROTOCOL_VERSION;
// Re-export so `car-cli` can reap OS-level schedules (e.g. in `car purge`)
// without a redundant direct `car-scheduler` dependency — car-cli already
// depends on car-ffi-common, which already depends on car-scheduler.
pub use os_schedule;
/// Parse a JSON argument into `T`, labeling a parse failure with the argument
/// name (e.g. `from_json("graph", graph_json)` → `"invalid graph JSON: …"`).
/// The shared front half of the stateless JSON-wrapper pattern that pervades
/// this crate — see the module docs.
/// Serialize a value to a JSON string, mapping the (near-impossible) failure to
/// its message. The shared back half of the stateless JSON-wrapper pattern.
/// Parse an *optional* JSON argument: `None` stays `None`, `Some(s)` is parsed
/// via [`from_json`] (so a malformed value is a labeled error, not a silent
/// `None`). The optional-argument companion to [`from_json`].
/// Initialize a `tracing_subscriber` honoring `RUST_LOG`. Idempotent
/// — subsequent calls return immediately. Used by FFI bindings to
/// surface `[voice] dropped …` and other crate-side warn/error lines
/// when callers set `RUST_LOG=car_voice=debug` (or similar).
///
/// Without this call, `tracing::warn!`/`error!` lines emitted from
/// car-voice / car-inference / etc. go nowhere in the FFI binary —
/// `#120`'s diagnostic dead-end. We can't `init` from a binding's
/// `[lib]` ctor (no static init in cdylib that's safe for tracing),
/// so each entry-point function calls this and the OnceLock guard
/// makes it cheap.
///
/// Falls back silently if another global subscriber is already set
/// (e.g., when the embedder loads `car-server` and the FFI module
/// in the same process).
// `auth_token` and `proxy` moved to the `car-daemon-client` crate so
// the UniFFI (Swift/Kotlin) binding can reach the daemon without
// absorbing this crate's transitive tree — car-voice (whisper-rs,
// coreaudio-sys), car-browser, car-vision are wrong for
// aarch64-apple-ios and unnecessary for a pure WS client. Re-exported
// here so every existing `car_ffi_common::proxy::…` /
// `car_ffi_common::auth_token::…` import path keeps working.
pub use ;
// (moved in v0.8.x phase 7.3) `a2a`, `a2a_dispatch`, `meeting`,
// and `voice_turn` modules used to live here. They were daemon-only
// (FFI bindings now proxy through `proxy::*` over WebSocket), and
// their car-engine / car-inference / car-a2a / car-meeting deps
// were the last reason this crate pulled those heavy graphs. The
// moved modules now live in `car-server-core/src/` next to the
// JSON-RPC handler that calls them. `a2a_dispatch` was deleted
// outright (no callers — the daemon's WS routes use their own
// `ServerState`-held dispatcher).
// (removed in v0.8) tracked_result_to_json — was a typed
// InferenceResult → JSON helper for FFI bindings. After phase 7.2,
// FFI binding methods build requests as raw json! and pass through
// the daemon's full InferenceResult JSON unmodified. The helper
// pulled car-inference (and transitively MLX) for what amounts to a
// thin field re-projection, so it's gone.
/// Process-wide serialization lock for tests that mutate environment
/// variables. The process environment is global, so any test that
/// `set_var`/`remove_var`s — or that *reads* an env-derived path while
/// another test mutates it — must hold this. Previously each module
/// (`auth_token`, `memory_path`, `proxy`) had its OWN lock, so e.g. an
/// `auth_token` test reading `HOME` raced a `memory_path` test writing
/// `HOME`; a panic under one lock also poisoned it and cascaded the
/// failure across that module's sibling tests. A single shared lock
/// removes the cross-module race, and recovering the guard on poison
/// (`into_inner`) stops one failure from cascading into many.
pub