Entropic 2.3.8
Local-first agentic inference engine
Loading...
Searching...
No Matches
hook_registry.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
10
11#include <algorithm>
12#include <cstdlib>
13#include <exception>
14
15static auto logger = entropic::log::get("core.hook_registry");
16
17namespace entropic {
18
26bool HookRegistry::is_valid_point(entropic_hook_point_t point) {
27 return point >= 0
28 && point < ENTROPIC_HOOK_COUNT_;
29}
30
44 void* user_data,
45 int priority) {
46 if (!is_valid_point(point)) {
48 }
49
50 auto idx = static_cast<size_t>(point);
51 std::unique_lock lock(mutexes_[idx]);
52
53 HookEntry entry{callback, user_data, priority};
54 auto& vec = entries_[idx];
55
56 // Insert sorted by priority (ascending)
57 auto pos = std::lower_bound(
58 vec.begin(), vec.end(), entry,
59 [](const HookEntry& a, const HookEntry& b) {
60 return a.priority < b.priority;
61 });
62 vec.insert(pos, entry);
63
64 logger->info("Registered hook: point={} priority={} total={}",
65 static_cast<int>(point), priority, vec.size());
66 return ENTROPIC_OK;
67}
68
81 void* user_data) {
82 if (!is_valid_point(point)) {
84 }
85
86 auto idx = static_cast<size_t>(point);
87 std::unique_lock lock(mutexes_[idx]);
88
89 auto& vec = entries_[idx];
90 auto it = std::find_if(vec.begin(), vec.end(),
91 [callback, user_data](const HookEntry& e) {
92 return e.callback == callback
93 && e.user_data == user_data;
94 });
95
96 if (it != vec.end()) {
97 vec.erase(it);
98 logger->info("Deregistered hook: point={}", static_cast<int>(point));
99 }
100 return ENTROPIC_OK;
101}
102
110std::vector<HookEntry> HookRegistry::snapshot(
111 entropic_hook_point_t point) const {
112 auto idx = static_cast<size_t>(point);
113 std::shared_lock lock(mutexes_[idx]);
114 return entries_[idx];
115}
116
128 const char* context_json,
129 char** out_json) {
130 *out_json = nullptr;
131
132 if (!is_valid_point(point)) {
133 return 0;
134 }
135
136 auto entries = snapshot(point);
137 logger->info("fire_pre: point={}, {} handler(s)",
138 static_cast<int>(point), entries.size());
139 char* accumulated = nullptr;
140 int result = 0;
141
142 for (const auto& entry : entries) {
143 const char* input = accumulated ? accumulated : context_json;
144 char* modified = nullptr;
145 int rc = 0;
146
147 try {
148 rc = entry.callback(point, input, &modified, entry.user_data);
149 } catch (const std::exception& e) {
150 logger->warn("Pre-hook threw for point={}: {}",
151 static_cast<int>(point), e.what());
152 continue;
153 } catch (...) {
154 logger->warn("Pre-hook threw unknown exception for point={}",
155 static_cast<int>(point));
156 continue;
157 }
158
159 if (rc != 0) {
160 free(accumulated);
161 free(modified);
162 accumulated = nullptr;
163 result = rc;
164 break;
165 }
166
167 if (modified != nullptr) {
168 free(accumulated);
169 accumulated = modified;
170 }
171 }
172
173 *out_json = accumulated;
174 return result;
175}
176
187 const char* context_json,
188 char** out_json) {
189 *out_json = nullptr;
190
191 if (!is_valid_point(point)) {
192 return;
193 }
194
195 auto entries = snapshot(point);
196 if (entries.empty()) {
197 return;
198 }
199
200 char* accumulated = nullptr;
201
202 for (const auto& entry : entries) {
203 const char* input = accumulated ? accumulated : context_json;
204 char* modified = nullptr;
205
206 try {
207 entry.callback(point, input, &modified, entry.user_data);
208 } catch (const std::exception& e) {
209 logger->warn("Post-hook threw for point={}: {}",
210 static_cast<int>(point), e.what());
211 continue;
212 } catch (...) {
213 logger->warn("Post-hook threw unknown exception for point={}",
214 static_cast<int>(point));
215 continue;
216 }
217
218 if (modified != nullptr) {
219 free(accumulated);
220 accumulated = modified;
221 }
222 }
223
224 *out_json = accumulated;
225}
226
236 const char* context_json) {
237 if (!is_valid_point(point)) {
238 return;
239 }
240
241 auto entries = snapshot(point);
242
243 for (const auto& entry : entries) {
244 char* modified = nullptr;
245 try {
246 entry.callback(point, context_json, &modified, entry.user_data);
247 } catch (const std::exception& e) {
248 logger->warn("Info hook threw for point={}: {}",
249 static_cast<int>(point), e.what());
250 } catch (...) {
251 logger->warn("Info hook threw unknown exception for point={}",
252 static_cast<int>(point));
253 }
254 // Ignore return value and modified_json for info hooks
255 free(modified);
256 }
257}
258
267 if (!is_valid_point(point)) {
268 return 0;
269 }
270 auto idx = static_cast<size_t>(point);
271 std::shared_lock lock(mutexes_[idx]);
272 return entries_[idx].size();
273}
274
275} // namespace entropic
entropic_error_t register_hook(entropic_hook_point_t point, entropic_hook_callback_t callback, void *user_data, int priority)
Register a hook callback at a hook point.
size_t hook_count(entropic_hook_point_t point) const
Get the number of registered hooks for a point.
int fire_pre(entropic_hook_point_t point, const char *context_json, char **out_json)
Fire pre-hooks.
void fire_post(entropic_hook_point_t point, const char *context_json, char **out_json)
Fire post-hooks.
entropic_error_t deregister_hook(entropic_hook_point_t point, entropic_hook_callback_t callback, void *user_data)
Deregister a hook callback.
void fire_info(entropic_hook_point_t point, const char *context_json)
Fire informational hooks (no modify, no cancel).
entropic_error_t
Error codes returned by all C API functions.
Definition error.h:35
@ ENTROPIC_OK
Success.
Definition error.h:36
@ ENTROPIC_ERROR_INVALID_CONFIG
Config validation failed (missing fields, bad values)
Definition error.h:38
Thread-safe hook registration and dispatch.
int(* entropic_hook_callback_t)(entropic_hook_point_t hook_point, const char *context_json, char **modified_json, void *user_data)
Hook callback function type.
Definition hooks.h:134
entropic_hook_point_t
Hook points in the engine lifecycle.
Definition hooks.h:34
@ ENTROPIC_HOOK_COUNT_
Sentinel — not a valid hook point.
Definition hooks.h:89
spdlog initialization and logger access.
ENTROPIC_EXPORT std::shared_ptr< spdlog::logger > get(const std::string &name)
Get or create a named logger.
Definition logging.cpp:211
Activate model on GPU (WARM → ACTIVE).
A single registered hook entry.