fix cron/heartbeat e2e stability and build issues
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -45,5 +45,4 @@ nanobot/
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
references/
|
||||
references/
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "memory/session_mgr.h"
|
||||
#include "proxy/http_proxy.h"
|
||||
#include "tools/tool_web_search.h"
|
||||
#include "tools/tool_registry.h"
|
||||
#include "cron/cron_service.h"
|
||||
#include "heartbeat/heartbeat.h"
|
||||
|
||||
#include <string.h>
|
||||
@@ -329,6 +331,42 @@ static int cmd_heartbeat_trigger(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --- cron_start command --- */
|
||||
static int cmd_cron_start(int argc, char **argv)
|
||||
{
|
||||
esp_err_t err = cron_service_start();
|
||||
if (err == ESP_OK) {
|
||||
printf("Cron service started.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Failed to start cron service: %s\n", esp_err_to_name(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cmd_tool_exec(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf("Usage: tool_exec <name> [json]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *tool_name = argv[1];
|
||||
const char *input_json = (argc >= 3) ? argv[2] : "{}";
|
||||
|
||||
char *output = calloc(1, 4096);
|
||||
if (!output) {
|
||||
printf("Out of memory.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
esp_err_t err = tool_registry_execute(tool_name, input_json, output, 4096);
|
||||
printf("tool_exec status: %s\n", esp_err_to_name(err));
|
||||
printf("%s\n", output[0] ? output : "(empty)");
|
||||
free(output);
|
||||
return (err == ESP_OK) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* --- restart command --- */
|
||||
static int cmd_restart(int argc, char **argv)
|
||||
{
|
||||
@@ -526,6 +564,22 @@ esp_err_t serial_cli_init(void)
|
||||
};
|
||||
esp_console_cmd_register(&heartbeat_cmd);
|
||||
|
||||
/* cron_start */
|
||||
esp_console_cmd_t cron_start_cmd = {
|
||||
.command = "cron_start",
|
||||
.help = "Start cron scheduler timer now",
|
||||
.func = &cmd_cron_start,
|
||||
};
|
||||
esp_console_cmd_register(&cron_start_cmd);
|
||||
|
||||
/* tool_exec */
|
||||
esp_console_cmd_t tool_exec_cmd = {
|
||||
.command = "tool_exec",
|
||||
.help = "Execute a registered tool: tool_exec <name> '{...json...}'",
|
||||
.func = &cmd_tool_exec,
|
||||
};
|
||||
esp_console_cmd_register(&tool_exec_cmd);
|
||||
|
||||
/* restart */
|
||||
esp_console_cmd_t restart_cmd = {
|
||||
.command = "restart",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_random.h"
|
||||
#include "cJSON.h"
|
||||
@@ -18,7 +18,7 @@ static const char *TAG = "cron";
|
||||
|
||||
static cron_job_t s_jobs[MAX_CRON_JOBS];
|
||||
static int s_job_count = 0;
|
||||
static TimerHandle_t s_cron_timer = NULL;
|
||||
static TaskHandle_t s_cron_task = NULL;
|
||||
|
||||
/* ── Persistence ──────────────────────────────────────────────── */
|
||||
|
||||
@@ -199,17 +199,11 @@ static esp_err_t cron_save_jobs(void)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* ── Timer callback ───────────────────────────────────────────── */
|
||||
/* ── Due-job processing ───────────────────────────────────────── */
|
||||
|
||||
static void cron_timer_callback(TimerHandle_t xTimer)
|
||||
static void cron_process_due_jobs(void)
|
||||
{
|
||||
(void)xTimer;
|
||||
|
||||
time_t now = time(NULL);
|
||||
if (now < 1700000000) {
|
||||
/* System time not set yet (before ~2023), skip */
|
||||
return;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
|
||||
@@ -267,6 +261,16 @@ static void cron_timer_callback(TimerHandle_t xTimer)
|
||||
}
|
||||
}
|
||||
|
||||
static void cron_task_main(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
while (1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(MIMI_CRON_CHECK_INTERVAL_MS));
|
||||
cron_process_due_jobs();
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Compute initial next_run for a new job ───────────────────── */
|
||||
|
||||
static void compute_initial_next_run(cron_job_t *job)
|
||||
@@ -295,8 +299,8 @@ esp_err_t cron_service_init(void)
|
||||
|
||||
esp_err_t cron_service_start(void)
|
||||
{
|
||||
if (s_cron_timer) {
|
||||
ESP_LOGW(TAG, "Cron timer already running");
|
||||
if (s_cron_task) {
|
||||
ESP_LOGW(TAG, "Cron task already running");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -313,21 +317,16 @@ esp_err_t cron_service_start(void)
|
||||
}
|
||||
}
|
||||
|
||||
s_cron_timer = xTimerCreate(
|
||||
BaseType_t ok = xTaskCreate(
|
||||
cron_task_main,
|
||||
"cron",
|
||||
pdMS_TO_TICKS(MIMI_CRON_CHECK_INTERVAL_MS),
|
||||
pdTRUE, /* auto-reload */
|
||||
4096,
|
||||
NULL,
|
||||
cron_timer_callback
|
||||
4,
|
||||
&s_cron_task
|
||||
);
|
||||
|
||||
if (!s_cron_timer) {
|
||||
ESP_LOGE(TAG, "Failed to create cron timer");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (xTimerStart(s_cron_timer, pdMS_TO_TICKS(1000)) != pdPASS) {
|
||||
ESP_LOGE(TAG, "Failed to start cron timer");
|
||||
if (ok != pdPASS || !s_cron_task) {
|
||||
ESP_LOGE(TAG, "Failed to create cron task");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
@@ -338,10 +337,9 @@ esp_err_t cron_service_start(void)
|
||||
|
||||
void cron_service_stop(void)
|
||||
{
|
||||
if (s_cron_timer) {
|
||||
xTimerStop(s_cron_timer, pdMS_TO_TICKS(1000));
|
||||
xTimerDelete(s_cron_timer, pdMS_TO_TICKS(1000));
|
||||
s_cron_timer = NULL;
|
||||
if (s_cron_task) {
|
||||
vTaskDelete(s_cron_task);
|
||||
s_cron_task = NULL;
|
||||
ESP_LOGI(TAG, "Cron service stopped");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,13 @@
|
||||
|
||||
static const char *TAG = "llm";
|
||||
|
||||
static char s_api_key[128] = {0};
|
||||
static char s_model[64] = MIMI_LLM_DEFAULT_MODEL;
|
||||
static char s_provider[16] = MIMI_LLM_PROVIDER_DEFAULT;
|
||||
#define LLM_API_KEY_MAX_LEN 256
|
||||
#define LLM_MODEL_MAX_LEN 64
|
||||
#define LLM_PROVIDER_MAX_LEN 16
|
||||
|
||||
static char s_api_key[LLM_API_KEY_MAX_LEN] = {0};
|
||||
static char s_model[LLM_MODEL_MAX_LEN] = MIMI_LLM_DEFAULT_MODEL;
|
||||
static char s_provider[LLM_PROVIDER_MAX_LEN] = MIMI_LLM_PROVIDER_DEFAULT;
|
||||
|
||||
static void safe_copy(char *dst, size_t dst_size, const char *src)
|
||||
{
|
||||
@@ -118,20 +122,23 @@ esp_err_t llm_proxy_init(void)
|
||||
/* NVS overrides take highest priority (set via CLI) */
|
||||
nvs_handle_t nvs;
|
||||
if (nvs_open(MIMI_NVS_LLM, NVS_READONLY, &nvs) == ESP_OK) {
|
||||
char tmp[128] = {0};
|
||||
char tmp[LLM_API_KEY_MAX_LEN] = {0};
|
||||
size_t len = sizeof(tmp);
|
||||
if (nvs_get_str(nvs, MIMI_NVS_KEY_API_KEY, tmp, &len) == ESP_OK && tmp[0]) {
|
||||
safe_copy(s_api_key, sizeof(s_api_key), tmp);
|
||||
}
|
||||
len = sizeof(tmp);
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
if (nvs_get_str(nvs, MIMI_NVS_KEY_MODEL, tmp, &len) == ESP_OK && tmp[0]) {
|
||||
safe_copy(s_model, sizeof(s_model), tmp);
|
||||
}
|
||||
len = sizeof(tmp);
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
if (nvs_get_str(nvs, MIMI_NVS_KEY_PROVIDER, tmp, &len) == ESP_OK && tmp[0]) {
|
||||
safe_copy(s_provider, sizeof(s_provider), tmp);
|
||||
|
||||
char model_tmp[LLM_MODEL_MAX_LEN] = {0};
|
||||
len = sizeof(model_tmp);
|
||||
if (nvs_get_str(nvs, MIMI_NVS_KEY_MODEL, model_tmp, &len) == ESP_OK && model_tmp[0]) {
|
||||
safe_copy(s_model, sizeof(s_model), model_tmp);
|
||||
}
|
||||
|
||||
char provider_tmp[LLM_PROVIDER_MAX_LEN] = {0};
|
||||
len = sizeof(provider_tmp);
|
||||
if (nvs_get_str(nvs, MIMI_NVS_KEY_PROVIDER, provider_tmp, &len) == ESP_OK && provider_tmp[0]) {
|
||||
safe_copy(s_provider, sizeof(s_provider), provider_tmp);
|
||||
}
|
||||
nvs_close(nvs);
|
||||
}
|
||||
|
||||
@@ -170,17 +170,20 @@ esp_err_t tool_cron_remove_execute(const char *input_json, char *output, size_t
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t err = cron_remove_job(job_id);
|
||||
char job_id_copy[16] = {0};
|
||||
strncpy(job_id_copy, job_id, sizeof(job_id_copy) - 1);
|
||||
|
||||
esp_err_t err = cron_remove_job(job_id_copy);
|
||||
cJSON_Delete(root);
|
||||
|
||||
if (err == ESP_OK) {
|
||||
snprintf(output, output_size, "OK: Removed cron job %s", job_id);
|
||||
snprintf(output, output_size, "OK: Removed cron job %s", job_id_copy);
|
||||
} else if (err == ESP_ERR_NOT_FOUND) {
|
||||
snprintf(output, output_size, "Error: job '%s' not found", job_id);
|
||||
snprintf(output, output_size, "Error: job '%s' not found", job_id_copy);
|
||||
} else {
|
||||
snprintf(output, output_size, "Error: failed to remove job (%s)", esp_err_to_name(err));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "cron_remove: %s -> %s", job_id, esp_err_to_name(err));
|
||||
ESP_LOGI(TAG, "cron_remove: %s -> %s", job_id_copy, esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include "esp_log.h"
|
||||
|
||||
Reference in New Issue
Block a user