Mercurial
diff mrjunejune/inference_bridge.c @ 265:056790c4fb0d
add role-aware Epi assistant prompts
Add verified June knowledge, guest/member/admin Copilot profiles, profile-isolated session recovery, animated Epi greetings, and a single authoritative runtime config workflow for inference.
Co-authored-by: Copilot <[email protected]>
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Fri, 07 Aug 2026 10:50:30 -0700 |
| parents | b401627fc49e |
| children |
line wrap: on
line diff
--- a/mrjunejune/inference_bridge.c Fri Aug 07 07:34:12 2026 -0700 +++ b/mrjunejune/inference_bridge.c Fri Aug 07 10:50:30 2026 -0700 @@ -187,19 +187,38 @@ return success; } +static const char *Inference_Bridge_Profile_Name( + Inference_Prompt_Profile profile) +{ + switch (profile) + { + case INFERENCE_PROMPT_PROFILE_PUBLIC_VISITOR: + return "public_visitor"; + case INFERENCE_PROMPT_PROFILE_INVITED_FRIEND: + return "invited_friend"; + case INFERENCE_PROMPT_PROFILE_JUNE_ADMIN: + return "june_admin"; + } + return NULL; +} + static boolean Inference_Bridge_Command( Inference_Bridge *p_bridge, const char *command, const char *request_id, const char *conversation_id, - const char *prompt) + const char *prompt, + const char *prompt_profile, + uint32 prompt_version, + uint32 knowledge_version) { if (!command || !request_id) return FALSE; size_t input_length = strlen(command) + strlen(request_id) + strlen(conversation_id ? conversation_id : "") + - strlen(prompt ? prompt : ""); + strlen(prompt ? prompt : "") + + strlen(prompt_profile ? prompt_profile : ""); if (input_length > (((size_t)-1) - 4096) / 12) return FALSE; Dowa_Arena *p_arena = Dowa_Arena_Create(input_length * 12 + 4096); @@ -212,8 +231,12 @@ char *escaped_prompt = prompt ? Dowa_JSON_Escape_String(prompt, 0, p_arena) : NULL; + char *escaped_profile = prompt_profile + ? Dowa_JSON_Escape_String(prompt_profile, 0, p_arena) + : NULL; if (!escaped_command || !escaped_request || !escaped_conversation || - (prompt && !escaped_prompt)) + (prompt && !escaped_prompt) || + (prompt_profile && !escaped_profile)) { Dowa_Arena_Free(p_arena); return FALSE; @@ -221,24 +244,30 @@ size_t capacity = strlen(escaped_command) + strlen(escaped_request) + strlen(escaped_conversation) + - (escaped_prompt ? strlen(escaped_prompt) : 0) + 160; + (escaped_prompt ? strlen(escaped_prompt) : 0) + + (escaped_profile ? strlen(escaped_profile) : 0) + 256; char *payload = Dowa_Arena_Allocate(p_arena, capacity); if (!payload) { Dowa_Arena_Free(p_arena); return FALSE; } - if (escaped_prompt) + if (escaped_prompt && escaped_profile) { snprintf( payload, capacity, "{\"command\":\"%s\",\"request_id\":\"%s\"," - "\"conversation_id\":\"%s\",\"prompt\":\"%s\"}", + "\"conversation_id\":\"%s\",\"prompt\":\"%s\"," + "\"prompt_profile\":\"%s\",\"prompt_version\":%u," + "\"knowledge_version\":%u}", escaped_command, escaped_request, escaped_conversation, - escaped_prompt); + escaped_prompt, + escaped_profile, + prompt_version, + knowledge_version); } else { @@ -304,7 +333,7 @@ return; if (atomic_load(&p_bridge->running) && p_bridge->p_commands) Inference_Bridge_Command( - p_bridge, "shutdown", "server-shutdown", "", NULL); + p_bridge, "shutdown", "server-shutdown", "", NULL, NULL, 0, 0); if (p_bridge->p_commands) { fclose(p_bridge->p_commands); @@ -465,10 +494,152 @@ Inference_Bridge *p_bridge, const char *request_id, const char *conversation_id, - const char *prompt) + const char *prompt, + Inference_Prompt_Profile prompt_profile, + uint32 prompt_version, + uint32 knowledge_version, + const Inference_Bridge_History_Message *p_history, + uint32 history_count) { - return Inference_Bridge_Command( - p_bridge, "turn.start", request_id, conversation_id, prompt); + const char *profile_name = Inference_Bridge_Profile_Name(prompt_profile); + if (!profile_name || prompt_version == 0 || knowledge_version == 0) + return FALSE; + if (history_count > INFERENCE_BRIDGE_HISTORY_MAX) + return FALSE; + /* Validate every history entry before touching the wire. */ + for (uint32 i = 0; i < history_count; i++) + { + const Inference_Bridge_History_Message *m = &p_history[i]; + if (!m->role || !m->content) + return FALSE; + if (strcmp(m->role, "user") != 0 && strcmp(m->role, "assistant") != 0) + return FALSE; + } + + if (!request_id) + return FALSE; + + /* Compute raw byte total to size the arena (12x expansion factor). */ + size_t input_length = + strlen("turn.start") + strlen(request_id) + + strlen(conversation_id ? conversation_id : "") + + strlen(prompt ? prompt : "") + + strlen(profile_name); + for (uint32 i = 0; i < history_count; i++) + { + input_length += strlen(p_history[i].role) + strlen(p_history[i].content); + } + if (input_length > (((size_t)-1) - 4096) / 12) + return FALSE; + + Dowa_Arena *p_arena = Dowa_Arena_Create(input_length * 12 + 4096); + if (!p_arena) + return FALSE; + + char *escaped_command = Dowa_JSON_Escape_String("turn.start", 0, p_arena); + char *escaped_request = Dowa_JSON_Escape_String(request_id, 0, p_arena); + char *escaped_conversation = Dowa_JSON_Escape_String( + conversation_id ? conversation_id : "", 0, p_arena); + char *escaped_prompt = prompt + ? Dowa_JSON_Escape_String(prompt, 0, p_arena) + : NULL; + char *escaped_profile = Dowa_JSON_Escape_String(profile_name, 0, p_arena); + + if (!escaped_command || !escaped_request || !escaped_conversation || + (prompt && !escaped_prompt) || !escaped_profile) + { + Dowa_Arena_Free(p_arena); + return FALSE; + } + + /* Escape history roles and contents. */ + char *escaped_hist_role[INFERENCE_BRIDGE_HISTORY_MAX]; + char *escaped_hist_content[INFERENCE_BRIDGE_HISTORY_MAX]; + for (uint32 i = 0; i < history_count; i++) + { + escaped_hist_role[i] = + Dowa_JSON_Escape_String(p_history[i].role, 0, p_arena); + escaped_hist_content[i] = + Dowa_JSON_Escape_String(p_history[i].content, 0, p_arena); + if (!escaped_hist_role[i] || !escaped_hist_content[i]) + { + Dowa_Arena_Free(p_arena); + return FALSE; + } + } + + /* Compute payload capacity. */ + size_t capacity = + strlen(escaped_command) + strlen(escaped_request) + + strlen(escaped_conversation) + + (escaped_prompt ? strlen(escaped_prompt) : 0) + + strlen(escaped_profile) + 256; + for (uint32 i = 0; i < history_count; i++) + { + capacity += + strlen(escaped_hist_role[i]) + strlen(escaped_hist_content[i]) + 32; + } + + char *payload = Dowa_Arena_Allocate(p_arena, capacity); + if (!payload) + { + Dowa_Arena_Free(p_arena); + return FALSE; + } + + /* Write the base turn.start fields. */ + int written = snprintf( + payload, + capacity, + "{\"command\":\"%s\",\"request_id\":\"%s\"," + "\"conversation_id\":\"%s\",\"prompt\":\"%s\"," + "\"prompt_profile\":\"%s\",\"prompt_version\":%u," + "\"knowledge_version\":%u,\"history\":[", + escaped_command, + escaped_request, + escaped_conversation, + escaped_prompt ? escaped_prompt : "", + escaped_profile, + prompt_version, + knowledge_version); + if (written <= 0 || (size_t)written >= capacity) + { + Dowa_Arena_Free(p_arena); + return FALSE; + } + size_t offset = (size_t)written; + + /* Append history entries. */ + for (uint32 i = 0; i < history_count; i++) + { + int entry_written = snprintf( + payload + offset, + capacity - offset, + "%s{\"role\":\"%s\",\"content\":\"%s\"}", + i == 0 ? "" : ",", + escaped_hist_role[i], + escaped_hist_content[i]); + if (entry_written <= 0 || offset + (size_t)entry_written >= capacity) + { + Dowa_Arena_Free(p_arena); + return FALSE; + } + offset += (size_t)entry_written; + } + + /* Close the history array and the outer object. */ + if (offset + 2 >= capacity) + { + Dowa_Arena_Free(p_arena); + return FALSE; + } + payload[offset++] = ']'; + payload[offset++] = '}'; + payload[offset] = '\0'; + + boolean success = Inference_Bridge_Write(p_bridge, payload); + Dowa_Arena_Free(p_arena); + return success; } boolean Inference_Bridge_Abort_Turn( @@ -477,7 +648,7 @@ const char *conversation_id) { return Inference_Bridge_Command( - p_bridge, "turn.abort", request_id, conversation_id, NULL); + p_bridge, "turn.abort", request_id, conversation_id, NULL, NULL, 0, 0); } boolean Inference_Bridge_Delete_Conversation( @@ -486,7 +657,14 @@ const char *conversation_id) { return Inference_Bridge_Command( - p_bridge, "conversation.delete", request_id, conversation_id, NULL); + p_bridge, + "conversation.delete", + request_id, + conversation_id, + NULL, + NULL, + 0, + 0); } void Inference_Bridge_Destroy(Inference_Bridge *p_bridge)