comparison mrjunejune/main.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 04fee26ecce0
children e02e2036ef84
comparison
equal deleted inserted replaced
264:04fee26ecce0 265:056790c4fb0d
130 return byte_count; 130 return byte_count;
131 } 131 }
132 132
133 static void load_config(const char *config_path) 133 static void load_config(const char *config_path)
134 { 134 {
135 boolean config_loaded = FALSE;
135 FILE *f = fopen(config_path, "r"); 136 FILE *f = fopen(config_path, "r");
136 char workspace_config_path[1024] = {0}; 137 char workspace_config_path[1024] = {0};
137 if (!f) 138 if (!f)
138 { 139 {
139 const char *workspace = getenv("BUILD_WORKSPACE_DIRECTORY"); 140 const char *workspace = getenv("BUILD_WORKSPACE_DIRECTORY");
153 { 154 {
154 printf("[CONFIG] Warning: Could not open %s, using defaults\n", config_path); 155 printf("[CONFIG] Warning: Could not open %s, using defaults\n", config_path);
155 } 156 }
156 else 157 else
157 { 158 {
159 config_loaded = TRUE;
158 char line[512]; 160 char line[512];
159 while (fgets(line, sizeof(line), f)) 161 while (fgets(line, sizeof(line), f))
160 { 162 {
161 // Skip comments and empty lines 163 // Skip comments and empty lines
162 if (line[0] == '#' || line[0] == '\n' || line[0] == '\r') continue; 164 if (line[0] == '#' || line[0] == '\n' || line[0] == '\r') continue;
266 (strcmp(value, "1") == 0 || strcmp(value, "true") == 0); 268 (strcmp(value, "1") == 0 || strcmp(value, "true") == 0);
267 } 269 }
268 else if (strcmp(key, "SERVER_HOST") == 0) 270 else if (strcmp(key, "SERVER_HOST") == 0)
269 { 271 {
270 strncpy(g_server_host, value, sizeof(g_server_host) - 1); 272 strncpy(g_server_host, value, sizeof(g_server_host) - 1);
273 }
274 else if (strcmp(key, "MRJUNEJUNE_ALLOW_GUEST_INFERENCE") == 0)
275 {
276 if (strcmp(value, "1") == 0 || strcasecmp(value, "true") == 0)
277 g_guest_inference_enabled = TRUE;
278 else if (strcmp(value, "0") == 0 || strcasecmp(value, "false") == 0)
279 g_guest_inference_enabled = FALSE;
280 else
281 {
282 fprintf(
283 stderr,
284 "[CONFIG] ERROR: MRJUNEJUNE_ALLOW_GUEST_INFERENCE must be true or false\n");
285 exit(1);
286 }
271 } 287 }
272 else if (strcmp(key, "AUTH_GUEST_DAILY_TURNS") == 0) 288 else if (strcmp(key, "AUTH_GUEST_DAILY_TURNS") == 0)
273 { 289 {
274 int64 v; 290 int64 v;
275 if (!config__parse_int64_strict(value, &v) || 291 if (!config__parse_int64_strict(value, &v) ||
318 printf("[CONFIG] Auth: secret=%s, bootstrap_user=%s, trusted_proxy=%s\n", 334 printf("[CONFIG] Auth: secret=%s, bootstrap_user=%s, trusted_proxy=%s\n",
319 g_auth_cookie_secret[0] ? "(set)" : "(not set)", 335 g_auth_cookie_secret[0] ? "(set)" : "(not set)",
320 g_auth_bootstrap_username[0] ? g_auth_bootstrap_username : "(none)", 336 g_auth_bootstrap_username[0] ? g_auth_bootstrap_username : "(none)",
321 g_auth_trusted_proxy[0] ? "(set)" : "(not set)"); 337 g_auth_trusted_proxy[0] ? "(set)" : "(not set)");
322 338
323 const char *database_path_override = getenv("DB_PATH"); 339 const char *database_path_override = getenv("MRJUNEJUNE_DB_PATH");
324 const char *test_tmpdir = getenv("TEST_TMPDIR"); 340 const char *test_tmpdir = getenv("TEST_TMPDIR");
325 if (database_path_override && database_path_override[0] != '\0') 341 if (database_path_override && database_path_override[0] != '\0')
326 { 342 {
327 strncpy(g_db_path, database_path_override, sizeof(g_db_path) - 1); 343 strncpy(g_db_path, database_path_override, sizeof(g_db_path) - 1);
328 } 344 }
329 else if (test_tmpdir && test_tmpdir[0] != '\0') 345 else if (test_tmpdir && test_tmpdir[0] != '\0')
330 { 346 {
331 snprintf(g_db_path, sizeof(g_db_path), "%s/mrjunejune.db", test_tmpdir); 347 snprintf(g_db_path, sizeof(g_db_path), "%s/mrjunejune.db", test_tmpdir);
332 } 348 }
333 349
334 /* Environment overrides: env vars always take precedence over file. 350 /* Environment configuration is a compatibility/testing fallback only when
335 * Values are never logged. */ 351 * no config file is present. Dynamic supervisor wiring is read separately. */
352 if (!config_loaded)
336 { 353 {
337 const char *env; 354 const char *env;
338 355
339 /* S3 / server config env overrides */ 356 /* S3 / server config env overrides */
340 if ((env = getenv("UPLOAD_AUTH_TOKEN")) && env[0] != '\0') 357 if ((env = getenv("UPLOAD_AUTH_TOKEN")) && env[0] != '\0')
353 fprintf(stderr, "[CONFIG] ERROR: S3_URL_EXPIRES must be a positive integer\n"); 370 fprintf(stderr, "[CONFIG] ERROR: S3_URL_EXPIRES must be a positive integer\n");
354 exit(1); 371 exit(1);
355 } 372 }
356 g_s3_url_expires = (int)v; 373 g_s3_url_expires = (int)v;
357 } 374 }
358 if ((env = getenv("MRJUNEJUNE_DB_PATH")) && env[0] != '\0')
359 strncpy(g_db_path, env, sizeof(g_db_path) - 1);
360 if ((env = getenv("AWS_MRJUNEJUNE_ACCESS_KEY")) && env[0] != '\0') 375 if ((env = getenv("AWS_MRJUNEJUNE_ACCESS_KEY")) && env[0] != '\0')
361 strncpy(g_s3_access_key, env, sizeof(g_s3_access_key) - 1); 376 strncpy(g_s3_access_key, env, sizeof(g_s3_access_key) - 1);
362 if ((env = getenv("AWS_MRJUNEJUNE_SECRET_ACCESS_KEY")) && env[0] != '\0') 377 if ((env = getenv("AWS_MRJUNEJUNE_SECRET_ACCESS_KEY")) && env[0] != '\0')
363 strncpy(g_s3_secret_key, env, sizeof(g_s3_secret_key) - 1); 378 strncpy(g_s3_secret_key, env, sizeof(g_s3_secret_key) - 1);
364 379
2355 { 2370 {
2356 signal(SIGINT, handle_sigint); 2371 signal(SIGINT, handle_sigint);
2357 signal(SIGTERM, handle_sigint); 2372 signal(SIGTERM, handle_sigint);
2358 2373
2359 // Load the ignored runtime config when present; environment overrides follow. 2374 // Load the ignored runtime config when present; environment overrides follow.
2360 load_config("mrjunejune/.config"); 2375 const char *config_path = getenv("MRJUNEJUNE_CONFIG_PATH");
2376 load_config(
2377 config_path && config_path[0] != '\0'
2378 ? config_path
2379 : "mrjunejune/.config");
2361 2380
2362 // Initialize S3 config using global credentials populated by load_config 2381 // Initialize S3 config using global credentials populated by load_config
2363 g_s3_config.access_key_id = g_s3_access_key; 2382 g_s3_config.access_key_id = g_s3_access_key;
2364 g_s3_config.secret_access_key = g_s3_secret_key; 2383 g_s3_config.secret_access_key = g_s3_secret_key;
2365 g_s3_config.region = g_s3_region; 2384 g_s3_config.region = g_s3_region;