Files
didactyl/src/main.c
T

138 lines
3.8 KiB
C

#define _POSIX_C_SOURCE 200809L
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../../nostr_core_lib/nostr_core/nostr_core.h"
#include "main.h"
#include "agent.h"
#include "config.h"
#include "context.h"
#include "llm.h"
#include "nostr_handler.h"
#include "debug.h"
static volatile sig_atomic_t g_running = 1;
static void signal_handler(int signum) {
(void)signum;
g_running = 0;
}
int main(int argc, char** argv) {
const char* config_path = "./config.json";
const char* context_path = "./SYSTEM.md";
int debug_level = DEBUG_LEVEL_TRACE;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--config") == 0 && i + 1 < argc) {
config_path = argv[++i];
} else if (strcmp(argv[i], "--context") == 0 && i + 1 < argc) {
context_path = argv[++i];
} else if (strcmp(argv[i], "--debug") == 0 && i + 1 < argc) {
debug_level = atoi(argv[++i]);
} else {
fprintf(stderr, "Usage: %s [--config <path>] [--context <path>] [--debug <0-5>]\n", argv[0]);
return 1;
}
}
debug_init(debug_level);
DEBUG_INFO("%s %s starting", DIDACTYL_NAME, DIDACTYL_VERSION);
if (nostr_init() != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to initialize nostr core\n");
return 1;
}
didactyl_config_t cfg;
if (config_load(config_path, &cfg) != 0) {
fprintf(stderr, "Failed to load config: %s\n", config_path);
nostr_cleanup();
return 1;
}
char* system_context = context_load(context_path);
if (!system_context) {
fprintf(stderr, "Failed to load context file: %s\n", context_path);
config_free(&cfg);
nostr_cleanup();
return 1;
}
if (llm_init(&cfg.llm) != 0) {
fprintf(stderr, "Failed to initialize llm client\n");
context_free(system_context);
config_free(&cfg);
nostr_cleanup();
return 1;
}
if (nostr_handler_init(&cfg) != 0) {
fprintf(stderr, "Failed to initialize nostr handler\n");
llm_cleanup();
context_free(system_context);
config_free(&cfg);
nostr_cleanup();
return 1;
}
if (agent_init(&cfg, system_context) != 0) {
fprintf(stderr, "Failed to initialize agent\n");
nostr_handler_cleanup();
llm_cleanup();
context_free(system_context);
config_free(&cfg);
nostr_cleanup();
return 1;
}
DEBUG_INFO("[didactyl] startup phase: publish profile begin");
if (nostr_handler_publish_profile() != 0) {
DEBUG_WARN("[didactyl] publish profile deferred/failed (will continue startup)");
}
DEBUG_INFO("[didactyl] startup phase: publish profile end");
DEBUG_INFO("[didactyl] startup phase: subscribe DMs begin");
if (nostr_handler_subscribe_dms(agent_on_message, NULL) != 0) {
DEBUG_ERROR("[didactyl] startup phase: subscribe DMs failed");
fprintf(stderr, "Failed to subscribe to DMs\n");
agent_cleanup();
nostr_handler_cleanup();
llm_cleanup();
context_free(system_context);
config_free(&cfg);
nostr_cleanup();
return 1;
}
DEBUG_INFO("[didactyl] startup phase: subscribe DMs end");
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
DEBUG_INFO("[didactyl] entering main poll loop");
DEBUG_INFO("[didactyl] running with pubkey %s", cfg.keys.public_key_hex);
while (g_running) {
(void)nostr_handler_poll(100);
struct timespec ts = {0, 10 * 1000 * 1000};
nanosleep(&ts, NULL);
}
DEBUG_INFO("[didactyl] shutting down");
agent_cleanup();
nostr_handler_cleanup();
llm_cleanup();
context_free(system_context);
config_free(&cfg);
nostr_cleanup();
return 0;
}