comparison mrjunejune/test/inference_bridge_fake_sidecar.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
comparison
equal deleted inserted replaced
264:04fee26ecce0 265:056790c4fb0d
6 6
7 static const char *Get_String(Dowa_JSON_Entry *object, const char *key) 7 static const char *Get_String(Dowa_JSON_Entry *object, const char *key)
8 { 8 {
9 char *value = Dowa_JSON_Get_String(object, key); 9 char *value = Dowa_JSON_Get_String(object, key);
10 return value ? value : ""; 10 return value ? value : "";
11 }
12
13 /* Validates the optional "history" array from a turn.start command.
14 * Returns TRUE if history is absent, null, or structurally valid (<=20
15 * entries, each an object with role user/assistant and string content).
16 * Returns FALSE and sets *error_out on any violation. */
17 static boolean Validate_History(
18 Dowa_JSON_Entry *object,
19 Dowa_Arena *p_arena,
20 const char **error_out)
21 {
22 (void)p_arena;
23 *error_out = NULL;
24 Dowa_JSON_Value *hist_val = Dowa_JSON_Get(object, "history");
25 if (!hist_val || hist_val->type == DOWA_JSON_NULL)
26 return TRUE;
27 if (hist_val->type != DOWA_JSON_ARRAY)
28 {
29 *error_out = "history must be a list";
30 return FALSE;
31 }
32 size_t count = Dowa_Array_Length(hist_val->array_val);
33 if (count > 20)
34 {
35 *error_out = "history must not exceed 20 entries";
36 return FALSE;
37 }
38 for (size_t i = 0; i < count; i++)
39 {
40 Dowa_JSON_Value *v = &hist_val->array_val[i];
41 if (v->type != DOWA_JSON_OBJECT)
42 {
43 *error_out = "each history entry must be an object";
44 return FALSE;
45 }
46 Dowa_JSON_Entry *entry = v->object_val;
47 Dowa_JSON_Value *role_val = Dowa_JSON_Get(entry, "role");
48 Dowa_JSON_Value *content_val = Dowa_JSON_Get(entry, "content");
49 if (!role_val || role_val->type != DOWA_JSON_STRING)
50 {
51 *error_out = "history role must be a string";
52 return FALSE;
53 }
54 if (!content_val || content_val->type != DOWA_JSON_STRING)
55 {
56 *error_out = "history content must be a string";
57 return FALSE;
58 }
59 const char *role = role_val->str_val;
60 if (!role ||
61 (strcmp(role, "user") != 0 && strcmp(role, "assistant") != 0))
62 {
63 *error_out = "history role must be user or assistant";
64 return FALSE;
65 }
66 }
67 return TRUE;
11 } 68 }
12 69
13 int main(void) 70 int main(void)
14 { 71 {
15 printf( 72 printf(
43 Dowa_Arena_Free(p_arena); 100 Dowa_Arena_Free(p_arena);
44 break; 101 break;
45 } 102 }
46 if (strcmp(command, "turn.start") == 0) 103 if (strcmp(command, "turn.start") == 0)
47 { 104 {
105 /* Validate history before any other processing. */
106 const char *hist_error = NULL;
107 if (!Validate_History(object, p_arena, &hist_error))
108 {
109 printf(
110 "{\"type\":\"turn.error\",\"request_id\":\"%s\","
111 "\"conversation_id\":\"%s\","
112 "\"error\":{\"code\":\"invalid_history\","
113 "\"message\":\"%s\"}}\n",
114 request_id,
115 conversation_id,
116 hist_error);
117 printf(
118 "{\"type\":\"turn.done\",\"request_id\":\"%s\","
119 "\"conversation_id\":\"%s\",\"failed\":true}\n",
120 request_id,
121 conversation_id);
122 fflush(stdout);
123 Dowa_Arena_Free(p_arena);
124 continue;
125 }
126
127 const char *prompt_profile = Get_String(object, "prompt_profile");
128 double prompt_version = Dowa_JSON_Get_Number(object, "prompt_version");
129 double knowledge_version =
130 Dowa_JSON_Get_Number(object, "knowledge_version");
131 boolean known_profile =
132 strcmp(prompt_profile, "public_visitor") == 0 ||
133 strcmp(prompt_profile, "invited_friend") == 0 ||
134 strcmp(prompt_profile, "june_admin") == 0;
135 if (!known_profile || prompt_version != 1 || knowledge_version != 1)
136 {
137 printf(
138 "{\"type\":\"turn.error\",\"request_id\":\"%s\","
139 "\"conversation_id\":\"%s\","
140 "\"error\":{\"code\":\"invalid_prompt_profile\","
141 "\"message\":\"prompt profile is required\"}}\n",
142 request_id,
143 conversation_id);
144 printf(
145 "{\"type\":\"turn.done\",\"request_id\":\"%s\","
146 "\"conversation_id\":\"%s\",\"failed\":true}\n",
147 request_id,
148 conversation_id);
149 fflush(stdout);
150 Dowa_Arena_Free(p_arena);
151 continue;
152 }
48 printf( 153 printf(
49 "{\"type\":\"turn.accepted\",\"request_id\":\"%s\"," 154 "{\"type\":\"turn.accepted\",\"request_id\":\"%s\","
50 "\"conversation_id\":\"%s\"}\n", 155 "\"conversation_id\":\"%s\"}\n",
51 request_id, 156 request_id,
52 conversation_id); 157 conversation_id);
53 printf( 158 printf(
54 "{\"type\":\"tool.started\",\"request_id\":\"%s\"," 159 "{\"type\":\"tool.started\",\"request_id\":\"%s\","
55 "\"conversation_id\":\"%s\"," 160 "\"conversation_id\":\"%s\","
56 "\"tool\":{\"name\":\"mock-search\"}}\n", 161 "\"tool\":{\"name\":\"mock-search\","
162 "\"prompt_profile\":\"%s\"}}\n",
57 request_id, 163 request_id,
58 conversation_id); 164 conversation_id,
165 prompt_profile);
59 printf( 166 printf(
60 "{\"type\":\"assistant.delta\",\"request_id\":\"%s\"," 167 "{\"type\":\"assistant.delta\",\"request_id\":\"%s\","
61 "\"conversation_id\":\"%s\"," 168 "\"conversation_id\":\"%s\","
62 "\"delta\":\"hello \\\"traveler\\\"\\\\path\"}\n", 169 "\"delta\":\"hello \\\"traveler\\\"\\\\path\"}\n",
63 request_id, 170 request_id,