138 lines
3.8 KiB
C
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;
|
|
}
|