#include "serial_cli.h" #include "mimi_config.h" #include "wifi/wifi_manager.h" #include "telegram/telegram_bot.h" #include "llm/llm_proxy.h" #include "memory/memory_store.h" #include "memory/session_mgr.h" #include "proxy/http_proxy.h" #include #include #include "esp_log.h" #include "esp_console.h" #include "esp_system.h" #include "esp_heap_caps.h" #include "argtable3/argtable3.h" static const char *TAG = "cli"; /* --- wifi_set command --- */ static struct { struct arg_str *ssid; struct arg_str *password; struct arg_end *end; } wifi_set_args; static int cmd_wifi_set(int argc, char **argv) { int nerrors = arg_parse(argc, argv, (void **)&wifi_set_args); if (nerrors != 0) { arg_print_errors(stderr, wifi_set_args.end, argv[0]); return 1; } wifi_manager_set_credentials(wifi_set_args.ssid->sval[0], wifi_set_args.password->sval[0]); printf("WiFi credentials saved. Restart to apply.\n"); return 0; } /* --- wifi_status command --- */ static int cmd_wifi_status(int argc, char **argv) { printf("WiFi connected: %s\n", wifi_manager_is_connected() ? "yes" : "no"); printf("IP: %s\n", wifi_manager_get_ip()); return 0; } /* --- set_tg_token command --- */ static struct { struct arg_str *token; struct arg_end *end; } tg_token_args; static int cmd_set_tg_token(int argc, char **argv) { int nerrors = arg_parse(argc, argv, (void **)&tg_token_args); if (nerrors != 0) { arg_print_errors(stderr, tg_token_args.end, argv[0]); return 1; } telegram_set_token(tg_token_args.token->sval[0]); printf("Telegram bot token saved.\n"); return 0; } /* --- set_api_key command --- */ static struct { struct arg_str *key; struct arg_end *end; } api_key_args; static int cmd_set_api_key(int argc, char **argv) { int nerrors = arg_parse(argc, argv, (void **)&api_key_args); if (nerrors != 0) { arg_print_errors(stderr, api_key_args.end, argv[0]); return 1; } llm_set_api_key(api_key_args.key->sval[0]); printf("API key saved.\n"); return 0; } /* --- set_model command --- */ static struct { struct arg_str *model; struct arg_end *end; } model_args; static int cmd_set_model(int argc, char **argv) { int nerrors = arg_parse(argc, argv, (void **)&model_args); if (nerrors != 0) { arg_print_errors(stderr, model_args.end, argv[0]); return 1; } llm_set_model(model_args.model->sval[0]); printf("Model set.\n"); return 0; } /* --- memory_read command --- */ static int cmd_memory_read(int argc, char **argv) { char *buf = malloc(4096); if (!buf) { printf("Out of memory.\n"); return 1; } if (memory_read_long_term(buf, 4096) == ESP_OK && buf[0]) { printf("=== MEMORY.md ===\n%s\n=================\n", buf); } else { printf("MEMORY.md is empty or not found.\n"); } free(buf); return 0; } /* --- memory_write command --- */ static struct { struct arg_str *content; struct arg_end *end; } memory_write_args; static int cmd_memory_write(int argc, char **argv) { int nerrors = arg_parse(argc, argv, (void **)&memory_write_args); if (nerrors != 0) { arg_print_errors(stderr, memory_write_args.end, argv[0]); return 1; } memory_write_long_term(memory_write_args.content->sval[0]); printf("MEMORY.md updated.\n"); return 0; } /* --- session_list command --- */ static int cmd_session_list(int argc, char **argv) { printf("Sessions:\n"); session_list(); return 0; } /* --- session_clear command --- */ static struct { struct arg_str *chat_id; struct arg_end *end; } session_clear_args; static int cmd_session_clear(int argc, char **argv) { int nerrors = arg_parse(argc, argv, (void **)&session_clear_args); if (nerrors != 0) { arg_print_errors(stderr, session_clear_args.end, argv[0]); return 1; } if (session_clear(session_clear_args.chat_id->sval[0]) == ESP_OK) { printf("Session cleared.\n"); } else { printf("Session not found.\n"); } return 0; } /* --- heap_info command --- */ static int cmd_heap_info(int argc, char **argv) { printf("Internal free: %d bytes\n", (int)heap_caps_get_free_size(MALLOC_CAP_INTERNAL)); printf("PSRAM free: %d bytes\n", (int)heap_caps_get_free_size(MALLOC_CAP_SPIRAM)); printf("Total free: %d bytes\n", (int)esp_get_free_heap_size()); return 0; } /* --- set_proxy command --- */ static struct { struct arg_str *host; struct arg_int *port; struct arg_end *end; } proxy_args; static int cmd_set_proxy(int argc, char **argv) { int nerrors = arg_parse(argc, argv, (void **)&proxy_args); if (nerrors != 0) { arg_print_errors(stderr, proxy_args.end, argv[0]); return 1; } http_proxy_set(proxy_args.host->sval[0], (uint16_t)proxy_args.port->ival[0]); printf("Proxy set. Restart to apply.\n"); return 0; } /* --- clear_proxy command --- */ static int cmd_clear_proxy(int argc, char **argv) { http_proxy_clear(); printf("Proxy cleared. Restart to apply.\n"); return 0; } /* --- restart command --- */ static int cmd_restart(int argc, char **argv) { printf("Restarting...\n"); esp_restart(); return 0; /* unreachable */ } esp_err_t serial_cli_init(void) { esp_console_repl_t *repl = NULL; esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); repl_config.prompt = "mimi> "; repl_config.max_cmdline_length = 256; /* USB Serial JTAG */ esp_console_dev_usb_serial_jtag_config_t hw_config = ESP_CONSOLE_DEV_USB_SERIAL_JTAG_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_console_new_repl_usb_serial_jtag(&hw_config, &repl_config, &repl)); /* Register commands */ /* wifi_set */ wifi_set_args.ssid = arg_str1(NULL, NULL, "", "WiFi SSID"); wifi_set_args.password = arg_str1(NULL, NULL, "", "WiFi password"); wifi_set_args.end = arg_end(2); esp_console_cmd_t wifi_set_cmd = { .command = "wifi_set", .help = "Set WiFi SSID and password", .func = &cmd_wifi_set, .argtable = &wifi_set_args, }; esp_console_cmd_register(&wifi_set_cmd); /* wifi_status */ esp_console_cmd_t wifi_status_cmd = { .command = "wifi_status", .help = "Show WiFi connection status", .func = &cmd_wifi_status, }; esp_console_cmd_register(&wifi_status_cmd); /* set_tg_token */ tg_token_args.token = arg_str1(NULL, NULL, "", "Telegram bot token"); tg_token_args.end = arg_end(1); esp_console_cmd_t tg_token_cmd = { .command = "set_tg_token", .help = "Set Telegram bot token", .func = &cmd_set_tg_token, .argtable = &tg_token_args, }; esp_console_cmd_register(&tg_token_cmd); /* set_api_key */ api_key_args.key = arg_str1(NULL, NULL, "", "Anthropic API key"); api_key_args.end = arg_end(1); esp_console_cmd_t api_key_cmd = { .command = "set_api_key", .help = "Set Claude API key", .func = &cmd_set_api_key, .argtable = &api_key_args, }; esp_console_cmd_register(&api_key_cmd); /* set_model */ model_args.model = arg_str1(NULL, NULL, "", "Model identifier"); model_args.end = arg_end(1); esp_console_cmd_t model_cmd = { .command = "set_model", .help = "Set LLM model (default: " MIMI_LLM_DEFAULT_MODEL ")", .func = &cmd_set_model, .argtable = &model_args, }; esp_console_cmd_register(&model_cmd); /* memory_read */ esp_console_cmd_t mem_read_cmd = { .command = "memory_read", .help = "Read MEMORY.md", .func = &cmd_memory_read, }; esp_console_cmd_register(&mem_read_cmd); /* memory_write */ memory_write_args.content = arg_str1(NULL, NULL, "", "Content to write"); memory_write_args.end = arg_end(1); esp_console_cmd_t mem_write_cmd = { .command = "memory_write", .help = "Write to MEMORY.md", .func = &cmd_memory_write, .argtable = &memory_write_args, }; esp_console_cmd_register(&mem_write_cmd); /* session_list */ esp_console_cmd_t sess_list_cmd = { .command = "session_list", .help = "List all sessions", .func = &cmd_session_list, }; esp_console_cmd_register(&sess_list_cmd); /* session_clear */ session_clear_args.chat_id = arg_str1(NULL, NULL, "", "Chat ID to clear"); session_clear_args.end = arg_end(1); esp_console_cmd_t sess_clear_cmd = { .command = "session_clear", .help = "Clear a session", .func = &cmd_session_clear, .argtable = &session_clear_args, }; esp_console_cmd_register(&sess_clear_cmd); /* heap_info */ esp_console_cmd_t heap_cmd = { .command = "heap_info", .help = "Show heap memory usage", .func = &cmd_heap_info, }; esp_console_cmd_register(&heap_cmd); /* set_proxy */ proxy_args.host = arg_str1(NULL, NULL, "", "Proxy host/IP"); proxy_args.port = arg_int1(NULL, NULL, "", "Proxy port"); proxy_args.end = arg_end(2); esp_console_cmd_t proxy_cmd = { .command = "set_proxy", .help = "Set HTTP proxy (e.g. set_proxy 192.168.1.83 7897)", .func = &cmd_set_proxy, .argtable = &proxy_args, }; esp_console_cmd_register(&proxy_cmd); /* clear_proxy */ esp_console_cmd_t clear_proxy_cmd = { .command = "clear_proxy", .help = "Remove proxy configuration", .func = &cmd_clear_proxy, }; esp_console_cmd_register(&clear_proxy_cmd); /* restart */ esp_console_cmd_t restart_cmd = { .command = "restart", .help = "Restart the device", .func = &cmd_restart, }; esp_console_cmd_register(&restart_cmd); /* Start REPL */ ESP_ERROR_CHECK(esp_console_start_repl(repl)); ESP_LOGI(TAG, "Serial CLI started"); return ESP_OK; }