Entropic 2.11.1
Local-first agentic inference engine
Loading...
Searching...
No Matches
c_interface.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
14
16
17#include <cstring>
18#include <new>
19#include <optional>
20#include <string>
21
23
24namespace {
25auto logger = entropic::log::get("storage.c_api");
26} // anonymous namespace
27
28// ── Handle mapping ────────────────────────────────────────
29
33
40 explicit entropic_storage_backend(const char* path)
41 : impl(path) {}
42};
43
44// ── Helpers ───────────────────────────────────────────────
45
53static char* dup_string(const std::string& s) {
54 auto* p = static_cast<char*>(std::malloc(s.size() + 1));
55 if (p) std::memcpy(p, s.c_str(), s.size() + 1);
56 return p;
57}
58
66static std::optional<std::string> opt_str(const char* s) {
67 return s ? std::optional<std::string>(s) : std::nullopt;
68}
69
70// ── Lifecycle ─────────────────────────────────────────────
71
82entropic_storage_create(const char* db_path) {
83 if (!db_path) return nullptr;
84 try {
85 return new entropic_storage_backend(db_path);
86 } catch (const std::exception& e) {
87 logger->error("storage_create failed: {}", e.what());
88 return nullptr;
89 }
90}
91
103 if (!storage) return ENTROPIC_ERROR_INVALID_ARGUMENT;
104 try {
105 return storage->impl.initialize()
107 } catch (const std::exception& e) {
108 logger->error("storage_initialize failed: {}", e.what());
109 return ENTROPIC_ERROR_IO;
110 }
111}
112
120 delete storage;
121}
122
123// ── Conversation CRUD ─────────────────────────────────────
124
139 const char* title,
140 const char* project_path,
141 const char* model_id) {
142 if (!storage || !title) return nullptr;
143 try {
144 auto id = storage->impl.create_conversation(
145 title, opt_str(project_path), opt_str(model_id));
146 return dup_string(id);
147 } catch (const std::exception& e) {
148 logger->error("create_conversation failed: {}", e.what());
149 return nullptr;
150 }
151}
152
166 const char* conversation_id,
167 const char* messages_json) {
168 if (!storage || !conversation_id || !messages_json) {
170 }
171 try {
172 return storage->impl.save_messages(conversation_id, messages_json)
174 } catch (const std::exception& e) {
175 logger->error("save_conversation failed: {}", e.what());
176 return ENTROPIC_ERROR_IO;
177 }
178}
179
193 const char* conversation_id,
194 char** result_json) {
195 if (!storage || !conversation_id || !result_json) {
197 }
198 try {
199 std::string json;
200 bool found = storage->impl.load_conversation(
201 conversation_id, json);
202 *result_json = found ? dup_string(json) : nullptr;
204 } catch (const std::exception& e) {
205 logger->error("load_conversation failed: {}", e.what());
206 return ENTROPIC_ERROR_IO;
207 }
208}
209
224 int limit, int offset,
225 char** result_json) {
226 if (!storage || !result_json) {
228 }
229 try {
230 std::string json;
231 storage->impl.list_conversations(limit, offset, json);
232 *result_json = dup_string(json);
233 return ENTROPIC_OK;
234 } catch (const std::exception& e) {
235 logger->error("list_conversations failed: {}", e.what());
236 return ENTROPIC_ERROR_IO;
237 }
238}
239
254 const char* query, int limit,
255 char** result_json) {
256 if (!storage || !query || !result_json) {
258 }
259 try {
260 std::string json;
261 storage->impl.search_conversations(query, limit, json);
262 *result_json = dup_string(json);
263 return ENTROPIC_OK;
264 } catch (const std::exception& e) {
265 logger->error("search_conversations failed: {}", e.what());
266 return ENTROPIC_ERROR_IO;
267 }
268}
269
283 const char* conversation_id) {
284 if (!storage || !conversation_id) {
286 }
287 try {
288 return storage->impl.delete_conversation(conversation_id)
290 } catch (const std::exception& e) {
291 logger->error("delete_conversation failed: {}", e.what());
292 return ENTROPIC_ERROR_IO;
293 }
294}
295
296// ── Delegation storage ────────────────────────────────────
297
315 const char* parent_conversation_id,
316 const char* delegating_tier,
317 const char* target_tier,
318 const char* task,
319 int max_turns,
320 char** result_json) {
321 if (!storage || !parent_conversation_id || !delegating_tier ||
322 !target_tier || !task || !result_json) {
324 }
325 try {
326 std::string del_id, child_id;
327 bool ok = storage->impl.create_delegation(
328 parent_conversation_id, delegating_tier,
329 target_tier, task, max_turns, del_id, child_id);
330 if (ok) {
331 auto json = "{\"delegation_id\":\"" + del_id +
332 "\",\"child_conversation_id\":\"" + child_id + "\"}";
333 *result_json = dup_string(json);
334 }
335 return ok ? ENTROPIC_OK : ENTROPIC_ERROR_IO;
336 } catch (const std::exception& e) {
337 logger->error("create_delegation failed: {}", e.what());
338 return ENTROPIC_ERROR_IO;
339 }
340}
341
356 const char* delegation_id,
357 const char* status,
358 const char* result_summary) {
359 if (!storage || !delegation_id || !status) {
361 }
362 try {
363 return storage->impl.complete_delegation(
364 delegation_id, status, opt_str(result_summary))
366 } catch (const std::exception& e) {
367 logger->error("complete_delegation failed: {}", e.what());
368 return ENTROPIC_ERROR_IO;
369 }
370}
371
385 const char* conversation_id,
386 char** result_json) {
387 if (!storage || !conversation_id || !result_json) {
389 }
390 try {
391 std::string json;
392 storage->impl.get_delegations(conversation_id, json);
393 *result_json = dup_string(json);
394 return ENTROPIC_OK;
395 } catch (const std::exception& e) {
396 logger->error("get_delegations failed: {}", e.what());
397 return ENTROPIC_ERROR_IO;
398 }
399}
400
401// ── Compaction snapshots ──────────────────────────────────
402
416 const char* conversation_id,
417 const char* messages_json) {
418 if (!storage || !conversation_id || !messages_json) {
420 }
421 try {
422 return storage->impl.save_snapshot(conversation_id, messages_json)
424 } catch (const std::exception& e) {
425 logger->error("save_snapshot failed: {}", e.what());
426 return ENTROPIC_ERROR_IO;
427 }
428}
429
430// ── Statistics ────────────────────────────────────────────
431
444 char** result_json) {
445 if (!storage || !result_json) {
447 }
448 try {
449 std::string json;
450 storage->impl.get_stats(json);
451 *result_json = dup_string(json);
452 return ENTROPIC_OK;
453 } catch (const std::exception& e) {
454 logger->error("get_stats failed: {}", e.what());
455 return ENTROPIC_ERROR_IO;
456 }
457}
entropic_error_t entropic_storage_get_stats(entropic_storage_backend_t storage, char **result_json)
Get statistics.
entropic_error_t entropic_storage_list_conversations(entropic_storage_backend_t storage, int limit, int offset, char **result_json)
List conversations.
entropic_error_t entropic_storage_load_conversation(entropic_storage_backend_t storage, const char *conversation_id, char **result_json)
Load a conversation.
entropic_error_t entropic_storage_create_delegation(entropic_storage_backend_t storage, const char *parent_conversation_id, const char *delegating_tier, const char *target_tier, const char *task, int max_turns, char **result_json)
Create a delegation.
entropic_error_t entropic_storage_save_snapshot(entropic_storage_backend_t storage, const char *conversation_id, const char *messages_json)
Save a compaction snapshot.
entropic_storage_backend_t entropic_storage_create(const char *db_path)
Create a storage backend.
void entropic_storage_destroy(entropic_storage_backend_t storage)
Destroy storage.
entropic_error_t entropic_storage_search_conversations(entropic_storage_backend_t storage, const char *query, int limit, char **result_json)
Search conversations.
static std::optional< std::string > opt_str(const char *s)
Convert optional C string to std::optional<std::string>.
entropic_error_t entropic_storage_initialize(entropic_storage_backend_t storage)
Initialize storage.
static char * dup_string(const std::string &s)
Duplicate a std::string to a malloc'd C string.
char * entropic_storage_create_conversation(entropic_storage_backend_t storage, const char *title, const char *project_path, const char *model_id)
Create a conversation.
entropic_error_t entropic_storage_complete_delegation(entropic_storage_backend_t storage, const char *delegation_id, const char *status, const char *result_summary)
Complete a delegation.
entropic_error_t entropic_storage_delete_conversation(entropic_storage_backend_t storage, const char *conversation_id)
Delete a conversation.
entropic_error_t entropic_storage_get_delegations(entropic_storage_backend_t storage, const char *conversation_id, char **result_json)
Get delegations for a conversation.
entropic_error_t entropic_storage_save_conversation(entropic_storage_backend_t storage, const char *conversation_id, const char *messages_json)
Save messages to a conversation.
SQLite-based storage backend.
Definition backend.h:43
bool save_messages(const std::string &conversation_id, const std::string &messages_json)
Save messages to a conversation.
Definition backend.cpp:324
bool complete_delegation(const std::string &delegation_id, const std::string &status, const std::optional< std::string > &result_summary=std::nullopt)
Mark a delegation as completed or failed.
Definition backend.cpp:711
bool create_delegation(const std::string &parent_conversation_id, const std::string &delegating_tier, const std::string &target_tier, const std::string &task, int max_turns, std::string &delegation_id, std::string &child_conversation_id)
Create a delegation record with a child conversation.
Definition backend.cpp:649
bool search_conversations(const std::string &query, int limit, std::string &result_json)
Full-text search across conversations.
Definition backend.cpp:535
bool get_delegations(const std::string &conversation_id, std::string &result_json)
Get delegations for a parent conversation.
Definition backend.cpp:789
bool save_snapshot(const std::string &conversation_id, const std::string &messages_json)
Save a pre-compaction snapshot of full conversation history.
Definition backend.cpp:884
std::string create_conversation(const std::string &title="New Conversation", const std::optional< std::string > &project_path=std::nullopt, const std::optional< std::string > &model_id=std::nullopt)
Create a new conversation.
Definition backend.cpp:222
bool load_conversation(const std::string &conversation_id, std::string &result_json)
Load a conversation with messages.
Definition backend.cpp:417
bool get_stats(std::string &result_json)
Get storage statistics.
Definition backend.cpp:917
bool delete_conversation(const std::string &conversation_id)
Delete a conversation and all associated records.
Definition backend.cpp:494
bool list_conversations(int limit, int offset, std::string &result_json)
List conversations with pagination.
Definition backend.cpp:457
bool initialize()
Initialize storage (open database, run migrations).
Definition backend.cpp:198
entropic_error_t
Error codes returned by all C API functions.
Definition error.h:37
@ ENTROPIC_OK
Success.
Definition error.h:38
@ ENTROPIC_ERROR_INVALID_ARGUMENT
NULL pointer, empty string, out-of-range value.
Definition error.h:39
@ ENTROPIC_ERROR_IO
File/network I/O error.
Definition error.h:52
Pure C interface contract for storage backends.
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
SqliteStorageBackend — conversation persistence via SQLite.
@dg_internal The opaque handle points directly to a SqliteStorageBackend.
entropic_storage_backend(const char *path)
Construct with database path.