chore: remove dead code and fix unsafe patterns
- Remove unused context_build_messages() (superseded by direct cJSON in agent_loop) - Remove unused llm_chat() and its helper extract_text_* functions (superseded by llm_chat_tools) - Remove ota_manager.c from build (never called) - Remove config_screen.c stub from build (no-op module) - Remove unused PWR_KEY_State, Button_GPIO_Get_Level; drop config_screen dependency from button_driver - Fix incorrect type cast in tool_get_time.c (char[64] cast to char**) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,6 @@ idf_component_register(
|
|||||||
"imu/I2C_Driver.c"
|
"imu/I2C_Driver.c"
|
||||||
"imu/QMI8658.c"
|
"imu/QMI8658.c"
|
||||||
"imu/imu_manager.c"
|
"imu/imu_manager.c"
|
||||||
"ui/config_screen.c"
|
|
||||||
"bus/message_bus.c"
|
"bus/message_bus.c"
|
||||||
"wifi/wifi_manager.c"
|
"wifi/wifi_manager.c"
|
||||||
"telegram/telegram_bot.c"
|
"telegram/telegram_bot.c"
|
||||||
@@ -17,7 +16,6 @@ idf_component_register(
|
|||||||
"memory/session_mgr.c"
|
"memory/session_mgr.c"
|
||||||
"gateway/ws_server.c"
|
"gateway/ws_server.c"
|
||||||
"cli/serial_cli.c"
|
"cli/serial_cli.c"
|
||||||
"ota/ota_manager.c"
|
|
||||||
"proxy/http_proxy.c"
|
"proxy/http_proxy.c"
|
||||||
"cron/cron_service.c"
|
"cron/cron_service.c"
|
||||||
"heartbeat/heartbeat.c"
|
"heartbeat/heartbeat.c"
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "cJSON.h"
|
|
||||||
|
|
||||||
static const char *TAG = "context";
|
static const char *TAG = "context";
|
||||||
|
|
||||||
@@ -95,33 +94,3 @@ esp_err_t context_build_system_prompt(char *buf, size_t size)
|
|||||||
ESP_LOGI(TAG, "System prompt built: %d bytes", (int)off);
|
ESP_LOGI(TAG, "System prompt built: %d bytes", (int)off);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t context_build_messages(const char *history_json, const char *user_message,
|
|
||||||
char *buf, size_t size)
|
|
||||||
{
|
|
||||||
/* Parse existing history */
|
|
||||||
cJSON *history = cJSON_Parse(history_json);
|
|
||||||
if (!history) {
|
|
||||||
history = cJSON_CreateArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Append current user message */
|
|
||||||
cJSON *user_msg = cJSON_CreateObject();
|
|
||||||
cJSON_AddStringToObject(user_msg, "role", "user");
|
|
||||||
cJSON_AddStringToObject(user_msg, "content", user_message);
|
|
||||||
cJSON_AddItemToArray(history, user_msg);
|
|
||||||
|
|
||||||
/* Serialize */
|
|
||||||
char *json_str = cJSON_PrintUnformatted(history);
|
|
||||||
cJSON_Delete(history);
|
|
||||||
|
|
||||||
if (json_str) {
|
|
||||||
strncpy(buf, json_str, size - 1);
|
|
||||||
buf[size - 1] = '\0';
|
|
||||||
free(json_str);
|
|
||||||
} else {
|
|
||||||
snprintf(buf, size, "[{\"role\":\"user\",\"content\":\"%s\"}]", user_message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,14 +12,3 @@
|
|||||||
*/
|
*/
|
||||||
esp_err_t context_build_system_prompt(char *buf, size_t size);
|
esp_err_t context_build_system_prompt(char *buf, size_t size);
|
||||||
|
|
||||||
/**
|
|
||||||
* Build the complete messages JSON array for LLM call.
|
|
||||||
* Combines session history + current user message.
|
|
||||||
*
|
|
||||||
* @param history_json JSON array from session_get_history_json()
|
|
||||||
* @param user_message Current user message text
|
|
||||||
* @param buf Output buffer
|
|
||||||
* @param size Buffer size
|
|
||||||
*/
|
|
||||||
esp_err_t context_build_messages(const char *history_json, const char *user_message,
|
|
||||||
char *buf, size_t size);
|
|
||||||
|
|||||||
@@ -2,50 +2,41 @@
|
|||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "ui/config_screen.h"
|
|
||||||
|
|
||||||
void ESP32_Button_init(void){
|
static void ESP32_Button_init(void){
|
||||||
gpio_reset_pin(Button_PIN1);
|
gpio_reset_pin(Button_PIN1);
|
||||||
gpio_set_direction(Button_PIN1, GPIO_MODE_INPUT);
|
gpio_set_direction(Button_PIN1, GPIO_MODE_INPUT);
|
||||||
gpio_set_pull_mode(Button_PIN1, GPIO_PULLUP_ONLY);
|
gpio_set_pull_mode(Button_PIN1, GPIO_PULLUP_ONLY);
|
||||||
}
|
}
|
||||||
uint8_t Button_GPIO_Get_Level(int GPIO_PIN){
|
static void Timer_Callback(void *arg){
|
||||||
return (uint8_t)(gpio_get_level(GPIO_PIN));
|
button_ticks();
|
||||||
}
|
|
||||||
void Timer_Callback(void *arg){
|
|
||||||
button_ticks();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Button BUTTON1;
|
||||||
|
PressEvent BOOT_KEY_State;
|
||||||
struct Button BUTTON1;
|
static uint8_t Read_Button_GPIO_Level(uint8_t button_id)
|
||||||
PressEvent BOOT_KEY_State,PWR_KEY_State;
|
|
||||||
uint8_t Read_Button_GPIO_Level(uint8_t button_id)
|
|
||||||
{
|
{
|
||||||
if(!button_id)
|
if(!button_id)
|
||||||
return (uint8_t)(gpio_get_level(Button_PIN1));
|
return (uint8_t)(gpio_get_level(Button_PIN1));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void Button_SINGLE_CLICK_Callback(void* btn){
|
static void Button_SINGLE_CLICK_Callback(void* btn){
|
||||||
struct Button *user_button = (struct Button *)btn;
|
struct Button *user_button = (struct Button *)btn;
|
||||||
if(user_button == &BUTTON1){
|
if(user_button == &BUTTON1){
|
||||||
BOOT_KEY_State = SINGLE_CLICK;
|
BOOT_KEY_State = SINGLE_CLICK;
|
||||||
if (config_screen_is_active()) {
|
|
||||||
config_screen_scroll_down();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Button_DOUBLE_CLICK_Callback(void* btn){
|
static void Button_DOUBLE_CLICK_Callback(void* btn){
|
||||||
struct Button *user_button = (struct Button *)btn;
|
struct Button *user_button = (struct Button *)btn;
|
||||||
if(user_button == &BUTTON1){
|
if(user_button == &BUTTON1){
|
||||||
BOOT_KEY_State = DOUBLE_CLICK;
|
BOOT_KEY_State = DOUBLE_CLICK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Button_LONG_PRESS_START_Callback(void* btn){
|
static void Button_LONG_PRESS_START_Callback(void* btn){
|
||||||
struct Button *user_button = (struct Button *)btn;
|
struct Button *user_button = (struct Button *)btn;
|
||||||
if(user_button == &BUTTON1){
|
if(user_button == &BUTTON1){
|
||||||
BOOT_KEY_State= LONG_PRESS_START;
|
BOOT_KEY_State= LONG_PRESS_START;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void button_Init(void)
|
void button_Init(void)
|
||||||
|
|||||||
@@ -312,44 +312,6 @@ static esp_err_t llm_http_call(const char *post_data, resp_buf_t *rb, int *out_s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Parse text from JSON response ────────────────────────────── */
|
|
||||||
|
|
||||||
static void extract_text_anthropic(cJSON *root, char *buf, size_t size)
|
|
||||||
{
|
|
||||||
buf[0] = '\0';
|
|
||||||
cJSON *content = cJSON_GetObjectItem(root, "content");
|
|
||||||
if (!content || !cJSON_IsArray(content)) return;
|
|
||||||
|
|
||||||
size_t off = 0;
|
|
||||||
cJSON *block;
|
|
||||||
cJSON_ArrayForEach(block, content) {
|
|
||||||
cJSON *btype = cJSON_GetObjectItem(block, "type");
|
|
||||||
if (!btype || strcmp(btype->valuestring, "text") != 0) continue;
|
|
||||||
cJSON *text = cJSON_GetObjectItem(block, "text");
|
|
||||||
if (!text || !cJSON_IsString(text)) continue;
|
|
||||||
size_t tlen = strlen(text->valuestring);
|
|
||||||
size_t copy = (tlen < size - off - 1) ? tlen : size - off - 1;
|
|
||||||
memcpy(buf + off, text->valuestring, copy);
|
|
||||||
off += copy;
|
|
||||||
}
|
|
||||||
buf[off] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
static void extract_text_openai(cJSON *root, char *buf, size_t size)
|
|
||||||
{
|
|
||||||
buf[0] = '\0';
|
|
||||||
cJSON *choices = cJSON_GetObjectItem(root, "choices");
|
|
||||||
if (!choices || !cJSON_IsArray(choices)) return;
|
|
||||||
cJSON *choice0 = cJSON_GetArrayItem(choices, 0);
|
|
||||||
if (!choice0) return;
|
|
||||||
cJSON *message = cJSON_GetObjectItem(choice0, "message");
|
|
||||||
if (!message) return;
|
|
||||||
cJSON *content = cJSON_GetObjectItem(message, "content");
|
|
||||||
if (!content || !cJSON_IsString(content)) return;
|
|
||||||
strncpy(buf, content->valuestring, size - 1);
|
|
||||||
buf[size - 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
static cJSON *convert_tools_openai(const char *tools_json)
|
static cJSON *convert_tools_openai(const char *tools_json)
|
||||||
{
|
{
|
||||||
if (!tools_json) return NULL;
|
if (!tools_json) return NULL;
|
||||||
@@ -519,118 +481,6 @@ static cJSON *convert_messages_openai(const char *system_prompt, cJSON *messages
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Public: simple chat (backward compat) ────────────────────── */
|
|
||||||
|
|
||||||
esp_err_t llm_chat(const char *system_prompt, const char *messages_json,
|
|
||||||
char *response_buf, size_t buf_size)
|
|
||||||
{
|
|
||||||
if (s_api_key[0] == '\0') {
|
|
||||||
snprintf(response_buf, buf_size, "Error: No API key configured");
|
|
||||||
return ESP_ERR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build request body (non-streaming) */
|
|
||||||
cJSON *body = cJSON_CreateObject();
|
|
||||||
cJSON_AddStringToObject(body, "model", s_model);
|
|
||||||
if (provider_is_openai()) {
|
|
||||||
cJSON_AddNumberToObject(body, "max_completion_tokens", MIMI_LLM_MAX_TOKENS);
|
|
||||||
} else {
|
|
||||||
cJSON_AddNumberToObject(body, "max_tokens", MIMI_LLM_MAX_TOKENS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (provider_is_openai()) {
|
|
||||||
cJSON *messages = cJSON_Parse(messages_json);
|
|
||||||
if (!messages) {
|
|
||||||
messages = cJSON_CreateArray();
|
|
||||||
cJSON *msg = cJSON_CreateObject();
|
|
||||||
cJSON_AddStringToObject(msg, "role", "user");
|
|
||||||
cJSON_AddStringToObject(msg, "content", messages_json);
|
|
||||||
cJSON_AddItemToArray(messages, msg);
|
|
||||||
}
|
|
||||||
cJSON *openai_msgs = convert_messages_openai(system_prompt, messages);
|
|
||||||
cJSON_Delete(messages);
|
|
||||||
cJSON_AddItemToObject(body, "messages", openai_msgs);
|
|
||||||
} else {
|
|
||||||
cJSON_AddStringToObject(body, "system", system_prompt);
|
|
||||||
cJSON *messages = cJSON_Parse(messages_json);
|
|
||||||
if (messages) {
|
|
||||||
cJSON_AddItemToObject(body, "messages", messages);
|
|
||||||
} else {
|
|
||||||
cJSON *arr = cJSON_CreateArray();
|
|
||||||
cJSON *msg = cJSON_CreateObject();
|
|
||||||
cJSON_AddStringToObject(msg, "role", "user");
|
|
||||||
cJSON_AddStringToObject(msg, "content", messages_json);
|
|
||||||
cJSON_AddItemToArray(arr, msg);
|
|
||||||
cJSON_AddItemToObject(body, "messages", arr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *post_data = cJSON_PrintUnformatted(body);
|
|
||||||
cJSON_Delete(body);
|
|
||||||
if (!post_data) {
|
|
||||||
snprintf(response_buf, buf_size, "Error: Failed to build request");
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Calling LLM API (provider: %s, model: %s, body: %d bytes)",
|
|
||||||
s_provider, s_model, (int)strlen(post_data));
|
|
||||||
llm_log_payload("LLM request", post_data);
|
|
||||||
|
|
||||||
resp_buf_t rb;
|
|
||||||
if (resp_buf_init(&rb, MIMI_LLM_STREAM_BUF_SIZE) != ESP_OK) {
|
|
||||||
free(post_data);
|
|
||||||
snprintf(response_buf, buf_size, "Error: Out of memory");
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
int status = 0;
|
|
||||||
esp_err_t err = llm_http_call(post_data, &rb, &status);
|
|
||||||
free(post_data);
|
|
||||||
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "HTTP request failed: %s", esp_err_to_name(err));
|
|
||||||
llm_log_payload("LLM partial response", rb.data);
|
|
||||||
resp_buf_free(&rb);
|
|
||||||
snprintf(response_buf, buf_size, "Error: HTTP request failed (%s)",
|
|
||||||
esp_err_to_name(err));
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
llm_log_payload("LLM raw response", rb.data);
|
|
||||||
|
|
||||||
if (status != 200) {
|
|
||||||
ESP_LOGE(TAG, "API returned status %d", status);
|
|
||||||
snprintf(response_buf, buf_size, "API error (HTTP %d): %.200s",
|
|
||||||
status, rb.data ? rb.data : "");
|
|
||||||
resp_buf_free(&rb);
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse JSON response */
|
|
||||||
cJSON *root = cJSON_Parse(rb.data);
|
|
||||||
resp_buf_free(&rb);
|
|
||||||
|
|
||||||
if (!root) {
|
|
||||||
snprintf(response_buf, buf_size, "Error: Failed to parse response");
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (provider_is_openai()) {
|
|
||||||
extract_text_openai(root, response_buf, buf_size);
|
|
||||||
} else {
|
|
||||||
extract_text_anthropic(root, response_buf, buf_size);
|
|
||||||
}
|
|
||||||
cJSON_Delete(root);
|
|
||||||
|
|
||||||
if (response_buf[0] == '\0') {
|
|
||||||
snprintf(response_buf, buf_size, "No response from LLM API");
|
|
||||||
} else {
|
|
||||||
ESP_LOGI(TAG, "LLM response: %d bytes", (int)strlen(response_buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Public: chat with tools (non-streaming) ──────────────────── */
|
/* ── Public: chat with tools (non-streaming) ──────────────────── */
|
||||||
|
|
||||||
void llm_response_free(llm_response_t *resp)
|
void llm_response_free(llm_response_t *resp)
|
||||||
|
|||||||
@@ -27,18 +27,6 @@ esp_err_t llm_set_provider(const char *provider);
|
|||||||
*/
|
*/
|
||||||
esp_err_t llm_set_model(const char *model);
|
esp_err_t llm_set_model(const char *model);
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a chat completion request to the configured LLM API (non-streaming).
|
|
||||||
*
|
|
||||||
* @param system_prompt System prompt string
|
|
||||||
* @param messages_json JSON array of messages: [{"role":"user","content":"..."},...]
|
|
||||||
* @param response_buf Output buffer for the complete response text
|
|
||||||
* @param buf_size Size of response_buf
|
|
||||||
* @return ESP_OK on success
|
|
||||||
*/
|
|
||||||
esp_err_t llm_chat(const char *system_prompt, const char *messages_json,
|
|
||||||
char *response_buf, size_t buf_size);
|
|
||||||
|
|
||||||
/* ── Tool Use Support ──────────────────────────────────────────── */
|
/* ── Tool Use Support ──────────────────────────────────────────── */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -126,9 +126,6 @@ static esp_err_t fetch_time_direct(char *out, size_t out_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get Date header */
|
/* Get Date header */
|
||||||
char date_val[64] = {0};
|
|
||||||
err = esp_http_client_get_header(client, "Date", (char **)&date_val);
|
|
||||||
/* esp_http_client_get_header returns pointer, not copy */
|
|
||||||
char *date_ptr = NULL;
|
char *date_ptr = NULL;
|
||||||
esp_http_client_get_header(client, "Date", &date_ptr);
|
esp_http_client_get_header(client, "Date", &date_ptr);
|
||||||
esp_http_client_cleanup(client);
|
esp_http_client_cleanup(client);
|
||||||
|
|||||||
Reference in New Issue
Block a user