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
//! Recall (vector + BM25 hybrid search) HTTP handlers.
//!
//! Why: Recall is the primary read path — agents and the admin UI both query
//! this endpoint for semantic memory retrieval. Both per-palace and
//! cross-palace fan-out variants are served here.
//! What: `GET /api/v1/palaces/{id}/recall` and `GET /api/v1/recall` handlers,
//! `RecallQuery` params struct, and the `recall_entry_json` re-export.
//! Test: `recall_all_handler_*` tests in `web::tests`.
use ;
use Deserialize;
use Value;
use crateAppState;
use ApiError;
/// Query parameters shared by the per-palace and cross-palace recall endpoints.
///
/// Why: both `GET /api/v1/palaces/{id}/recall` and `GET /api/v1/recall` accept
/// the same `q` / `top_k` / `deep` triple. Keeping one struct avoids drift
/// between the two handler signatures.
/// What: `q` is required; `top_k` and `deep` are optional with handler-side
/// defaults (10 and false respectively).
/// Test: `recall_all_handler_*` tests in this module.
pub
/// `GET /api/v1/palaces/{id}/recall` — recall from a single palace.
///
/// Why: Palace-scoped recall lets the admin UI and per-project agents query
/// just one project's memory without merging across palaces.
/// What: Delegates to `MemoryService::recall` with the given `id`.
/// Test: Covered by integration; `recall_all_handler_honors_palace_filter`
/// exercises the scoped path via the flat endpoint with `?palace=`.
pub async
pub use craterecall_entry_json;
/// Extracts a human-readable error message from a partial-failure envelope.
///
/// Why: `recall_all` may return an object with a non-empty `"errors"` array
/// when one or more palaces fail during fan-out while others succeed. Without
/// this guard, that envelope passes through as 200 OK and callers receive
/// silent data loss. Extracting the detection into a pure function lets unit
/// tests verify every branch directly, without spinning up the HTTP stack.
/// What: Inspects `value` for a non-empty `"errors"` array. If found, formats
/// a message from the first entry — plain string, `{"message":"..."}` object,
/// or a generic fallback — and returns `Some(message)`. Returns `None` when
/// the array is absent or empty (i.e. no partial failure detected).
/// Test: `extract_partial_error_*` unit tests in `web::tests::recall_tests`.
pub
/// `GET /api/v1/recall?q=<query>&top_k=<n>&deep=<bool>[&palace=<id>]` — recall
/// with optional palace scoping.
///
/// Why: Agents and dashboard widgets often need the most relevant memories
/// regardless of palace boundary; forcing the caller to issue one request per
/// palace and merge client-side is both slower (no fan-out) and wrong (no
/// dedup/rerank). Serving the merged top-k from the daemon collapses the
/// round-trip and reuses the shared embedder singleton.
/// Issue #465: the `palace=` query param was silently ignored — this endpoint
/// always queried the default palace regardless of the supplied filter, causing
/// callers to receive results from the wrong palace. Fix: when `palace=` is
/// present and non-empty, route the recall to that specific palace (matching
/// the behaviour of `GET /api/v1/palaces/{id}/recall`). When absent, fall back
/// to the cross-palace fan-out.
/// Issue #1102: hardened error detection on the cross-palace fan-out path.
/// `recall_all` now returns either a JSON array (success) or an object
/// carrying an `"error"` string (full failure). Both are detected; a
/// non-empty `"errors"` array in any future partial-success envelope is also
/// surfaced as an internal error rather than silently passed through as 200 OK
/// (see `extract_partial_error` for the branch logic, which is unit-tested
/// independently).
/// What: If `palace` query param is set, delegates to `MemoryService::recall`
/// for that palace. Otherwise delegates to `MemoryService::recall_all`.
/// Returns a JSON array of `{ palace_id, drawer_id, content, score, layer }`
/// entries sorted by score descending, or a 500 on failure.
/// Test: `recall_all_handler_honors_palace_filter`,
/// `recall_all_handler_fans_out_without_palace_param`,
/// `recall_all_handler_surfaces_error_envelope`,
/// `extract_partial_error_*` (unit tests for the branch logic).
pub async