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
//! `ReasoningInferenceHandle` — narrow trait surface for the engine
//! capabilities a `ReasoningSession` reaches beyond what
//! `InferenceHandle` already covers.
//!
//! Motivation: pre-#189, `ReasoningSession` held `Arc<InferenceEngine>`
//! directly and called three engine internals that `InferenceHandle`
//! (added in #188) intentionally omits:
//!
//! - `engine.generate_tracked(req)` — the rich variant of `generate`
//! that returns `InferenceResult` (trace_id, model_used, latency_ms)
//! instead of bare text. The session records each action's trace
//! in its `ActionOutcome` for the post-hoc learning loop.
//! - `engine.unified_registry.find_by_name(name)` — used by
//! `pick_model_for_tier` to verify a tier-candidate model is
//! actually registered before naming it in a generation request.
//! - `engine.outcome_tracker().write().await` →
//! `resolve_pending_from_signals` — the post-action learning step
//! that writes back inferred outcomes for each action's trace.
//!
//! That direct coupling meant `cmd_reason` had to construct a full
//! in-process `InferenceEngine` even when the daemon was reachable —
//! the v0.7 holdover #186 was trying to eliminate.
//!
//! This trait is `InferenceHandle + Send + Sync` with three extra
//! methods, scoped to what car-reason actually uses. Two
//! implementations:
//!
//! 1. **In-process** — `impl ReasoningInferenceHandle for InferenceEngine`
//! in this crate. Delegates to existing engine methods. Behavior
//! matches the pre-refactor path exactly so existing tests against
//! the in-process engine continue to pass.
//! 2. **Daemon-routed** — `impl ReasoningInferenceHandle for
//! DaemonInferenceHandle` lives in `car-cli/src/daemon_handle.rs`
//! next to the existing `InferenceHandle` impl from #188.
//! `generate_tracked` reuses the daemon's `infer` JSON-RPC method
//! (which already returns the full `InferenceResult` shape).
//! `find_model_by_name` lazily caches a `models.list_unified`
//! snapshot. `record_inferred_outcomes` is best-effort — the
//! daemon doesn't yet have an `outcomes.resolve_pending` endpoint,
//! so the daemon path no-ops (with an opt-in `eprintln!` gated by
//! the `CAR_REASON_DEBUG` env var) and returns successfully.
//!
//! Tracked in Parslee-ai/car#189.
use Arc;
use ;
/// Inference operations a `ReasoningSession` needs beyond the
/// `InferenceHandle` core (generate + embed).
///
/// Implementors are `Send + Sync` because the session holds the
/// handle in an `Arc` and may dispatch from `tokio::spawn` tasks.
/// Convenience alias for the common shape `ReasoningSession::new`
/// expects. Callers usually have an `Arc<InferenceEngine>` or
/// `Arc<DaemonInferenceHandle>`; both coerce to this.
pub type SharedReasoningHandle = ;