28#include "../inference/tool_call_serialize.h"
30#include <nlohmann/json.hpp>
80 }
catch (
const std::filesystem::filesystem_error& e) {
82 s_log->error(
"c_api filesystem_error: {}", e.what());
84 }
catch (
const nlohmann::json::exception& e) {
86 s_log->error(
"c_api json::exception: {}", e.what());
88 }
catch (
const std::exception& e) {
90 s_log->error(
"c_api std::exception: {}", e.what());
108 if (!src) {
return nullptr; }
109 size_t len = std::strlen(src) + 1;
111 if (dst) { std::memcpy(dst, src, len); }
135static thread_local std::string s_last_error_cache;
136static thread_local char s_pre_create_error[512] =
"";
157 if (!handle) {
return s_pre_create_error; }
160 return s_last_error_cache.c_str();
234 const std::string tier(tier_name);
236 throw std::runtime_error(
"no backend for tier: " + tier);
239 if (backend ==
nullptr || !backend->is_active()) {
240 throw std::runtime_error(
241 "model could not be made resident for tier: " + tier);
262 if (handle ==
nullptr) {
265 entropic::log::init(spdlog::level::info);
278 static std::atomic<int> s_log_id_counter{0};
281 s_log->info(
"entropic_create() — v{} (log_id={})",
282 CONFIG_ENTROPIC_VERSION_STRING,
engine->log_id);
335 return cached->second;
340 if (cfg && !cfg->allowed_tools.empty()) {
341 return cfg->allowed_tools;
357 const nlohmann::json& all_tools,
358 const std::vector<std::string>& allowed) {
359 std::vector<std::string> result;
360 for (
const auto& tool : all_tools) {
361 std::string name = tool.value(
"name",
"");
362 bool pass = allowed.empty()
363 || std::find(allowed.begin(), allowed.end(), name)
365 if (pass) { result.push_back(tool.dump()); }
378 const std::vector<std::string>& tool_jsons) {
379 nlohmann::json arr = nlohmann::json::array();
380 for (
const auto& tj : tool_jsons) {
381 auto obj = nlohmann::json::parse(tj,
nullptr,
false);
382 if (!obj.is_discarded()) { arr.push_back(std::move(obj)); }
412 auto* servers = (h !=
nullptr && h->server_manager)
415 if (servers ==
nullptr) {
return 1; }
416 auto all_tools = nlohmann::json::parse(servers->list_tools(),
420 if (!all_tools.is_array() || all_tools.empty() || tool_jsons.empty()) {
441 h->
engine->set_external_interrupt(
450 h->
engine->set_external_reset(
471 h->
engine->set_stream_observer(
490 h->
engine->set_queue_observer(
509 h->
engine->set_state_observer(
568 const std::filesystem::path& data_dir,
569 const std::string& shared_prefix) {
573 auto parsed = entropic::prompts::resolve_tier_identity_full(
574 tier, name, data_dir);
575 info.system_prompt = shared_prefix + parsed.body;
576 info.explicit_completion = parsed.frontmatter.explicit_completion
577 .value_or(!tier.auto_chain.has_value());
581 info.max_iterations_override =
582 parsed.frontmatter.max_iterations;
583 info.max_tool_calls_per_turn_override =
584 parsed.frontmatter.max_tool_calls_per_turn;
585 info.max_consecutive_empty_turns_override =
586 parsed.frontmatter.max_consecutive_empty_turns;
588 h->
engine->set_tier_info(name, info);
613 const char* parent_id,
const char* delegating_tier,
614 const char* target_tier,
const char* task,
int max_turns,
615 std::string& delegation_id, std::string& child_conversation_id,
618 if (sb ==
nullptr) {
return false; }
620 parent_id ? parent_id :
"",
621 delegating_tier ? delegating_tier :
"",
622 target_tier ? target_tier :
"",
624 max_turns, delegation_id, child_conversation_id);
640 const char* title, std::string& conversation_id,
643 if (sb ==
nullptr) {
return false; }
645 title ? title :
"session", std::nullopt, std::nullopt);
646 return !conversation_id.empty();
655 const char* delegation_id,
const char* status,
656 const char* summary,
void* user_data) {
658 if (sb ==
nullptr || delegation_id ==
nullptr) {
return false; }
659 std::optional<std::string> sum;
660 if (summary !=
nullptr) { sum = summary; }
662 status ? status :
"completed", sum);
671 const char* conversation_id,
const char* messages_json,
674 if (sb ==
nullptr || conversation_id ==
nullptr
675 || messages_json ==
nullptr) {
687 const char* conversation_id,
const char* messages_json,
690 if (sb ==
nullptr || conversation_id ==
nullptr
691 || messages_json ==
nullptr) {
708 const char* target_tier, std::string& delegation_id,
711 if (sb ==
nullptr || target_tier ==
nullptr) {
return false; }
730 const char* delegation_id, std::string& result_json,
733 bool ok = sb !=
nullptr && delegation_id !=
nullptr;
734 std::string del_json;
735 nlohmann::json del, conv;
736 std::string child_id, target, conv_json;
738 ok = sb->get_delegation_by_id(delegation_id, del_json);
741 del = nlohmann::json::parse(del_json,
nullptr,
false);
742 ok = del.is_object();
745 child_id = del.value(
"child_conversation_id", std::string{});
746 target = del.value(
"target_tier", std::string{});
747 ok = !child_id.empty() && !target.empty()
748 && sb->load_conversation(child_id, conv_json);
751 conv = nlohmann::json::parse(conv_json,
nullptr,
false);
752 ok = conv.is_object();
755 conv[
"target_tier"] = target;
756 conv[
"delegation_id"] = del.value(
"id", std::string{});
757 result_json = conv.dump();
797 h->
storage = std::make_unique<entropic::SqliteStorageBackend>(db_path);
798 if (h->
storage->initialize()) {
799 s_log->info(
"storage: {}", db_path.string());
801 s_log->warn(
"storage init failed, continuing without persistence");
833 std::unordered_set<std::string> targets;
834 for (
const auto& [source, dests] :
config.routing.handoff_rules) {
835 for (
const auto& t : dests) { targets.insert(t); }
837 if (targets.empty()) {
838 for (
const auto& [name, tier] :
config.models.tiers) {
839 if (name !=
config.models.default_tier) {
840 targets.insert(name);
844 return {targets.begin(), targets.end()};
859 const std::filesystem::path& data_dir) {
861 ? std::filesystem::current_path()
868 std::vector<std::string> require_context;
870 if (tier.requires_context) { require_context.push_back(name); }
873 h->
config.
mcp, tier_names, data_dir.string(), require_context);
903 const std::filesystem::path& data_dir) {
904 std::string constitution, app_ctx;
906 entropic::prompts::load_shared_prompt_sources(
907 h->
config, data_dir, constitution, app_ctx);
909 if (!constitution.empty()) { prefix += constitution +
"\n\n"; }
910 if (!app_ctx.empty()) { prefix += app_ctx +
"\n\n"; }
974 const std::string& name,
983 h->
engine->set_relay_single_delegate(name);
1001 const std::filesystem::path& data_dir) {
1003 std::filesystem::path id_path;
1004 if (tier.identity.has_value()) {
1005 id_path = tier.identity.value();
1006 }
else if (!tier.identity_disabled) {
1007 id_path = data_dir /
"prompts" / (
"identity_" + name +
".md");
1009 if (id_path.empty() || !std::filesystem::exists(id_path)) {
1013 if (entropic::prompts::load_identity(id_path,
id).empty()) {
1046 const std::filesystem::path& data_dir) {
1048 std::filesystem::path id_path;
1049 if (tier.identity.has_value()) {
1050 id_path = tier.identity.value();
1051 }
else if (!tier.identity_disabled) {
1052 id_path = data_dir /
"prompts" / (
"identity_" + name +
".md");
1054 if (id_path.empty() || !std::filesystem::exists(id_path)) {
1058 if (entropic::prompts::load_identity(id_path,
id).empty()) {
1083 if (exec ==
nullptr) {
return nullptr; }
1085 if (s.empty() || s ==
"[]") {
return nullptr; }
1086 auto* out =
static_cast<char*
>(std::malloc(s.size() + 1));
1087 if (out !=
nullptr) {
1088 std::memcpy(out, s.data(), s.size());
1089 out[s.size()] =
'\0';
1107 h->
tool_executor = std::make_unique<entropic::ToolExecutor>(
1109 h->
engine->loop_config(),
1111 h->
engine->build_directive_hooks());
1114 const std::vector<entropic::ToolCall>& calls,
1115 void* ud) -> std::vector<entropic::Message> {
1117 ->process_tool_calls(ctx, calls);
1121 tei.
free_fn = [](
char* p) { std::free(p); };
1125 +[](
const std::string& key,
void* ud)
1130 h->
engine->set_tool_executor(tei);
1148 if (h ==
nullptr || h->validator ==
nullptr) {
return nullptr; }
1152 switch (r.verdict) {
1154 v[
"verdict"] =
"passed";
break;
1156 v[
"verdict"] =
"revised";
break;
1158 v[
"verdict"] =
"rejected_reverted_length";
break;
1160 v[
"verdict"] =
"rejected_max_revisions";
break;
1162 v[
"verdict"] =
"skipped";
break;
1164 v[
"verdict"] =
"paused_pending_consumer";
break;
1166 v[
"verdict"] =
"passed_consumer_override";
break;
1168 v[
"revisions_applied"] = r.revision_count;
1172 v[
"attempt_n"] = r.attempt_n;
1173 nlohmann::json violations = nlohmann::json::array();
1174 for (
const auto& vi : r.final_critique.violations) {
1175 violations.push_back({
1177 {
"rule_id", vi.rule},
1178 {
"rule_text", vi.rule},
1179 {
"excerpt", vi.excerpt},
1180 {
"quote", vi.excerpt},
1181 {
"explanation", vi.explanation},
1182 {
"severity",
"error"},
1185 v[
"violations"] = violations;
1186 return strdup(v.dump().c_str());
1207 const std::string& constitution_text) {
1211 const char* json,
char** out) ->
int {
1213 ->fire_pre(pt, json, out);
1216 const char* json,
char** out) {
1218 ->fire_post(pt, json, out);
1224 h->
engine->set_hooks(hook_iface);
1234 && !constitution_text.empty()) {
1235 h->
validator = std::make_unique<entropic::ConstitutionalValidator>(
1237 h->
validator->attach(&hook_iface, &iface);
1246 [h](
const std::string& tier)
1247 -> std::pair<std::string, std::string> {
1250 if (adapter ==
nullptr) {
return {
"<think>",
"</think>"}; }
1251 auto m = adapter->thinking_markers();
1252 return {m.open, m.close};
1257 s_log->info(
"Constitutional validator attached (max_revisions={})",
1273 j[
"log_level"] = h->config.log_level;
1274 j[
"log_dir"] = h->config.log_dir.string();
1275 j[
"ggml_logging"] = h->config.ggml_logging;
1276 return strdup(j.dump().c_str());
1294 auto data_dir = entropic::config::resolve_data_dir(h->
config);
1295 std::string constitution, app_ctx;
1297 entropic::prompts::load_shared_prompt_sources(
1298 h->
config, data_dir, constitution, app_ctx);
1299 std::string identity_body;
1302 identity_body = entropic::prompts::resolve_tier_identity(
1303 it->second, tier_name, data_dir);
1306 if (!constitution.empty()) { out += constitution +
"\n\n"; }
1307 if (!app_ctx.empty()) { out += app_ctx +
"\n\n"; }
1308 if (!identity_body.empty()) { out += identity_body; }
1334 nlohmann::json arr = nlohmann::json::array();
1335 for (
const auto& [name, _] : h->config.models.tiers) {
1336 nlohmann::json entry;
1337 entry[
"name"] = name;
1338 entry[
"assembled_prompt"] =
1340 arr.push_back(std::move(entry));
1342 return strdup(arr.dump().c_str());
1352 if (!h->server_manager) {
return strdup(
"[]"); }
1353 return strdup(h->server_manager->list_tools().c_str());
1376 if (!h || !h->engine) {
return strdup(
"[]"); }
1377 const auto& msgs = h->engine->get_messages();
1378 nlohmann::json arr = nlohmann::json::array();
1382 start =
static_cast<int>(msgs.size()) -
max_entries;
1384 for (
int i = start; i < static_cast<int>(msgs.size()); ++i) {
1385 const auto& m = msgs[
static_cast<size_t>(i)];
1386 std::string preview = m.content.size() > 200
1387 ? entropic::facade::utf8_safe_substr(m.content, 200) +
"..."
1391 {
"content_preview", preview},
1392 {
"token_count_est", m.content.size() / 4u}
1395 return strdup(arr.dump().c_str());
1413 if (!h || !h->orchestrator) {
1414 return strdup(
"{\"vram_total_bytes\":0,\"vram_budget_bytes\":0,"
1415 "\"vram_headroom_bytes\":0,\"backend\":\"unknown\","
1416 "\"residency\":[]}");
1418 return strdup(h->orchestrator->residency_snapshot_json().c_str());
1429 j[
"engine_state"] = h->
configured.load() ?
"configured" :
"init";
1430 j[
"default_tier"] = h->config.models.default_tier;
1432 nlohmann::json tiers = nlohmann::json::array();
1433 for (
const auto& [name, _] : h->config.models.tiers) {
1434 tiers.push_back(name);
1436 j[
"active_tiers"] = tiers;
1438 if (h->server_manager) {
1439 j[
"working_dir"] = h->server_manager->project_dir().string();
1440 j[
"registered_servers"] = h->server_manager->server_names();
1442 j[
"data_dir"] = entropic::config::resolve_data_dir(
1443 h->config).string();
1444 j[
"log_dir"] = h->config.log_dir.string();
1445 return strdup(j.dump().c_str());
1464 nlohmann::json arr = nlohmann::json::array();
1466 for (
const auto& rec : h->
orchestrator->generation_records()) {
1468 {
"finish_reason", rec.finish_reason},
1469 {
"token_count", rec.token_count},
1470 {
"prefill_tokens", rec.prefill_tokens},
1471 {
"throughput_tok_s", rec.throughput_tok_s},
1472 {
"n_drafted", rec.n_drafted},
1473 {
"n_accepted", rec.n_accepted},
1475 {
"source", rec.grammar.source},
1476 {
"key", rec.grammar.key},
1477 {
"resolved", rec.grammar.resolved},
1478 {
"conflict_winner", rec.grammar.conflict_winner},
1504 if (!h || !h->engine) {
return strdup(
"{}"); }
1505 auto m = h->engine->last_loop_metrics();
1508 j[
"iterations"] = m.iterations;
1509 j[
"tool_calls"] = m.tool_calls;
1510 j[
"tokens_used"] = m.tokens_used;
1511 j[
"errors"] = m.errors;
1512 j[
"duration_ms"] = m.duration_ms();
1514 nlohmann::json per_tier = nlohmann::json::object();
1515 for (
auto& [tier, tm] : h->engine->per_tier_metrics()) {
1517 {
"iterations", tm.iterations},
1518 {
"tool_calls", tm.tool_calls},
1519 {
"tokens_used", tm.tokens_used},
1520 {
"errors", tm.errors},
1521 {
"duration_ms", tm.duration_ms()},
1524 j[
"per_tier"] = per_tier;
1525 return strdup(j.dump().c_str());
1555 const char* query,
int max_results,
void* ud) {
1558 if (h ==
nullptr || !h->storage || query ==
nullptr
1559 || !h->storage->search_delegations(query, max_results, out)) {
1562 auto rows = nlohmann::json::parse(out,
nullptr,
false);
1563 nlohmann::json records = nlohmann::json::array();
1564 for (
const auto& r : rows.is_array() ? rows : nlohmann::json::array()) {
1566 rec[
"delegation_id"] = r.value(
"id",
"");
1567 rec[
"target_tier"] = r.value(
"target_tier",
"");
1568 rec[
"summary"] = r.value(
"result_summary",
"");
1569 rec[
"completed_at"] = r.value(
"completed_at",
"");
1570 records.push_back(std::move(rec));
1572 return strdup(records.dump().c_str());
1585 const char* delegation_id,
void* ud) {
1587 if (h ==
nullptr || !h->storage || delegation_id ==
nullptr) {
1592 delegation_id, out, h->storage.get())) {
1595 return strdup(out.c_str());
1613 if (es ==
nullptr) {
return; }
1629 es->set_state_provider(sp);
1630 s_log->info(
"State provider wired to entropic server");
1642 h->
validator->set_tier_rules(name, rules);
1665 const std::string& session_key,
void* ud) {
1668 if (servers ==
nullptr) {
return {}; }
1669 return servers->project_dir();
1682 const std::string& session_key,
1683 const std::vector<std::string>& allowed,
void* ud) {
1686 if (servers ==
nullptr) {
return {}; }
1690 return servers->external_tools_without_readonly_hint(allowed);
1704 h->
engine->set_session_root_interface(iface);
1736 if (bm ==
"tokens") {
1738 }
else if (bm ==
"wall_clock") {
1742 s_log->warn(
"Unknown generation.budget_mode '{}' — "
1743 "treating as 'off'", bm);
1771 if (
port != 0 && (port < 0 || port > 65535)) {
1772 err =
"mcp.external.http_port out of range: " + std::to_string(
port);
1774 err =
"the unix bridge did not start";
1775 }
else if (
port != 0) {
1776 h->
http_listener = std::make_unique<entropic::http::HttpListener>(
1804 s_log->warn(
"External MCP bridge failed to start");
1861 h->
orchestrator = std::make_unique<entropic::ModelOrchestrator>();
1863 h->
last_error =
"orchestrator initialization failed";
1870 h->
orchestrator->load_grammars_from(data_dir /
"grammars");
1889 h->
mcp_auth = std::make_unique<entropic::MCPAuthorizationManager>();
1910 h->
engine = std::make_unique<entropic::AgentEngine>(
1918 std::make_unique<entropic::CompactorRegistry>(
1919 h->
engine->compaction_manager());
1951 h->
engine->set_system_prompt(
1952 entropic::prompts::assemble(h->
config, data_dir));
1977 auto err = entropic::prompts::validate_configured_prompts(
1982 s_log->error(
"configure: {}",
err);
2015 auto warning = entropic::config::warn_unresolved_tier_grammars(
2017 entropic::config::grammar_search_paths(h->
config, data_dir));
2018 if (!warning.empty()) {
2019 s_log->warn(
"configure: {}", warning);
2044 auto data_dir = entropic::config::resolve_data_dir(h->
config);
2075 s_log->info(
"configure complete");
2089 auto err = entropic::config::load_config_from_string(
2093 s_log->error(
"configure: {}",
err);
2104 entropic::log::register_handle_log(
2122 const char* config_json) {
2123 if (!handle || !config_json) {
2142 auto err = entropic::config::load_config_from_file(
2146 s_log->error(
"configure_from_file: {}",
err);
2158 entropic::log::register_handle_log(
2176 const char* config_path) {
2177 if (!handle || !config_path) {
2197 if (project_dir && project_dir[0] !=
'\0') {
2198 entropic::log::setup_session(project_dir);
2202 entropic::log::register_handle_log(handle->
log_id, project_dir);
2205 std::filesystem::path proj_dir = (project_dir && project_dir[0] !=
'\0')
2207 auto err = entropic::config::load_layered(
2208 proj_dir,
"default_config.yaml",
2212 s_log->error(
"configure_dir: {}",
err);
2220 handle->
engine->set_project_dir(std::filesystem::absolute(proj_dir));
2243 const char* project_dir) {
2263 if (handle ==
nullptr) {
2266 s_log->info(
"entropic_destroy()");
2290 for (
auto& [name, ws] : handle->
workspaces) {
2291 if (ws && ws->servers) { ws->servers->shutdown(); }
2300 entropic::log::unregister_handle_log(handle->
log_id);
2315 return CONFIG_ENTROPIC_VERSION_STRING;
2338 if (!handle || !handle->
engine) {
return 0; }
2339 return handle->
engine->seconds_since_last_activity();
2351 return malloc(size);
2389 char** result_json) {
2406 auto result = handle->
engine->run_turn(input);
2408 facade_json::serialize_messages(result));
2417 }
catch (
const std::exception& e) {
2425 facade_json::serialize_messages(
2426 handle->
engine->get_messages()));
2428 *result_json =
nullptr;
2444 char** result_json) {
2446 auto result = handle->
engine->run_turn_as(tier, input);
2447 *result_json =
alloc_cstr(facade_json::serialize_messages(result));
2453 }
catch (
const std::exception& e) {
2455 s_log->error(
"run_as: {}", handle->
last_error);
2460 facade_json::serialize_messages(handle->
engine->get_messages()));
2462 *result_json =
nullptr;
2490 const char* tier_or_identity,
2492 char** result_json) {
2501 if (rc !=
ENTROPIC_OK || !tier_or_identity || !input || !result_json
2504 : (!tier_or_identity || !input || !result_json)
2509 if (!handle->
engine->has_tier(tier_or_identity)) {
2511 std::string(
"unknown tier: ") + tier_or_identity;
2512 s_log->error(
"run_as: {}", handle->
last_error);
2515 return run_as_inner(handle, tier_or_identity, input, result_json);
2526 const std::vector<entropic::GenerationResult>& results) {
2527 nlohmann::json arr = nlohmann::json::array();
2528 for (
const auto& r : results) {
2530 obj[
"content"] = entropic::mcp::sanitize_utf8(r.content);
2531 obj[
"finish_reason"] = r.finish_reason;
2532 obj[
"tool_calls"] = nlohmann::json::parse(
2534 arr.push_back(std::move(obj));
2555 size_t n, std::vector<std::string>& tiers_out) {
2556 std::vector<std::vector<entropic::Message>> msgs(n);
2557 tiers_out.resize(n);
2558 for (
size_t i = 0; i < n; ++i) {
2559 tiers_out[i] = (tiers && tiers[i]) ? tiers[i] :
"";
2560 const std::string& sys =
2561 handle->
engine->tier_system_prompt(tiers_out[i]);
2562 std::vector<entropic::Message> m;
2567 m.push_back(std::move(s));
2571 u.
content = prompts[i] ? prompts[i] :
"";
2572 m.push_back(std::move(u));
2573 msgs[i] = std::move(m);
2603 const char** prompts,
2605 char** result_json) {
2615 || n == 0 || !turn.
claim()) {
2617 : (!prompts || !result_json || n == 0)
2623 std::vector<std::string> tiers_vec;
2625 std::vector<entropic::GenerationParams> params(n);
2632 std::atomic<bool>&
cancel = handle->
engine->run_cancel_flag();
2634 msgs, params, tiers_vec,
cancel);
2637 }
catch (
const std::exception& e) {
2639 s_log->error(
"run_batch: {}", handle->
last_error);
2669 void (*on_token)(
const char* token,
size_t len,
void* user_data),
2683 : (!input || !on_token || !handle->
engine)
2692 int code = handle->
engine->run_streaming(
2693 input, on_token, user_data, cancel_flag);
2699 }
catch (
const std::exception& e) {
2701 s_log->error(
"run_streaming: {}", handle->
last_error);
2727 const char* messages_json,
2759 const char* messages_json,
2760 char** result_json) {
2764 auto result = handle->
engine->run_turn(std::move(msgs));
2766 facade_json::serialize_messages(result));
2795 const char* messages_json,
2796 char** result_json) {
2805 if (rc !=
ENTROPIC_OK || !messages_json || !result_json
2808 : (!messages_json || !result_json || !handle->
engine)
2814 }
catch (
const std::exception& e) {
2816 s_log->error(
"run_messages: {}", handle->
last_error);
2833 const char* messages_json,
2834 void (*on_token)(
const char* token,
size_t len,
void* user_data),
2840 int code = handle->
engine->run_streaming(
2841 std::move(msgs), on_token, user_data, cancel_flag);
2871 const char* messages_json,
2872 void (*on_token)(
const char* token,
size_t len,
void* user_data),
2883 if (rc !=
ENTROPIC_OK || !messages_json || !on_token
2886 : (!messages_json || !on_token || !handle->
engine)
2892 handle, messages_json, on_token, user_data, cancel_flag);
2893 }
catch (
const std::exception& e) {
2895 s_log->error(
"run_messages_streaming: {}", handle->
last_error);
2912 void (*observer)(
const char* token,
size_t len,
void* user_data),
2920 handle->
engine->set_stream_observer(observer, user_data);
2939 handle->
validator->set_auto_retry(enabled != 0);
2958 return handle->
validator->resume_retry();
2975 return handle->
validator->accept_last();
2993 handle->
validator->set_attempt_boundary_cb(cb, user_data);
3017 handle->
engine->set_delegation_callbacks(
3018 on_start, on_complete, user_data);
3043 void (*observer)(
int state,
void* user_data),
3047 handle->state_observer_data = user_data;
3055 handle->
engine->set_state_observer(observer, user_data);
3082 void (*start_cb)(
void* user_data),
3083 void (*end_cb)(
void* user_data),
3090 handle->
validator->set_critique_callbacks(
3091 start_cb, end_cb, user_data);
3109 handle->
engine->interrupt();
3130 const char* session_key) {
3133 const bool found = handle->
engine->interrupt_session(
3134 session_key !=
nullptr ? session_key :
"");
3162 }
else if (!message) {
3164 }
else if (!handle->
engine || !handle->
engine->is_running()) {
3166 }
else if (!handle->
engine->queue_user_message(message)) {
3186 ? handle->
engine->user_message_queue_depth() : 0;
3202 handle->
engine->clear_user_message_queue();
3223 void (*observer)(
const char*,
size_t,
void*),
3227 handle->queue_observer_data = user_data;
3229 handle->
engine->set_queue_observer(observer, user_data);
3253 const auto key = handle->
engine->active_session_key();
3254 handle->
engine->clear_conversation();
3280 if (!handle || !messages_json || !handle->
engine) {
3281 return (handle !=
nullptr && messages_json ==
nullptr)
3287 facade_json::serialize_messages(handle->
engine->get_messages()));
3318 const char* session_key,
3320 char** result_json) {
3330 handle->
engine->set_active_session(session_key ? session_key :
"");
3332 auto result = handle->
engine->run_turn(input);
3334 facade_json::serialize_messages(result));
3339 }
catch (
const std::exception& e) {
3341 s_log->error(
"run_session: {}", handle->
last_error);
3342 *result_json =
nullptr;
3362 const char* session_key,
3363 const char* tier_or_identity,
3365 char** result_json) {
3368 if (rc !=
ENTROPIC_OK || !tier_or_identity || !input || !result_json
3371 : (!tier_or_identity || !input || !result_json)
3376 if (!handle->
engine->has_tier(tier_or_identity)) {
3378 std::string(
"unknown tier: ") + tier_or_identity;
3381 handle->
engine->set_active_session(session_key ? session_key :
"");
3382 return run_as_inner(handle, tier_or_identity, input, result_json);
3397 void (*on_token)(
const char*,
size_t,
void*)) {
3399 if (!input || !on_token || !handle->
engine) {
3401 }
else if (tier !=
nullptr && !handle->
engine->has_tier(tier)) {
3402 handle->
last_error = std::string(
"unknown tier: ") + tier;
3423 const char* input,
void (*on_token)(
const char*,
size_t,
void*),
3424 void* user_data,
int* cancel_flag) {
3425 handle->
engine->set_active_session(session_key ? session_key :
"");
3427 int code = handle->
engine->run_streaming(
3428 input, on_token, user_data, cancel_flag, tier);
3433 }
catch (
const std::exception& e) {
3435 s_log->error(
"run_session_streaming: {}", handle->
last_error);
3455 const char* input,
void (*on_token)(
const char*,
size_t,
void*),
3456 void* user_data,
int* cancel_flag) {
3463 input, on_token, user_data, cancel_flag);
3482 const char* session_key,
3484 void (*on_token)(
const char* token,
size_t len,
void* user_data),
3488 on_token, user_data, cancel_flag);
3507 const char* session_key,
3508 const char* tier_or_identity,
3510 void (*on_token)(
const char* token,
size_t len,
void* user_data),
3515 input, on_token, user_data, cancel_flag);
3529 const char* session_key,
3530 char** messages_json) {
3531 if (!handle || !messages_json || !handle->
engine) {
3532 return (handle !=
nullptr && messages_json ==
nullptr)
3537 *messages_json =
alloc_cstr(facade_json::serialize_messages(
3538 handle->
engine->messages_for(session_key ? session_key :
"")));
3556 const char* messages_json,
3557 std::vector<entropic::Message>& out) {
3561 }
catch (
const std::exception& e) {
3563 std::string(
"session_context_set: malformed messages JSON: ")
3591 const std::string& key,
3592 const char* messages_json) {
3593 std::vector<entropic::Message> msgs;
3597 if (!handle->
engine->set_session_messages(key, std::move(msgs))) {
3599 "session_context_set: a run on session '" + key
3632 const char* session_key,
3633 const char* messages_json) {
3634 if (!handle || !handle->
engine || !messages_json) {
3635 return (handle !=
nullptr && handle->
engine !=
nullptr)
3641 handle, session_key !=
nullptr ? session_key :
"", messages_json);
3655 const char* session_key,
3657 if (!handle || !count || !handle->
engine) {
3658 return (handle !=
nullptr && count ==
nullptr)
3663 *count = handle->
engine->message_count_for(
3664 session_key ? session_key :
"");
3687 const char* session_key) {
3688 if (!handle || !handle->
engine) {
3692 const std::string key = session_key ? session_key :
"";
3693 handle->
engine->clear_conversation_for(key);
3714 const char* session_key) {
3715 if (!handle || !handle->
engine) {
3719 const std::string key = session_key ? session_key :
"";
3720 handle->
engine->drop_session(key);
3740 char** sessions_json) {
3741 if (!handle || !sessions_json || !handle->
engine) {
3742 return (handle !=
nullptr && sessions_json ==
nullptr)
3747 nlohmann::json arr = nlohmann::json::array();
3748 for (
const auto& key : handle->
engine->session_keys()) {
3749 arr.push_back({{
"key", key},
3750 {
"messages", handle->
engine->message_count_for(key)}});
3769 if (!handle || !count || !handle->
engine) {
3770 return (handle !=
nullptr && count ==
nullptr)
3774 *count = handle->
engine->message_count();
3795 size_t* tokens_used,
3800 auto [used, max] = handle->
engine->context_usage(
3801 handle->
engine->get_messages());
3802 *tokens_used =
static_cast<size_t>(used);
3803 *capacity =
static_cast<size_t>(max);
3816 std::vector<uint8_t> buf;
3818 std::ofstream out(path, std::ios::binary | std::ios::trunc);
3819 bool ok = out.is_open()
3820 && out.write(
reinterpret_cast<const char*
>(buf.data()),
3821 static_cast<std::streamsize
>(buf.size())).good();
3835 const char* tier_name,
3840 if (!handle || !tier_name || !path
3841 || (handle->
engine !=
nullptr && !turn.
claim())) {
3863 std::ifstream in(path, std::ios::binary | std::ios::ate);
3864 if (!in.is_open()) {
return false; }
3865 auto sz =
static_cast<std::streamsize
>(in.tellg());
3866 if (sz <= 0) {
return false; }
3867 in.seekg(0, std::ios::beg);
3868 out_buf.resize(
static_cast<size_t>(sz));
3869 return static_cast<bool>(
3870 in.read(
reinterpret_cast<char*
>(out_buf.data()), sz));
3882 std::vector<uint8_t> buf;
3884 return backend->restore_state(0, buf)
3898 const char* tier_name,
3902 if (!handle || !tier_name || !path
3903 || (handle->
engine !=
nullptr && !turn.
claim())) {
3953 const char* adapter_path,
const char* base_model_path,
float scale)
3957 throw std::runtime_error(
"no tier for model: "
3958 + std::string(base_model_path));
3965 if (!llama || !llama->llama_model_ptr()) {
3966 throw std::runtime_error(
"backend not ready for tier: " + tier);
3968 bool ok = handle->
orchestrator->adapter_manager().load(
3969 adapter_name, adapter_path, llama->llama_model_ptr(), scale);
3997 const char* adapter_name,
3998 const char* adapter_path,
3999 const char* base_model_path,
4005 if (rc !=
ENTROPIC_OK || !adapter_name || !adapter_path
4007 || (handle->
engine !=
nullptr && !turn.
claim())) {
4009 : (!adapter_name || !adapter_path || !base_model_path)
4016 base_model_path, scale);
4035 const char* adapter_name)
4044 auto info = mgr.info(adapter_name);
4046 throw std::runtime_error(
"adapter not loaded: "
4047 + std::string(adapter_name));
4052 mgr.
unload(adapter_name, llama ? llama->llama_context_ptr() :
nullptr);
4054 }
catch (
const std::exception& e) {
4075 const char* adapter_name)
4086 if (!llama || !llama->llama_context_ptr()) {
4087 throw std::runtime_error(
"no active llama context for swap");
4089 bool ok = handle->
orchestrator->adapter_manager().swap(
4090 adapter_name, llama->llama_context_ptr());
4092 }
catch (
const std::exception& e) {
4112 const char* adapter_name)
4119 auto st = handle->
orchestrator->adapter_manager().state(adapter_name);
4120 return static_cast<int>(st);
4121 }
catch (
const std::exception& e) {
4123 s_log->error(
"adapter_state: {}", handle->
last_error);
4143 const char* adapter_name)
4150 auto ai = handle->
orchestrator->adapter_manager().info(adapter_name);
4152 facade_json::serialize_adapter_info(ai).c_str());
4153 }
catch (
const std::exception& e) {
4155 s_log->error(
"adapter_info: {}", handle->
last_error);
4179 auto adapters = handle->
orchestrator->adapter_manager().list_adapters();
4181 facade_json::serialize_adapter_list(adapters).c_str());
4182 }
catch (
const std::exception& e) {
4184 s_log->error(
"adapter_list: {}", handle->
last_error);
4208 const char* gbnf_content)
4217 .register_grammar(key, gbnf_content);
4218 s_log->info(
"grammar_register: key={} ok={}", key, ok);
4220 }
catch (
const std::exception& e) {
4222 s_log->error(
"grammar_register: {}", handle->
last_error);
4252 .register_from_file(key, path);
4253 s_log->info(
"grammar_register_file: key={} ok={}", key, ok);
4255 }
catch (
const std::exception& e) {
4257 s_log->error(
"grammar_register_file: {}", handle->
last_error);
4285 bool ok = handle->
orchestrator->grammar_registry().deregister(key);
4286 s_log->info(
"grammar_deregister: key={} ok={}", key, ok);
4288 }
catch (
const std::exception& e) {
4290 s_log->error(
"grammar_deregister: {}", handle->
last_error);
4317 auto content = handle->
orchestrator->grammar_registry().get(key);
4318 return content.empty() ? nullptr :
alloc_cstr(content.c_str());
4319 }
catch (
const std::exception& e) {
4321 s_log->error(
"grammar_get: {}", handle->
last_error);
4341 if (!gbnf_content) {
return alloc_cstr(
"null input"); }
4345 }
catch (
const std::exception& e) {
4370 auto entries = handle->
orchestrator->grammar_registry().list();
4371 nlohmann::json arr = nlohmann::json::array();
4372 for (
const auto& e : entries) {
4373 arr.push_back({{
"key", e.key},
4374 {
"source", e.source},
4375 {
"validated", e.validated},
4376 {
"error", e.error}});
4379 }
catch (
const std::exception& e) {
4381 s_log->error(
"grammar_list: {}", handle->
last_error);
4404 const char* profile_json)
4412 auto j = nlohmann::json::parse(profile_json);
4414 p.
name = j.value(
"name",
"");
4415 if (p.
name.empty()) {
throw std::invalid_argument(
"missing 'name'"); }
4416 p.
n_batch = j.value(
"n_batch", 512);
4421 .register_profile(p);
4422 s_log->info(
"profile_register: name={} ok={}", p.
name, ok);
4424 }
catch (
const std::exception& e) {
4426 s_log->error(
"profile_register: {}", handle->
last_error);
4454 bool ok = handle->
orchestrator->profile_registry().deregister(name);
4455 s_log->info(
"profile_deregister: name={} ok={}", name, ok);
4457 }
catch (
const std::exception& e) {
4459 s_log->error(
"profile_deregister: {}", handle->
last_error);
4488 auto p = handle->
orchestrator->profile_registry().get(name);
4491 j[
"n_batch"] = p.n_batch;
4492 j[
"n_threads"] = p.n_threads;
4493 j[
"n_threads_batch"] = p.n_threads_batch;
4494 j[
"description"] = p.description;
4496 }
catch (
const std::exception& e) {
4498 s_log->error(
"profile_get: {}", handle->
last_error);
4522 auto names = handle->
orchestrator->profile_registry().list();
4523 nlohmann::json arr = nlohmann::json(names);
4525 }
catch (
const std::exception& e) {
4527 s_log->error(
"profile_list: {}", handle->
last_error);
4550 const char* model_path)
4557 return handle->
orchestrator->throughput_tracker().tok_per_sec();
4558 }
catch (
const std::exception& e) {
4560 s_log->error(
"throughput_tok_per_sec: {}", handle->
last_error);
4580 const char* model_path)
4588 s_log->info(
"throughput_reset: data cleared");
4589 }
catch (
const std::exception& e) {
4591 s_log->error(
"throughput_reset: {}", handle->
last_error);
4607 const char* identity_name,
4608 const char* pattern,
4612 if (rc !=
ENTROPIC_OK || !identity_name || !pattern) {
4616 return handle->
mcp_auth->grant(identity_name, pattern, lvl);
4629 const char* identity_name,
4630 const char* pattern)
4633 if (rc !=
ENTROPIC_OK || !identity_name || !pattern) {
4636 return handle->
mcp_auth->revoke(identity_name, pattern);
4649 const char* identity_name,
4650 const char* tool_name,
4654 || !handle->
mcp_auth || !identity_name || !tool_name) {
4658 return handle->
mcp_auth->check_access(identity_name, tool_name, lvl) ? 1 : 0;
4673 const char* identity_name)
4676 || !handle->
mcp_auth || !identity_name) {
4680 auto keys = handle->
mcp_auth->list_keys(identity_name);
4681 nlohmann::json arr = nlohmann::json::array();
4682 for (
const auto& k : keys) {
4683 arr.push_back({{
"pattern", k.tool_pattern},
4684 {
"level",
static_cast<int>(k.level)}});
4687 }
catch (
const std::exception& e) {
4703 const char* granter,
4704 const char* grantee,
4705 const char* pattern,
4709 if (rc !=
ENTROPIC_OK || !granter || !grantee || !pattern) {
4713 return handle->
mcp_auth->grant_from(granter, grantee, pattern, lvl);
4732 auto json = handle->
mcp_auth->serialize_all();
4734 }
catch (
const std::exception& e) {
4756 bool ok = handle->
mcp_auth->deserialize_all(json);
4773 const char* config_json)
4780 auto j = nlohmann::json::parse(config_json);
4782 cfg.
name = j.value(
"name",
"");
4784 if (j.contains(
"focus") && j[
"focus"].is_array()) {
4785 cfg.
focus = j[
"focus"].get<std::vector<std::string>>();
4789 }
catch (
const std::exception& e) {
4807 const char* config_json)
4814 auto j = nlohmann::json::parse(config_json);
4818 if (j.contains(
"focus") && j[
"focus"].is_array()) {
4819 cfg.
focus = j[
"focus"].get<std::vector<std::string>>();
4823 }
catch (
const std::exception& e) {
4865 if (!cfg) {
throw std::runtime_error(
"identity not found"); }
4867 j[
"name"] = cfg->name;
4868 j[
"system_prompt"] = cfg->system_prompt;
4870 ?
"static" :
"dynamic";
4892 nlohmann::json arr(names);
4941 result->
logprobs =
static_cast<float*
>(
4942 malloc(
sizeof(
float) * lr.
logprobs.size()));
4944 result->
tokens =
static_cast<int32_t*
>(
4945 malloc(
sizeof(int32_t) * lr.
tokens.size()));
4965 const char* model_id,
4966 const int32_t* tokens,
4973 if (rc !=
ENTROPIC_OK || !model_id || !tokens || !result || n_tokens < 2
4974 || (handle->
engine !=
nullptr && !turn.
claim())) {
4976 : (!model_id || !tokens || !result || n_tokens < 2)
4986 }
catch (
const std::exception& e) {
4988 s_log->error(
"get_logprobs: {}", handle->
last_error);
5007 const char* model_id,
5008 const int32_t* tokens,
5015 if (rc !=
ENTROPIC_OK || !model_id || !tokens || !perplexity
5016 || n_tokens < 2 || (handle->
engine !=
nullptr && !turn.
claim())) {
5018 : (!model_id || !tokens || !perplexity || n_tokens < 2)
5025 *perplexity = backend->compute_perplexity(tokens, n_tokens);
5027 }
catch (
const std::exception& e) {
5029 s_log->error(
"compute_perplexity: {}", handle->
last_error);
5046 if (result ==
nullptr) {
5052 result->
tokens =
nullptr;
5072 const char* model_id)
5083 return handle->
orchestrator->tier_declares_vision(model_id) ? 1 : 0;
5084 }
catch (
const std::exception& e) {
5086 s_log->error(
"model_has_vision: {}", handle->
last_error);
5107 handle->
validator->set_global_enabled(enabled);
5121 const char* identity_name,
5129 handle->
validator->set_identity_validation(identity_name, enabled);
5145 if (!handle || !handle->
validator) {
return nullptr; }
5147 auto result = handle->
validator->last_result();
5149 j[
"content"] = entropic::mcp::sanitize_utf8(result.content);
5150 j[
"was_revised"] = result.was_revised;
5151 j[
"revision_count"] = result.revision_count;
5170 char** prompt_out) {
5171 if (handle ==
nullptr || prompt_out ==
nullptr) {
5175 static const char* prompt =
5176 "[SYSTEM DIRECTIVE: SELF-DIAGNOSIS]\n\n"
5177 "Analyze your recent actions and identify any issues. "
5178 "Follow these steps:\n\n"
5179 "1. Call entropic.diagnose to get a full engine state "
5181 "2. Review the tool call history for:\n"
5182 " - Repeated failures (same tool, same error)\n"
5183 " - Duplicate tool calls (circuit breaker risk)\n"
5184 " - Tool calls that returned errors\n"
5185 " - Unexpected state (wrong phase, wrong tier)\n"
5186 "3. Review your reasoning for:\n"
5187 " - Actions that didn't achieve the stated goal\n"
5188 " - Unnecessary tool calls\n"
5189 " - Missing context that led to errors\n"
5190 "4. Produce a structured assessment:\n"
5191 " - FINDINGS: What went wrong (be specific)\n"
5192 " - ROOT CAUSE: Why it went wrong\n"
5193 " - RECOMMENDATION: What to do differently\n\n"
5194 "Be honest and specific. The goal is accurate "
5195 "self-assessment, not self-defense.\n";
5225 char** diagnostic) {
5226 if (handle ==
nullptr || compatible ==
nullptr) {
5232 auto info = handle->
orchestrator->check_speculative_compat();
5233 *compatible = info.compatible ? 1 : 0;
5234 if (diagnostic !=
nullptr) {
5235 *diagnostic = info.compatible
5271 if (observer !=
nullptr) {
5272 fn = [observer, user_data](
5274 const std::string& tier_name,
5275 const std::string& model_path,
5285 handle->
orchestrator->set_residency_observer(std::move(fn));
5308 const char* tier_name) {
5312 || (handle->
engine !=
nullptr && !turn.
claim())) {
5318 tier_name !=
nullptr ? tier_name :
"");
5342 if (handle ==
nullptr || out_json ==
nullptr) {
5347 std::string snapshot =
5350 if (*out_json ==
nullptr) {
static std::string validate(const std::string &gbnf_content)
Validate a GBNF grammar string.
gh#59 (v2.3.1): RAII guard combining api_mutex + log scope.
gh#144 (v2.12.0): RAII turn claim + log scope, for the RUN paths.
bool claim()
Claim the turn.
Thread-safe hook registration and dispatch.
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.
void fire_info(entropic_hook_point_t point, const char *context_json)
Fire informational hooks (no modify, no cancel).
Concrete base class for inference backends (80% logic).
void unload()
Full unload (→ COLD).
LlamaCppBackend — common llama.cpp patterns (15% layer).
Multi-model lifecycle and routing orchestrator.
std::function< void(ResidencyEvent event, const std::string &tier_name, const std::string &model_path, size_t footprint)> ResidencyObserverFn
Residency observer callback type (internal C++ form).
void clear_all_prompt_caches()
Invalidate prompt/KV caches across every pooled backend.
ResidencyEvent
Residency observer event codes — mirror the C ABI enum entropic_residency_event_t exactly (LOADED=0,...
Manages MCP server instances and routes tool calls.
void clear_external_tool_interrupts()
Release the interrupt on every external client (gh#150).
void interrupt_external_tools()
Abort in-flight tool calls across every external MCP client.
SQLite-based storage backend.
bool save_messages(const std::string &conversation_id, const std::string &messages_json)
Save messages to a conversation.
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.
bool latest_delegation_for_target(const std::string &target_tier, std::string &delegation_id)
Search delegations across all conversations (gh#32, v2.1.6).
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.
bool save_snapshot(const std::string &conversation_id, const std::string &messages_json)
Save a pre-compaction snapshot of full conversation history.
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.
std::string to_json(size_t count) const
Serialize recent entries to JSON array string.
std::string auto_discover_and_load()
Auto-discover and load bundled_models.yaml.
AgentEngine * engine
Fallback interrupt target.
int * cancel
Consumer's cancel flag, nullable.
Private definition of the entropic_engine struct.
static entropic_error_t check_mcp_auth(entropic_handle_t h)
Check handle prerequisites for MCP auth APIs.
static void thread_frontmatter_sampler(entropic::TierConfig &tc, const entropic::prompts::IdentityFrontmatter &fm)
Cache per-tier frontmatter fields (allowed_tools, validation_rules, relay).
static entropic_error_t stream_session_turn(entropic_handle_t handle, const char *session_key, const std::string &tier, const char *input, void(*on_token)(const char *, size_t, void *), void *user_data, int *cancel_flag)
Run one streaming turn on a claimed session (gh#144, gh#205).
static entropic_error_t do_configure_dir(entropic_handle_t handle, const char *project_dir)
entropic_configure_dir body — wrapped by c_api_try.
static void apply_identity_frontmatter(entropic_handle_t h, const std::string &name, const entropic::prompts::IdentityFrontmatter &fm)
Apply a parsed identity's frontmatter to the engine handle.
entropic_error_t entropic_run_messages(entropic_handle_t handle, const char *messages_json, char **result_json)
Blocking multimodal agentic run (gh#37, v2.1.8).
static entropic_error_t do_state_load(entropic_handle_t handle, const char *tier_name, const char *path)
Load tier's KV cache from file body (gh#23 v2.3.25).
entropic_error_t entropic_identity_count(entropic_handle_t handle, size_t *total, size_t *dynamic)
Get identity count (total and dynamic).
static bool si_create_delegation(const char *parent_id, const char *delegating_tier, const char *target_tier, const char *task, int max_turns, std::string &delegation_id, std::string &child_conversation_id, void *user_data)
Initialize persistence: storage + session logger.
static entropic_error_t reject_if_configured(entropic_handle_t h)
Post-parse config setup: subsystem construction + wiring.
entropic_error_t entropic_session_drop(entropic_handle_t handle, const char *session_key)
Forget a session entirely (gh#144, v2.12.0).
static std::vector< std::string > resolve_allowed_tools(entropic_engine *h, const std::string &tier)
Post-parse config setup: load bundled models, set configured.
static entropic_error_t do_configure_json(entropic_handle_t handle, const char *config_json)
entropic_configure body — wrapped by c_api_try in the public entry.
static void start_external_bridge(entropic_handle_t h)
Start the external MCP bridge if enabled in config.
static char * sp_search_delegations(const char *query, int max_results, void *ud)
State provider: search_delegations (gh#32, v2.1.6).
entropic_error_t entropic_grammar_deregister(entropic_handle_t handle, const char *key)
Remove a grammar from the registry.
entropic_error_t entropic_run_session_streaming(entropic_handle_t handle, const char *session_key, const char *input, void(*on_token)(const char *token, size_t len, void *user_data), void *user_data, int *cancel_flag)
Streaming turn on a named session (gh#144, v2.12.0).
static entropic_error_t validate_prompt_sources(entropic_handle_t h, const std::filesystem::path &data_dir)
Reject a configured prompt path that cannot be loaded (gh#156).
entropic_error_t entropic_context_usage(entropic_handle_t handle, size_t *tokens_used, size_t *capacity)
Read current context-window pressure (gh#39, v2.1.8).
char * entropic_adapter_list(entropic_handle_t handle)
List all known adapters as a JSON array.
static nlohmann::json generations_json(entropic_engine *h)
Serialize the orchestrator's per-generation records (gh#154).
entropic_error_t entropic_validation_resume_retry(entropic_handle_t handle)
Resume a paused constitutional revision pass.
static char * sp_load_delegation_conversation(const char *delegation_id, void *ud)
State provider: load_delegation_conversation (gh#32, v2.1.6).
static entropic_error_t run_messages_stream_inner(entropic_handle_t handle, const char *messages_json, void(*on_token)(const char *token, size_t len, void *user_data), void *user_data, int *cancel_flag)
Streaming multimodal run (gh#37, v2.1.8).
static char * sp_get_metrics(void *ud)
State provider: get_metrics.
static char * sp_get_state(void *ud)
State provider: get_state (runtime environment).
static void rewire_observers(entropic_handle_t h)
Re-bind every pre-configure observer to the new engine.
entropic_error_t entropic_deserialize_mcp_keys(entropic_handle_t handle, const char *json)
Deserialize all identity key sets from JSON.
static char * sp_get_residency(void *ud)
State provider: get_residency — VRAM residency snapshot.
static std::string build_shared_prompt_prefix(entropic_handle_t h, const std::filesystem::path &data_dir)
Build shared system prompt prefix (constitution + app_context).
entropic_error_t entropic_create(entropic_handle_t *handle)
Create a new engine instance.
static void init_mcp_servers(entropic_handle_t h, const std::filesystem::path &data_dir)
Initialize MCP servers with resolved working directory.
entropic_error_t entropic_grammar_register(entropic_handle_t handle, const char *key, const char *gbnf_content)
Register a grammar by key with GBNF content.
entropic_error_t entropic_set_stream_observer(entropic_handle_t handle, void(*observer)(const char *token, size_t len, void *user_data), void *user_data)
Set a global stream observer callback.
entropic_error_t entropic_validation_set_auto_retry(entropic_handle_t handle, int enabled)
Toggle automatic constitutional revision.
entropic_error_t entropic_update_identity(entropic_handle_t handle, const char *name, const char *config_json)
Update an existing dynamic identity.
entropic_error_t entropic_set_residency_observer(entropic_handle_t handle, entropic_residency_observer_t observer, void *user_data)
Register a residency observer on the orchestrator.
entropic_error_t entropic_metrics_json(entropic_handle_t handle, char **out)
Get loop metrics as JSON (flat + per_tier).
entropic_error_t entropic_validation_set_identity(entropic_handle_t handle, const char *identity_name, bool enabled)
Set per-identity validation override.
entropic_error_t entropic_grant_mcp_key_from(entropic_handle_t handle, const char *granter, const char *grantee, const char *pattern, entropic_mcp_access_level_t level)
Grant a key from one identity to another.
void entropic_free(void *ptr)
Free memory allocated by the engine.
entropic_error_t entropic_run_streaming(entropic_handle_t handle, const char *input, void(*on_token)(const char *token, size_t len, void *user_data), void *user_data, int *cancel_flag)
Streaming generation — delegates entirely to engine.
static entropic_error_t check_stream_args(entropic_handle_t handle, const char *tier, const char *input, void(*on_token)(const char *, size_t, void *))
Validate a streaming session turn's arguments (gh#205).
double entropic_throughput_tok_per_sec(entropic_handle_t handle, const char *model_path)
Get EWMA throughput estimate in tokens per second.
char * entropic_profile_get(entropic_handle_t handle, const char *name)
Get a GPU resource profile by name as JSON.
entropic_error_t entropic_validation_accept_last(entropic_handle_t handle)
Accept the last paused attempt as the final answer.
static void populate_tier_info(entropic_handle_t h, const std::filesystem::path &data_dir, const std::string &shared_prefix)
Register per-tier ChildContextInfo with the engine.
static entropic_error_t start_http_listener(entropic_handle_t h)
Start the Streamable-HTTP listener when one is configured (gh#204).
static entropic::InferenceBackend * require_ready_backend(entropic_handle_t h, const char *tier_name)
Resolve a tier name to a resident backend, loading it if needed.
static void init_persistence(entropic_handle_t h)
Initialize persistence: storage + session logger + StorageInterface.
void entropic_throughput_reset(entropic_handle_t handle, const char *model_path)
Reset throughput tracking data.
entropic_error_t entropic_state_load(entropic_handle_t handle, const char *tier_name, const char *path)
Restore a tier's KV cache from a file (gh#23 v2.3.25).
static char * sp_get_docs(const char *section, void *ud)
State provider: get_docs.
static bool si_save_conversation(const char *conversation_id, const char *messages_json, void *user_data)
StorageInterface bridge: save_conversation trampoline.
static void rewire_state_observer(entropic_handle_t h)
Propagate any pre-configure state observer to the new engine.
entropic_error_t entropic_session_context_set(entropic_handle_t handle, const char *session_key, const char *messages_json)
Replace one session's conversation — see entropic.h (gh#165).
static entropic_error_t run_as_inner(entropic_handle_t handle, const char *tier, const char *input, char **result_json)
Run + serialize for entropic_run_as (gh#99).
entropic_error_t entropic_set_critique_callbacks(entropic_handle_t handle, void(*start_cb)(void *user_data), void(*end_cb)(void *user_data), void *user_data)
Register critique start/end callbacks on the handle (gh#50, v2.1.12).
entropic_error_t entropic_queue_user_message(entropic_handle_t handle, const char *message)
Enqueue a follow-up user message while a run is in flight.
char * entropic_list_mcp_keys(entropic_handle_t handle, const char *identity_name)
List MCP keys for an identity as JSON array.
void entropic_destroy(entropic_handle_t handle)
Destroy an engine instance.
entropic_error_t entropic_adapter_load(entropic_handle_t handle, const char *adapter_name, const char *adapter_path, const char *base_model_path, float scale)
Load a LoRA adapter into RAM.
static bool si_latest_delegation_for_target(const char *target_tier, std::string &delegation_id, void *user_data)
StorageInterface bridge: latest_delegation_for_target (gh#162).
entropic_error_t entropic_run_batch(entropic_handle_t handle, const char **tiers, const char **prompts, size_t n, char **result_json)
Same-prefix batch run on a shared resident model (gh#98).
entropic_error_t entropic_validation_set_enabled(entropic_handle_t handle, bool enabled)
Enable or disable constitutional validation globally.
entropic_error_t entropic_configure_from_file(entropic_handle_t handle, const char *config_path)
Configure the engine from a YAML config file.
static std::vector< std::vector< entropic::Message > > build_batch_messages(entropic_handle_t handle, const char **tiers, const char **prompts, size_t n, std::vector< std::string > &tiers_out)
Build per-request messages for entropic_run_batch (gh#98).
static void thread_frontmatter_samplers(entropic_handle_t h, const std::filesystem::path &data_dir)
Thread per-tier frontmatter SAMPLERS into config pre-orchestrator.
int entropic_adapter_state(entropic_handle_t handle, const char *adapter_name)
Query adapter lifecycle state.
static void rewire_critique_callbacks(entropic_handle_t h)
Propagate pre-configure critique callbacks to a newly- constructed ConstitutionalValidator (gh#50,...
int64_t entropic_seconds_since_last_activity(entropic_handle_t handle)
gh#35: idle-time accessor for host-side idle-exit policies.
entropic_error_t entropic_set_state_observer(entropic_handle_t handle, void(*observer)(int state, void *user_data), void *user_data)
Register a state-change observer on the handle.
static void init_engine_and_interfaces(entropic_handle_t h, const std::filesystem::path &data_dir)
Build the engine + inference interfaces (configure step 2).
static void wire_hooks_and_validator(entropic_handle_t h, entropic::InferenceInterface &iface, const std::string &constitution_text)
Wire hook dispatch and attach the constitutional validator.
entropic_error_t entropic_grant_mcp_key(entropic_handle_t handle, const char *identity_name, const char *pattern, entropic_mcp_access_level_t level)
Grant an MCP tool key to an identity.
entropic_error_t entropic_run_session(entropic_handle_t handle, const char *session_key, const char *input, char **result_json)
Run a turn on a named session (gh#144, v2.12.0).
static entropic_error_t do_adapter_load(entropic_handle_t handle, const char *adapter_name, const char *adapter_path, const char *base_model_path, float scale)
Body of entropic_adapter_load — resolve the tier, make its model resident, load the adapter against i...
static entropic::LoopConfig build_loop_config(entropic_handle_t h)
Build LoopConfig from parsed config.
static entropic_error_t check_orchestrator(entropic_handle_t h)
Check handle prerequisites for orchestrator APIs.
entropic_error_t entropic_context_count(entropic_handle_t handle, size_t *count)
Get conversation message count.
static void rewire_queue_observer(entropic_handle_t h)
Propagate any pre-configure queue observer to the new engine.
char * entropic_validation_last_result(entropic_handle_t handle)
Get last validation result as JSON.
static char * sp_get_validation(void *ud)
Return the validator's last verdict as JSON for ON_COMPLETE.
static std::vector< std::string > facade_unsafe_external_tools(const std::string &session_key, const std::vector< std::string > &allowed, void *ud)
External tools a sandboxed child could write through (gh#160).
char * entropic_grammar_validate(const char *gbnf_content)
Validate a GBNF grammar string without registering.
char * entropic_profile_list(entropic_handle_t handle)
List all registered profile names as a JSON array.
entropic_error_t entropic_session_list(entropic_handle_t handle, char **sessions_json)
List the sessions this handle holds (gh#144, v2.12.0).
entropic_error_t entropic_compute_perplexity(entropic_handle_t handle, const char *model_id, const int32_t *tokens, int n_tokens, float *perplexity)
Compute perplexity for a token sequence.
entropic_error_t entropic_grammar_register_file(entropic_handle_t handle, const char *key, const char *path)
Register a grammar from a GBNF file.
static entropic_error_t session_context_set_inner(entropic_handle_t handle, const std::string &key, const char *messages_json)
Parse, replace and invalidate for entropic_session_context_set.
static char * sp_get_config(void *ud)
State provider: get_config.
entropic_error_t entropic_speculative_compat(entropic_handle_t handle, int *compatible, char **diagnostic)
Query speculative-decoding compatibility for the configured target/draft pair.
entropic_error_t entropic_destroy_identity(entropic_handle_t handle, const char *name)
Destroy a dynamic identity.
static std::string serialize_batch_results(const std::vector< entropic::GenerationResult > &results)
Serialize batch results to a JSON array string (gh#98).
static char * sp_get_history(int max_entries, void *ud)
State provider: get_history — conversation context snapshot.
int entropic_check_mcp_key(entropic_handle_t handle, const char *identity_name, const char *tool_name, entropic_mcp_access_level_t level)
Check MCP key authorization for an identity.
entropic_error_t entropic_run(entropic_handle_t handle, const char *input, char **result_json)
Single-turn blocking agentic run.
static void rewire_stream_observer(entropic_handle_t h)
Propagate any pre-configure stream observer to the new engine.
entropic_error_t entropic_session_context_count(entropic_handle_t handle, const char *session_key, size_t *count)
Message count for one session (gh#144, v2.12.0).
char * entropic_adapter_info(entropic_handle_t handle, const char *adapter_name)
Get adapter info as JSON string.
static char * sp_get_tools(void *ud)
State provider: get_tools.
static entropic_error_t do_configure_from_file(entropic_handle_t handle, const char *config_path)
entropic_configure_from_file body — wrapped by c_api_try.
entropic_error_t entropic_configure(entropic_handle_t handle, const char *config_json)
Configure the engine from a JSON/YAML config string.
entropic_error_t entropic_profile_deregister(entropic_handle_t handle, const char *name)
Remove a GPU resource profile by name.
static void fill_logprob_result(const entropic::LogprobResult &lr, entropic_logprob_result_t *result)
Copy a LogprobResult into the caller's C struct.
entropic_error_t entropic_set_queue_observer(entropic_handle_t handle, void(*observer)(const char *, size_t, void *), void *user_data)
Register the queue-consumption observer.
static std::vector< entropic::Message > parse_and_check_vision(entropic_handle_t handle, const char *messages_json, entropic_error_t &out_rc)
Parse messages_json and check vision-tier availability (gh#37/gh#41).
static char * tool_history_json_thunk(size_t count, void *ud)
Wire the ToolExecutor and attach it to the engine.
static std::string build_assembled_prompt_for_tier(entropic_engine *h, const std::string &tier_name)
Build the assembled system prompt the engine would send for a given tier (constitution + app_context ...
static bool si_complete_delegation(const char *delegation_id, const char *status, const char *summary, void *user_data)
StorageInterface bridge: complete_delegation trampoline.
static bool read_state_file(const char *path, std::vector< uint8_t > &out_buf)
Load tier's KV cache from file body (gh#23 v2.3.25).
entropic_error_t entropic_user_message_queue_depth(entropic_handle_t handle, size_t *count)
Snapshot the mid-gen queue depth.
static entropic_error_t init_orchestrator(entropic_handle_t h, const std::filesystem::path &data_dir)
Shared body of all entropic_configure* entry points.
char * entropic_grammar_get(entropic_handle_t handle, const char *key)
Get grammar GBNF content by key.
char * entropic_list_identities(entropic_handle_t handle)
List all identity names as JSON array.
entropic_error_t entropic_context_get(entropic_handle_t handle, char **messages_json)
Get conversation as JSON array.
entropic_error_t entropic_state_save(entropic_handle_t handle, const char *tier_name, const char *path)
Save a tier's KV cache to a file (gh#23 v2.3.25, MVP item 13).
entropic_error_t entropic_run_as(entropic_handle_t handle, const char *tier_or_identity, const char *input, char **result_json)
Single-turn blocking run under a named tier (gh#99).
static void wire_prompts_and_persistence(entropic_handle_t h, const std::filesystem::path &data_dir)
Assemble prompts + wire validation/persistence (config step 3).
static entropic_error_t configure_common(entropic_handle_t h)
Shared body of all entropic_configure* entry points.
static void warn_tier_grammars_step(entropic_handle_t h, const std::filesystem::path &data_dir)
Warn about a tier grammar stem that resolves to nothing (gh#154).
entropic_error_t entropic_profile_register(entropic_handle_t handle, const char *profile_json)
Register a custom GPU resource profile from JSON.
char * entropic_serialize_mcp_keys(entropic_handle_t handle)
Serialize all identity key sets to JSON.
void entropic_free_logprob_result(entropic_logprob_result_t *result)
Free internal arrays of a logprob result.
entropic_error_t entropic_adapter_swap(entropic_handle_t handle, const char *adapter_name)
Swap active LoRA adapter.
static entropic_error_t run_messages_inner(entropic_handle_t handle, const char *messages_json, char **result_json)
Blocking multimodal run (gh#37, v2.1.8).
entropic_error_t entropic_set_delegation_callbacks(entropic_handle_t handle, ent_delegation_start_cb on_start, ent_delegation_complete_cb on_complete, void *user_data)
Register delegation start/complete callbacks (gh#29, v2.1.5).
entropic_error_t entropic_interrupt_session(entropic_handle_t handle, const char *session_key)
Interrupt one session's run — see entropic.h (gh#158, v2.13.0).
entropic_error_t entropic_release_model(entropic_handle_t handle, const char *tier_name)
Release a resident model, keeping conversations and registrations.
entropic_error_t entropic_interrupt(entropic_handle_t handle)
Interrupt a running generation (thread-safe).
static std::vector< std::string > collect_delegatable_tiers(const entropic::ParsedConfig &config)
Collect valid delegation targets from handoff_rules.
entropic_error_t entropic_session_context_clear(entropic_handle_t handle, const char *session_key)
Clear one session's history, leaving others intact (gh#144).
static void wire_session_roots(entropic_handle_t h)
Install the gh#160 session-root + dir-swap seams on the engine.
static std::vector< std::string > filter_tools(const nlohmann::json &all_tools, const std::vector< std::string > &allowed)
Filter tool definitions by allowed list.
int entropic_model_has_vision(entropic_handle_t handle, const char *model_id)
Check if a model has vision (multimodal) capability.
entropic_error_t entropic_get_diagnostic_prompt(entropic_handle_t handle, char **prompt_out)
Get diagnostic prompt text for /diagnose command (stub).
static void wire_external_interrupt(entropic_handle_t h)
Wire engine interrupt propagation into MCP transports (P1-10).
static entropic::StorageInterface build_storage_iface(entropic::SqliteStorageBackend *sb)
Build a populated StorageInterface bound to sb.
static void cache_tier_allowed_tools(entropic_handle_t h, const std::filesystem::path &data_dir)
Cache per-tier frontmatter fields from identity files.
entropic_error_t entropic_run_session_as(entropic_handle_t handle, const char *session_key, const char *tier_or_identity, const char *input, char **result_json)
Run a turn on a named session under a named tier (gh#144).
const char * entropic_last_error(entropic_handle_t handle)
Read the per-handle last_error under api_mutex.
entropic_error_t entropic_configure_dir(entropic_handle_t handle, const char *project_dir)
Configure using layered resolution (project dir).
entropic_error_t entropic_residency_snapshot(entropic_handle_t handle, char **out_json)
Return the engine's current residency-set snapshot as JSON.
entropic_error_t entropic_run_messages_streaming(entropic_handle_t handle, const char *messages_json, void(*on_token)(const char *token, size_t len, void *user_data), void *user_data, int *cancel_flag)
Streaming multimodal agentic run (gh#37, v2.1.8).
entropic_error_t entropic_context_clear(entropic_handle_t handle)
Clear conversation history.
static bool parse_restore_payload(entropic_handle_t handle, const char *messages_json, std::vector< entropic::Message > &out)
Parse a restore payload into messages (gh#165, v2.13.0).
static entropic_error_t run_session_streaming_impl(entropic_handle_t handle, const char *session_key, const char *tier, const char *input, void(*on_token)(const char *, size_t, void *), void *user_data, int *cancel_flag)
Streaming turn on a named session, optionally under a tier.
static char * sp_get_identities(void *ud)
State provider: get_identities.
entropic_error_t entropic_run_session_streaming_as(entropic_handle_t handle, const char *session_key, const char *tier_or_identity, const char *input, void(*on_token)(const char *token, size_t len, void *user_data), void *user_data, int *cancel_flag)
Streaming turn on a named session under a named tier (gh#205).
entropic_error_t entropic_create_identity(entropic_handle_t handle, const char *config_json)
Create a dynamic identity from JSON config.
entropic_error_t entropic_set_attempt_boundary_cb(entropic_handle_t handle, ent_validation_attempt_boundary_cb cb, void *user_data)
Register attempt-boundary callback on the validator.
int entropic_api_version(void)
Get the plugin API version number.
char * entropic_grammar_list(entropic_handle_t handle)
List all registered grammars as a JSON array.
static std::string tool_defs_array(const std::vector< std::string > &tool_jsons)
Re-parse filtered tool defs into one JSON array string.
static bool si_create_conversation(const char *title, std::string &conversation_id, void *user_data)
StorageInterface bridge: create_conversation trampoline.
const char * entropic_version(void)
Get the library version string.
static entropic_error_t do_state_save(entropic_handle_t handle, const char *tier_name, const char *path)
Save tier's KV cache to file body (gh#23 v2.3.25).
static entropic_error_t check_identity(entropic_handle_t h)
Check handle prerequisites for identity manager APIs.
static void wire_state_provider(entropic_handle_t h)
Wire state provider to the EntropicServer.
static int facade_get_tool_prompt(const char *tier, char **result, void *user_data)
Build formatted tool prompt for a tier.
entropic_error_t entropic_get_logprobs(entropic_handle_t handle, const char *model_id, const int32_t *tokens, int n_tokens, entropic_logprob_result_t *result)
Evaluate per-token log-probabilities for a token sequence.
static void wire_tier_validation_rules(entropic_handle_t h)
Pass per-identity validation rules to the validator.
static void wire_tool_executor(entropic_handle_t h)
Wire the ToolExecutor and attach it to the engine.
static entropic_error_t c_api_try(entropic_handle_t handle, Fn &&fn)
Run a C-API entry-point body inside an exception barrier.
entropic_error_t entropic_adapter_unload(entropic_handle_t handle, const char *adapter_name)
Unload a LoRA adapter.
entropic_error_t entropic_session_context_get(entropic_handle_t handle, const char *session_key, char **messages_json)
Read one session's conversation as JSON (gh#144, v2.12.0).
static bool si_save_snapshot(const char *conversation_id, const char *messages_json, void *user_data)
StorageInterface bridge: save_snapshot trampoline.
void * entropic_alloc(size_t size)
Allocate memory using the engine's allocator.
entropic_error_t entropic_clear_user_message_queue(entropic_handle_t handle)
Drop all queued mid-gen user messages.
static std::filesystem::path facade_session_root(const std::string &session_key, void *ud)
Root a session's MCP tools resolve against (gh#160).
entropic_error_t entropic_revoke_mcp_key(entropic_handle_t handle, const char *identity_name, const char *pattern)
Revoke an MCP tool key from an identity.
char * entropic_get_identity_config(entropic_handle_t handle, const char *name)
Get identity config as JSON by name.
static char * alloc_cstr(const char *src)
Allocate a C string copy via the engine allocator.
static bool si_load_delegation_with_messages(const char *delegation_id, std::string &result_json, void *user_data)
StorageInterface bridge: load_delegation_with_messages.
Public C API for the Entropic inference engine.
ent_decision_t(* ent_delegation_start_cb)(const ent_delegation_request_t *req, void *user_data)
Callback fired before a delegation runs.
ent_decision_t(* ent_delegation_complete_cb)(const ent_delegation_result_t *res, void *user_data)
Callback fired after a delegation produces a patch.
void(* entropic_residency_observer_t)(entropic_residency_event_t event, const char *tier_name, const char *model_path, size_t footprint_bytes, void *user_data)
Residency observer callback.
entropic_residency_event_t
Reasons fired by entropic_residency_observer_t.
entropic_mcp_access_level_t
Access level enum for MCP authorization.
void(* ent_validation_attempt_boundary_cb)(int attempt_n, void *user_data)
Stream-side callback fired between constitutional revision passes.
Entropic MCP server — engine-level tools including introspection.
entropic_error_t
Error codes returned by all C API functions.
@ ENTROPIC_ERROR_NO_VISION_TIER
Image content present but no vision-capable tier (v2.1.8, gh#41)
@ ENTROPIC_ERROR_ADAPTER_SWAP_FAILED
Swap failed (e.g., base model not ACTIVE) (v1.9.2)
@ ENTROPIC_ERROR_CANCELLED
Operation cancelled via cancel token.
@ ENTROPIC_ERROR_ALREADY_EXISTS
Named resource already exists (v1.9.6)
@ ENTROPIC_ERROR_INTERNAL
Unexpected internal error (bug)
@ ENTROPIC_ERROR_ALREADY_RUNNING
entropic_run already in progress on handle (v1.8.9)
@ ENTROPIC_ERROR_IDENTITY_NOT_FOUND
Identity name not in config (v1.8.9)
@ ENTROPIC_ERROR_NOT_RUNNING
Interrupt called but nothing running (v1.8.9)
@ ENTROPIC_ERROR_GRAMMAR_NOT_FOUND
Grammar key not in registry (v1.9.3)
@ ENTROPIC_ERROR_INVALID_ARGUMENT
NULL pointer, empty string, out-of-range value.
@ ENTROPIC_ERROR_QUEUE_FULL
Mid-gen user-message queue at capacity (v2.1.10, gh#40)
@ ENTROPIC_ERROR_INVALID_HANDLE
NULL or destroyed handle (v1.8.9)
@ ENTROPIC_ERROR_OUT_OF_MEMORY
Allocation failed (system RAM or VRAM)
@ ENTROPIC_ERROR_EVAL_FAILED
Evaluation failed (llama_decode error) (v1.9.10)
@ ENTROPIC_ERROR_ADAPTER_LOAD_FAILED
LoRA file invalid or incompatible with base model (v1.9.2)
@ ENTROPIC_ERROR_PROFILE_NOT_FOUND
Profile name not in registry (v1.9.7)
@ ENTROPIC_ERROR_IO
File/network I/O error.
@ ENTROPIC_ERROR_GENERATE_FAILED
Generation failed (context overflow, model error)
@ ENTROPIC_ERROR_INVALID_CONFIG
Config validation failed (missing fields, bad values)
@ ENTROPIC_ERROR_INVALID_STATE
Operation not valid in current state (e.g., generate before activate)
@ ENTROPIC_ERROR_LOAD_FAILED
Model load failed (corrupt file, OOM, unsupported format)
std::string err
size_exceeded, when set
int max_entries
<= 0 means unbounded
entropic_hook_point_t
Hook points in the engine lifecycle.
Pure C interface contract for inference backends.
void entropic_inference_log_silence(void)
Silence all llama/ggml log output.
Factory for building InferenceInterface from a ModelOrchestrator.
JSON serialization helpers for the facade.
LlamaCppBackend — llama.cpp C API integration.
Config loader — YAML to C++ structs with validation.
spdlog initialization and logger access.
ENTROPIC_EXPORT std::shared_ptr< spdlog::logger > get(const std::string &name)
Get or create a named logger.
Prompt manager — frontmatter parsing, identity loading, assembly.
Shared parser: messages-JSON wire format → vector<Message>.
bool any_message_has_images(const std::vector< Message > &messages)
Convenience: true if any message carries image content_parts.
void wire_external_server_policy(entropic_handle_t h, ServerManager &servers, bool with_declared)
Give a server set the handle's external-server policy (v2.14.0).
@ tokens
Gate on generated tokens since the last tool call.
@ off
Disabled (default) — no thinking-budget gating.
@ wall_clock
Gate on wall-clock seconds since the last tool call.
std::string serialize_tool_calls(const std::vector< ToolCall > &calls)
Serialize parsed tool calls to the C-ABI JSON array form.
@ passed_consumer_override
gh#30 (v2.1.5): consumer called accept_last() to override a paused rejection.
@ rejected_reverted_length
Revision gutted content >50%; original preserved.
@ passed
No violations, content unchanged.
@ revised
Violations found; revision applied.
@ paused_pending_consumer
gh#30 (v2.1.5): auto_retry disabled and a critique failed.
@ skipped
Validation did not run (skip_tiers / pure-tool-call / empty)
@ rejected_max_revisions
Revisions exhausted; last output returned as-is.
@ optional
optional: every escape asks the host's path approver
@ DYNAMIC
Created at runtime via API.
@ STATIC
Loaded from YAML frontmatter file at startup.
std::filesystem::path bridge_project_dir(entropic_handle_t h)
The project dir the external bridge derives its socket from.
void destroy_orchestrator_interface(InterfaceContext *context)
Free a context returned by build_orchestrator_interface().
ENTROPIC_EXPORT std::string current_run_session()
The session key of the run executing on this thread (gh#166).
std::vector< Message > parse_messages_json(const char *json_str)
Parse a JSON array of messages into a vector of Message.
MCPAccessLevel
MCP tool access level for per-identity authorization.
@ sandbox
Child tools run in a copy; output is a patch.
ENTROPIC_EXPORT void swap_session_tool_dir(const std::string &session_key, const std::filesystem::path &path, bool entering, void *ud)
The facade's gh#160 ScopedSandbox swap callback.
void wire_outside_root_approver(entropic_handle_t h)
Point the DEFAULT server set's filesystem server at the handle's path-approval slot (v2....
std::size_t release_session_tool_state(entropic_handle_t h, const std::string &key)
Release a session's per-session tool state on every server set (gh#158).
@ COLD
Not loaded. No resources consumed.
entropic::ServerManager * workspace_servers(entropic_handle_t h, const std::string &key)
The MCP servers a session's tools must run against (gh#166).
InferenceInterface build_orchestrator_interface(ModelOrchestrator *orchestrator, const std::string &default_tier, InterfaceContext **out_context)
Build an InferenceInterface wired to an orchestrator.
ModelOrchestrator — multi-model lifecycle and routing.
std::string config
–config FILE
Resolved tier information for building child delegation contexts.
int max_revisions
Max re-generation attempts (0 = critique only)
bool enabled
Global enable/disable (default OFF)
DelegationIsolation isolation
Default: none.
int http_port
Also serve the bridge over Streamable HTTP on 127.0.0.1:<port> (gh#204, v2.14.0).
bool enabled
Enable external MCP.
Named GPU resource profile for controlling inference hardware knobs.
int n_threads_batch
CPU threads for batch processing (0 = use n_threads)
int n_batch
Batch size for prompt processing (1-2048)
std::string name
Profile name ("maximum", "balanced", "background", "minimal")
int n_threads
CPU threads for generation (0 = auto-detect)
std::string description
Human-readable description.
int budget_limit
gh#80 (v2.5.0) budget ceiling: generated tokens (budget_mode "tokens") or wall-clock seconds (budget_...
std::string budget_mode
gh#80 (v2.5.0) thinking-budget mode: "off" (default), "tokens", or "wall_clock".
bool stream_output
gh#110 (v2.9.6) agent-loop token delivery mode: true streams tokens via the per-token callback path,...
Full identity configuration.
std::string name
Unique identity name (e.g., "eng", "npc_blacksmith")
std::vector< std::string > focus
Classification focus keywords (min 1)
IdentityOrigin origin
How this identity was created.
std::string system_prompt
Full system prompt text (markdown body)
Configuration for the identity manager.
SpeculativeConfig speculative
Speculative decoding (gh#36)
Per-token log-probability evaluation result.
std::vector< float > logprobs
Log-prob for each token transition (N-1 values)
int n_logprobs
Number of logprob values (n_tokens - 1)
int n_tokens
Number of input tokens.
float total_logprob
Sum of all logprob values.
float perplexity
exp(-mean(logprobs)) — lower = less surprising
std::vector< int32_t > tokens
Input tokens echoed back for verification.
Configuration for the agentic loop.
int budget_limit
Budget ceiling for the active budget_mode: generated tokens (mode tokens) or wall-clock seconds (mode...
int context_length
Context budget for compaction (v2.0.4)
bool stream_output
Stream vs batch generation.
bool auto_approve_tools
Skip tool approval (v1.8.5)
bool speculative_enabled
gh#110 (v2.9.6): mirrors inference.speculative.enabled from config, plumbed through since core....
BudgetMode budget_mode
Thinking-budget gating mode (gh#80, v2.5.0).
bool delegation_isolation
gh#160 (v2.13.0): mirrors delegation.isolation == sandbox.
Mutable state carried through the agentic loop.
ExternalMCPConfig external
External MCP server config (Entropic-as-server)
std::string working_dir
Server working directory (empty = CWD) (v2.0.4)
A message in a conversation.
std::string content
Message text content (always populated)
std::string role
Message role.
std::unordered_map< std::string, TierConfig > tiers
Tier name → config.
std::string find_tier_by_path(const std::filesystem::path &model_path) const
Find tier name by model path.
std::string default_tier
Default tier name.
Full parsed configuration.
PermissionsConfig permissions
Tool permissions.
DelegationConfig delegation
Delegation isolation (gh#160)
CompactionConfig compaction
Auto-compaction settings.
RoutingConfig routing
Routing rules.
InferenceConfig inference
Inference-side knobs (currently speculative decoding only).
bool concurrent_sessions
gh#158 (v2.13.0): may DIFFERENT session keys run together?
ModelsConfig models
Tiers + router.
ConstitutionalValidationConfig constitutional_validation
Constitutional validation pipeline settings.
std::filesystem::path log_dir
Session log directory (session.log + session_model.log).
GenerationConfig generation
Default generation params.
MCPConfig mcp
MCP server settings.
bool console_logging
Emit engine spdlog output to the stderr console sink.
bool auto_approve
Skip confirmation prompts.
std::unordered_map< std::string, std::vector< std::string > > handoff_rules
Tier handoff rules.
Where a session's tools live, and what it can reach (gh#160).
void * user_data
Opaque pointer (facade context)
std::filesystem::path(* resolve_root)(const std::string &session_key, void *user_data)
Root directory this session's MCP tools resolve against.
std::vector< std::string >(* unsafe_external_tools)(const std::string &session_key, const std::vector< std::string > &allowed_tools, void *user_data)
Child-visible EXTERNAL tools that are not declared read-only.
bool enabled
Master switch (off by default)
Storage interface for conversation persistence.
bool(* create_conversation)(const char *title, std::string &conversation_id, void *user_data)
Create a root conversation row.
Tier-specific model configuration.
std::optional< float > frequency_penalty
gh#85
std::optional< float > temperature
Per-tier sampler temperature from identity frontmatter (gh#82).
std::optional< float > top_p
Per-tier sampler knobs from identity frontmatter (gh#85).
std::optional< float > repeat_penalty
Per-tier repeat_penalty + enable_thinking from identity frontmatter (gh#86).
std::optional< float > min_p
gh#85
std::optional< float > presence_penalty
gh#85
std::optional< int > max_output_tokens
Per-tier max output tokens from identity frontmatter (gh#82).
std::optional< int > top_k
gh#85
std::optional< bool > enable_thinking
gh#86
std::optional< std::filesystem::path > grammar
Grammar file path.
Identity frontmatter — full tier identity metadata.
std::vector< std::string > validation_rules
Per-identity constitutional rules (v2.0.6)
std::optional< std::vector< std::string > > allowed_tools
Tool filter.
std::optional< float > top_p
Per-tier top_p (gh#85); nullopt = use param default.
std::optional< float > repeat_penalty
Per-tier repeat_penalty (gh#86); nullopt = use param default.
std::optional< float > min_p
Per-tier min_p (gh#85); nullopt = use param default.
std::optional< float > presence_penalty
Per-tier presence_penalty (gh#85); nullopt = use param default.
std::optional< bool > enable_thinking
Per-tier thinking mode (gh#86); nullopt = use param default.
std::optional< int > max_output_tokens
Per-tier max output tokens (gh#82); nullopt = use param default.
std::optional< int > top_k
Per-tier top_k (gh#85); nullopt = use param default.
bool relay_single_delegate
Skip re-synthesis when single delegate returns (v2.0.11)
std::optional< float > frequency_penalty
Per-tier frequency_penalty (gh#85); nullopt = use param default.
std::optional< std::string > grammar
Grammar file reference.
std::optional< float > temperature
Per-tier sampling temperature (gh#82); nullopt = use param default.
Parsed identity file: frontmatter + body.
Engine handle struct — owns all subsystems.
std::unique_ptr< entropic::ConstitutionalValidator > validator
Constitutional validation.
std::unique_ptr< entropic::ToolExecutor > tool_executor
Tool dispatch.
void(* critique_end_cb)(void *)
Fires after the critique generate returns.
int log_id
gh#59 (v2.3.1): unique handle id for per-handle log routing via entropic::log::HandleAwareSink.
std::mutex workspace_mutex
gh#166: guards both maps above. Held for lookups only.
std::map< std::string, std::unique_ptr< EntropicWorkspace > > workspaces
gh#166: named workspaces, by name.
std::unordered_map< std::string, std::vector< std::string > > tier_validation_rules
Per-tier validation_rules from identity frontmatter (v2.0.6).
std::unique_ptr< entropic::SqliteStorageBackend > storage
SQLite persistence.
entropic::InferenceInterface inference_iface
Stable copy for validator lifetime.
std::unique_ptr< entropic::http::HttpListener > http_listener
Streamable-HTTP front end for external_bridge (gh#204).
std::unique_ptr< entropic::SessionLogger > session_logger
Model transcript log.
std::unordered_map< std::string, std::vector< std::string > > tier_allowed_tools
Per-tier allowed_tools from identity frontmatter.
std::unique_ptr< entropic::CompactorRegistry > compactor_registry
Compaction strategies.
std::atomic< bool > configured
True after configure()
std::unique_ptr< entropic::ExternalBridge > external_bridge
Unix socket MCP bridge.
void(* state_observer)(int, void *)
Observer for engine state transitions.
entropic::config::BundledModels bundled_models
Model registry.
void * stream_observer_data
Observer user_data.
std::map< std::string, std::string > session_workspace
gh#166: session key → workspace name.
std::unique_ptr< entropic::IdentityManager > identity_manager
Identity lifecycle.
std::string last_error
Per-handle error message.
std::unique_ptr< entropic::AgentEngine > engine
Agentic loop (owns conversation state)
void * critique_cb_data
Forwarded to both callbacks.
std::unique_ptr< entropic::MCPAuthorizationManager > mcp_auth
Per-identity tool auth.
std::unique_ptr< entropic::ModelOrchestrator > orchestrator
Model pool + routing.
entropic::ParsedConfig config
Parsed config.
void(* stream_observer)(const char *, size_t, void *)
Global stream observer — fires for all streaming output.
void(* queue_observer)(const char *, size_t, void *)
Observer fired when a queued mid-gen user message is consumed and seeded as the next turn.
std::unique_ptr< entropic::ServerManager > server_manager
MCP server lifecycle.
entropic::InterfaceContext * inference_iface_ctx
Per-handle owned context backing inference_iface.user_data.
void(* critique_start_cb)(void *)
Fires before the constitutional validator's critique generate begins.
entropic::HookRegistry hook_registry
Hook dispatch.
Per-token log-probability result.
float perplexity
exp(-mean(logprobs)) over the sequence.
int32_t * tokens
Input tokens echoed back (N values).
int n_logprobs
Number of logprob values (n_tokens - 1).
int n_tokens
Number of input tokens.
float * logprobs
Per-token log-probabilities (N-1 values).
float total_logprob
Sum of all logprob values.
Read-only engine state provider for introspection tools.
char *(* get_config)(void *user_data)
Get current engine configuration as JSON.
UTF-8-boundary-aware string truncation helper for the facade.
Config validation functions.