refactor: remove NVS/CLI config, use mimi_secrets.h as sole configuration method
All configuration is now done exclusively through mimi_secrets.h at build time. Removed NVS read/write logic, CLI config commands (wifi_set, set_tg_token, set_api_key, set_model, set_proxy, clear_proxy, set_search_key), and setter functions from all modules. CLI retains debug/maintenance commands only. Updated all documentation to reflect the change. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
35
README.md
35
README.md
@@ -66,7 +66,7 @@ idf.py set-target esp32s3
|
||||
|
||||
### Configure
|
||||
|
||||
**Option A: Config file (recommended)** — fill in once, baked into firmware at build time:
|
||||
All configuration is done through `mimi_secrets.h` at build time:
|
||||
|
||||
```bash
|
||||
cp main/mimi_secrets.h.example main/mimi_secrets.h
|
||||
@@ -91,39 +91,16 @@ idf.py build
|
||||
idf.py -p /dev/ttyACM0 flash monitor
|
||||
```
|
||||
|
||||
Config file values have the **highest priority** — they override anything set via CLI.
|
||||
|
||||
> **Note:** After editing `mimi_secrets.h`, run `touch main/mimi_config.h` before `idf.py build` to force recompilation.
|
||||
|
||||
**Option B: Serial CLI** — configure at runtime after flashing:
|
||||
|
||||
```bash
|
||||
idf.py build
|
||||
idf.py -p /dev/ttyACM0 flash monitor
|
||||
```
|
||||
|
||||
```
|
||||
mimi> wifi_set YourWiFiName YourWiFiPassword
|
||||
mimi> set_tg_token 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
|
||||
mimi> set_api_key sk-ant-api03-xxxxx
|
||||
mimi> set_search_key BSA-xxxxx # optional: Brave Search API key for web_search
|
||||
mimi> restart
|
||||
```
|
||||
|
||||
CLI values are stored in NVS (persistent flash) and used when no config file value is set.
|
||||
> **Important:** After editing `mimi_secrets.h`, you must do a full rebuild: `idf.py fullclean && idf.py build`
|
||||
|
||||
### CLI Commands
|
||||
|
||||
The serial CLI provides debug and maintenance commands:
|
||||
|
||||
```
|
||||
mimi> wifi_set <ssid> <pass> # set WiFi credentials
|
||||
mimi> wifi_status # am I connected?
|
||||
mimi> set_tg_token <token> # set Telegram bot token
|
||||
mimi> set_api_key <key> # set Anthropic API key
|
||||
mimi> set_model claude-opus-4-6 # use a different model
|
||||
mimi> set_search_key <key> # set Brave Search API key (for web_search tool)
|
||||
mimi> set_proxy 10.0.0.1 7897 # route through HTTP proxy
|
||||
mimi> clear_proxy # remove proxy, connect directly
|
||||
mimi> memory_read # see what the bot remembers
|
||||
mimi> memory_write "content" # write to MEMORY.md
|
||||
mimi> heap_info # how much RAM is free?
|
||||
mimi> session_list # list all chat sessions
|
||||
mimi> session_clear 12345 # wipe a conversation
|
||||
@@ -151,7 +128,7 @@ MimiClaw uses Anthropic's tool use protocol — Claude can call tools during a c
|
||||
| `web_search` | Search the web via Brave Search API for current information |
|
||||
| `get_current_time` | Fetch current date/time via HTTP and set the system clock |
|
||||
|
||||
To enable web search, set a [Brave Search API key](https://brave.com/search/api/) in your config file or via CLI (`set_search_key`).
|
||||
To enable web search, set a [Brave Search API key](https://brave.com/search/api/) via `MIMI_SECRET_SEARCH_KEY` in `mimi_secrets.h`.
|
||||
|
||||
## Also Included
|
||||
|
||||
|
||||
51
README_CN.md
51
README_CN.md
@@ -66,7 +66,7 @@ idf.py set-target esp32s3
|
||||
|
||||
### 配置
|
||||
|
||||
**方式 A:配置文件(推荐)** — 填一次,编译时写入固件:
|
||||
所有配置通过 `mimi_secrets.h` 在编译时写入:
|
||||
|
||||
```bash
|
||||
cp main/mimi_secrets.h.example main/mimi_secrets.h
|
||||
@@ -91,26 +91,7 @@ idf.py build
|
||||
idf.py -p /dev/ttyACM0 flash monitor
|
||||
```
|
||||
|
||||
配置文件的值**优先级最高** — 会覆盖 CLI 设置的值。
|
||||
|
||||
> **注意**:修改 `mimi_secrets.h` 后,需要先执行 `touch main/mimi_config.h` 再 `idf.py build`,否则不会重新编译。
|
||||
|
||||
**方式 B:串口命令行** — 烧录后在运行时配置:
|
||||
|
||||
```bash
|
||||
idf.py build
|
||||
idf.py -p /dev/ttyACM0 flash monitor
|
||||
```
|
||||
|
||||
```
|
||||
mimi> wifi_set 你的WiFi名 你的WiFi密码
|
||||
mimi> set_tg_token 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
|
||||
mimi> set_api_key sk-ant-api03-xxxxx
|
||||
mimi> set_search_key BSA-xxxxx # 可选:Brave Search API key,启用网页搜索
|
||||
mimi> restart
|
||||
```
|
||||
|
||||
CLI 设置的值存在 NVS(持久 Flash)中,仅在配置文件未设置对应值时生效。
|
||||
> **重要**:修改 `mimi_secrets.h` 后必须完整重编译:`idf.py fullclean && idf.py build`
|
||||
|
||||
### 代理配置(国内用户)
|
||||
|
||||
@@ -118,34 +99,18 @@ CLI 设置的值存在 NVS(持久 Flash)中,仅在配置文件未设置对
|
||||
|
||||
**前提**:局域网内有一个支持 HTTP CONNECT 的代理(Clash Verge、V2Ray 等),并开启了「允许局域网连接」。
|
||||
|
||||
推荐直接在 `mimi_secrets.h` 中配置代理(见上方方式 A),也可以用命令行:
|
||||
|
||||
```
|
||||
mimi> set_proxy 10.0.0.1 7897
|
||||
mimi> restart
|
||||
```
|
||||
|
||||
清除代理恢复直连:
|
||||
|
||||
```
|
||||
mimi> clear_proxy
|
||||
mimi> restart
|
||||
```
|
||||
在 `mimi_secrets.h` 中设置 `MIMI_SECRET_PROXY_HOST` 和 `MIMI_SECRET_PROXY_PORT`。清除代理只需把这两项改回空字符串 `""`,然后重新编译。
|
||||
|
||||
> **提示**:确保 ESP32-S3 和代理机器在同一局域网。Clash Verge 在「设置 → 允许局域网」中开启。
|
||||
|
||||
### 所有命令
|
||||
### CLI 命令
|
||||
|
||||
串口 CLI 提供调试和运维命令:
|
||||
|
||||
```
|
||||
mimi> wifi_set <ssid> <pass> # 设置 WiFi
|
||||
mimi> wifi_status # 连上了吗?
|
||||
mimi> set_tg_token <token> # 设置 Telegram Bot Token
|
||||
mimi> set_api_key <key> # 设置 Anthropic API Key
|
||||
mimi> set_model claude-opus-4-6 # 换个模型
|
||||
mimi> set_search_key <key> # 设置 Brave Search API Key(web_search 工具用)
|
||||
mimi> set_proxy 10.0.0.1 7897 # 通过 HTTP 代理
|
||||
mimi> clear_proxy # 清除代理,直连
|
||||
mimi> memory_read # 看看它记住了什么
|
||||
mimi> memory_write "内容" # 写入 MEMORY.md
|
||||
mimi> heap_info # 还剩多少内存?
|
||||
mimi> session_list # 列出所有会话
|
||||
mimi> session_clear 12345 # 删除一个会话
|
||||
@@ -173,7 +138,7 @@ MimiClaw 使用 Anthropic 的 tool use 协议 — Claude 在对话中可以调
|
||||
| `web_search` | 通过 Brave Search API 搜索网页,获取实时信息 |
|
||||
| `get_current_time` | 通过 HTTP 获取当前日期和时间,并设置系统时钟 |
|
||||
|
||||
启用网页搜索需要设置 [Brave Search API key](https://brave.com/search/api/),在配置文件或 CLI(`set_search_key`)中设置。
|
||||
启用网页搜索需要在 `mimi_secrets.h` 中设置 [Brave Search API key](https://brave.com/search/api/)(`MIMI_SECRET_SEARCH_KEY`)。
|
||||
|
||||
## 其他功能
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ main/
|
||||
│
|
||||
├── wifi/
|
||||
│ ├── wifi_manager.h WiFi STA lifecycle API
|
||||
│ └── wifi_manager.c NVS credentials, event handler, exponential backoff
|
||||
│ └── wifi_manager.c Event handler, exponential backoff
|
||||
│
|
||||
├── telegram/
|
||||
│ ├── telegram_bot.h Bot init/start, send_message API
|
||||
@@ -144,7 +144,7 @@ main/
|
||||
│
|
||||
├── cli/
|
||||
│ ├── serial_cli.h CLI init API
|
||||
│ └── serial_cli.c esp_console REPL with 15 commands
|
||||
│ └── serial_cli.c esp_console REPL with debug/maintenance commands
|
||||
│
|
||||
└── ota/
|
||||
├── ota_manager.h OTA update API
|
||||
@@ -190,7 +190,7 @@ Large buffers (32 KB+) are allocated from PSRAM via `heap_caps_calloc(1, size, M
|
||||
```
|
||||
Offset Size Name Purpose
|
||||
─────────────────────────────────────────────
|
||||
0x009000 24 KB nvs WiFi creds, TG token, API key, model
|
||||
0x009000 24 KB nvs ESP-IDF internal use (WiFi calibration etc.)
|
||||
0x00F000 8 KB otadata OTA boot state
|
||||
0x011000 4 KB phy_init WiFi PHY calibration
|
||||
0x020000 2 MB ota_0 Firmware slot A
|
||||
@@ -223,22 +223,22 @@ Session files are JSONL (one JSON object per line):
|
||||
|
||||
---
|
||||
|
||||
## NVS Configuration
|
||||
## Configuration
|
||||
|
||||
| Namespace | Key | Description |
|
||||
|-----------------|--------------|-----------------------------------------|
|
||||
| `wifi_config` | `ssid` | WiFi SSID |
|
||||
| `wifi_config` | `password` | WiFi password |
|
||||
| `tg_config` | `bot_token` | Telegram Bot API token |
|
||||
| `llm_config` | `api_key` | Anthropic API key |
|
||||
| `llm_config` | `model` | Model ID (default: claude-opus-4-6) |
|
||||
| `proxy_config` | `host` | HTTP proxy hostname/IP |
|
||||
| `proxy_config` | `port` | HTTP proxy port |
|
||||
| `search_config` | `api_key` | Brave Search API key |
|
||||
All configuration is done exclusively through `mimi_secrets.h` at build time. There is no runtime configuration — changing any setting requires `idf.py fullclean && idf.py build`.
|
||||
|
||||
**Configuration priority**: `mimi_secrets.h` (build-time) > NVS (CLI-set) > defaults.
|
||||
| Define | Description |
|
||||
|------------------------------|-----------------------------------------|
|
||||
| `MIMI_SECRET_WIFI_SSID` | WiFi SSID |
|
||||
| `MIMI_SECRET_WIFI_PASS` | WiFi password |
|
||||
| `MIMI_SECRET_TG_TOKEN` | Telegram Bot API token |
|
||||
| `MIMI_SECRET_API_KEY` | Anthropic API key |
|
||||
| `MIMI_SECRET_MODEL` | Model ID (default: claude-opus-4-6) |
|
||||
| `MIMI_SECRET_PROXY_HOST` | HTTP proxy hostname/IP (optional) |
|
||||
| `MIMI_SECRET_PROXY_PORT` | HTTP proxy port (optional) |
|
||||
| `MIMI_SECRET_SEARCH_KEY` | Brave Search API key (optional) |
|
||||
|
||||
All configurable via Serial CLI or build-time config file (`mimi_secrets.h`).
|
||||
NVS is still initialized (required by ESP-IDF WiFi internals) but is not used for application configuration.
|
||||
|
||||
---
|
||||
|
||||
@@ -340,14 +340,14 @@ app_main()
|
||||
├── memory_store_init() Verify SPIFFS paths
|
||||
├── session_mgr_init()
|
||||
├── wifi_manager_init() Init WiFi STA mode + event handlers
|
||||
├── http_proxy_init() Load proxy config (secrets > NVS)
|
||||
├── telegram_bot_init() Load bot token (secrets > NVS)
|
||||
├── llm_proxy_init() Load API key + model (secrets > NVS)
|
||||
├── http_proxy_init() Load proxy config from build-time secrets
|
||||
├── telegram_bot_init() Load bot token from build-time secrets
|
||||
├── llm_proxy_init() Load API key + model from build-time secrets
|
||||
├── tool_registry_init() Register tools, build tools JSON
|
||||
├── agent_loop_init()
|
||||
├── serial_cli_init() Start REPL (works without WiFi)
|
||||
│
|
||||
├── wifi_manager_start() Connect (secrets > NVS credentials)
|
||||
├── wifi_manager_start() Connect using build-time credentials
|
||||
│ └── wifi_manager_wait_connected(30s)
|
||||
│
|
||||
└── [if WiFi connected]
|
||||
@@ -357,22 +357,17 @@ app_main()
|
||||
└── outbound_dispatch task Launch outbound task (Core 0)
|
||||
```
|
||||
|
||||
If WiFi credentials are missing or connection times out, the CLI remains available for configuration.
|
||||
If WiFi credentials are missing or connection times out, the CLI remains available for diagnostics.
|
||||
|
||||
---
|
||||
|
||||
## Serial CLI Commands
|
||||
|
||||
The CLI provides debug and maintenance commands only. All configuration is done via `mimi_secrets.h`.
|
||||
|
||||
| Command | Description |
|
||||
|--------------------------------|--------------------------------------|
|
||||
| `wifi_set <SSID> <PASSWORD>` | Save WiFi credentials to NVS |
|
||||
| `wifi_status` | Show connection status and IP |
|
||||
| `set_tg_token <TOKEN>` | Save Telegram bot token |
|
||||
| `set_api_key <KEY>` | Save Anthropic API key |
|
||||
| `set_model <MODEL_ID>` | Set LLM model identifier |
|
||||
| `set_search_key <KEY>` | Save Brave Search API key |
|
||||
| `set_proxy <HOST> <PORT>` | Set HTTP CONNECT proxy |
|
||||
| `clear_proxy` | Remove proxy, use direct connection |
|
||||
| `memory_read` | Print MEMORY.md contents |
|
||||
| `memory_write <CONTENT>` | Overwrite MEMORY.md |
|
||||
| `session_list` | List all session files |
|
||||
@@ -381,8 +376,6 @@ If WiFi credentials are missing or connection times out, the CLI remains availab
|
||||
| `restart` | Reboot the device |
|
||||
| `help` | List all available commands |
|
||||
|
||||
> **Note**: CLI-set values are stored in NVS but are overridden by `mimi_secrets.h` build-time values if set.
|
||||
|
||||
---
|
||||
|
||||
## Nanobot Reference Mapping
|
||||
@@ -396,7 +389,7 @@ If WiFi credentials are missing or connection times out, the CLI remains availab
|
||||
| `channels/telegram.py` | `telegram/telegram_bot.c` | Raw HTTP, no python-telegram-bot |
|
||||
| `bus/events.py` + `queue.py`| `bus/message_bus.c` | FreeRTOS queues vs asyncio |
|
||||
| `providers/litellm_provider.py` | `llm/llm_proxy.c` | Direct Anthropic API only |
|
||||
| `config/schema.py` | `mimi_config.h` + `mimi_secrets.h` + NVS | Build-time secrets > NVS |
|
||||
| `config/schema.py` | `mimi_config.h` + `mimi_secrets.h` | Build-time secrets only |
|
||||
| `cli/commands.py` | `cli/serial_cli.c` | esp_console REPL |
|
||||
| `agent/tools/*` | `tools/tool_registry.c` + `tool_web_search.c` | web_search via Brave API |
|
||||
| `agent/subagent.py` | *(not yet implemented)* | See TODO.md |
|
||||
|
||||
13
docs/TODO.md
13
docs/TODO.md
@@ -36,7 +36,7 @@
|
||||
### [ ] Telegram User Allowlist (allow_from)
|
||||
- **nanobot**: `channels/base.py` L59-82 — `is_allowed()` checks sender_id against allow_list
|
||||
- **MimiClaw**: No authentication; anyone can message the bot and consume API credits
|
||||
- **Recommendation**: Store allow_from list in NVS, filter in `process_updates()`
|
||||
- **Recommendation**: Store allow_from list in `mimi_secrets.h` as a build-time define, filter in `process_updates()`
|
||||
|
||||
### [ ] Telegram Markdown to HTML Conversion
|
||||
- **nanobot**: `channels/telegram.py` L16-76 — `_markdown_to_telegram_html()` full converter: code blocks, inline code, bold, italic, links, strikethrough, lists
|
||||
@@ -105,7 +105,7 @@
|
||||
- **Recommendation**: Requires extra HTTPS request to Whisper API: download Telegram voice -> forward -> get text
|
||||
|
||||
### [x] ~~Build-time Config File~~
|
||||
- Implemented: `mimi_secrets.h` — build-time credentials with highest priority over NVS/CLI
|
||||
- Implemented: `mimi_secrets.h` — sole configuration method (build-time only, no NVS/CLI)
|
||||
- Replaces need for YAML config; suitable for MCU workflow
|
||||
|
||||
### [ ] WebSocket Gateway Protocol Enhancement
|
||||
@@ -124,7 +124,7 @@
|
||||
- **Recommendation**: Low priority, Telegram is sufficient
|
||||
|
||||
### [x] ~~Telegram Proxy Support (HTTP CONNECT)~~
|
||||
- Implemented: HTTP CONNECT tunnel via `proxy/http_proxy.c`, configurable via NVS + CLI (`set_proxy`/`clear_proxy`)
|
||||
- Implemented: HTTP CONNECT tunnel via `proxy/http_proxy.c`, configurable via `mimi_secrets.h` (`MIMI_SECRET_PROXY_HOST`/`MIMI_SECRET_PROXY_PORT`)
|
||||
|
||||
### [ ] Session Metadata Persistence
|
||||
- **nanobot**: `session/manager.py` L136-153 — session file includes metadata line (created_at, updated_at)
|
||||
@@ -144,13 +144,12 @@
|
||||
- [x] Memory Store (MEMORY.md + daily notes)
|
||||
- [x] Session Manager (JSONL per chat_id, ring buffer history)
|
||||
- [x] WebSocket Gateway (port 18789, JSON protocol)
|
||||
- [x] Serial CLI (esp_console, 15 commands)
|
||||
- [x] Serial CLI (esp_console, debug/maintenance commands)
|
||||
- [x] HTTP CONNECT Proxy (Telegram + Claude API + Brave Search via proxy tunnel)
|
||||
- [x] OTA Update
|
||||
- [x] WiFi Manager (NVS credentials, exponential backoff)
|
||||
- [x] WiFi Manager (build-time credentials, exponential backoff)
|
||||
- [x] SPIFFS storage
|
||||
- [x] Build-time config (`mimi_secrets.h`, highest priority over NVS)
|
||||
- [x] NVS configuration (token, API key, model, search key)
|
||||
- [x] Build-time config (`mimi_secrets.h`, sole configuration method)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
#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 "tools/tool_web_search.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@@ -18,26 +14,6 @@
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -46,60 +22,6 @@ static int cmd_wifi_status(int argc, char **argv)
|
||||
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)
|
||||
{
|
||||
@@ -176,51 +98,6 @@ static int cmd_heap_info(int argc, char **argv)
|
||||
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;
|
||||
}
|
||||
|
||||
/* --- set_search_key command --- */
|
||||
static struct {
|
||||
struct arg_str *key;
|
||||
struct arg_end *end;
|
||||
} search_key_args;
|
||||
|
||||
static int cmd_set_search_key(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&search_key_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, search_key_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
tool_web_search_set_key(search_key_args.key->sval[0]);
|
||||
printf("Search API key saved.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --- restart command --- */
|
||||
static int cmd_restart(int argc, char **argv)
|
||||
{
|
||||
@@ -244,18 +121,6 @@ esp_err_t serial_cli_init(void)
|
||||
|
||||
/* Register commands */
|
||||
|
||||
/* wifi_set */
|
||||
wifi_set_args.ssid = arg_str1(NULL, NULL, "<ssid>", "WiFi SSID");
|
||||
wifi_set_args.password = arg_str1(NULL, NULL, "<password>", "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",
|
||||
@@ -264,39 +129,6 @@ esp_err_t serial_cli_init(void)
|
||||
};
|
||||
esp_console_cmd_register(&wifi_status_cmd);
|
||||
|
||||
/* set_tg_token */
|
||||
tg_token_args.token = arg_str1(NULL, NULL, "<token>", "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, "<key>", "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>", "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",
|
||||
@@ -343,37 +175,6 @@ esp_err_t serial_cli_init(void)
|
||||
};
|
||||
esp_console_cmd_register(&heap_cmd);
|
||||
|
||||
/* set_search_key */
|
||||
search_key_args.key = arg_str1(NULL, NULL, "<key>", "Brave Search API key");
|
||||
search_key_args.end = arg_end(1);
|
||||
esp_console_cmd_t search_key_cmd = {
|
||||
.command = "set_search_key",
|
||||
.help = "Set Brave Search API key for web_search tool",
|
||||
.func = &cmd_set_search_key,
|
||||
.argtable = &search_key_args,
|
||||
};
|
||||
esp_console_cmd_register(&search_key_cmd);
|
||||
|
||||
/* set_proxy */
|
||||
proxy_args.host = arg_str1(NULL, NULL, "<host>", "Proxy host/IP");
|
||||
proxy_args.port = arg_int1(NULL, NULL, "<port>", "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",
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "esp_http_client.h"
|
||||
#include "esp_crt_bundle.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "nvs.h"
|
||||
#include "cJSON.h"
|
||||
|
||||
static const char *TAG = "llm";
|
||||
@@ -71,7 +70,6 @@ static esp_err_t http_event_handler(esp_http_client_event_t *evt)
|
||||
|
||||
esp_err_t llm_proxy_init(void)
|
||||
{
|
||||
/* Build-time secrets take highest priority */
|
||||
if (MIMI_SECRET_API_KEY[0] != '\0') {
|
||||
strncpy(s_api_key, MIMI_SECRET_API_KEY, sizeof(s_api_key) - 1);
|
||||
}
|
||||
@@ -79,27 +77,10 @@ esp_err_t llm_proxy_init(void)
|
||||
strncpy(s_model, MIMI_SECRET_MODEL, sizeof(s_model) - 1);
|
||||
}
|
||||
|
||||
/* Fall back to NVS for values not set at build time */
|
||||
if (s_api_key[0] == '\0' || s_model[0] == '\0') {
|
||||
nvs_handle_t nvs;
|
||||
esp_err_t err = nvs_open(MIMI_NVS_LLM, NVS_READONLY, &nvs);
|
||||
if (err == ESP_OK) {
|
||||
if (s_api_key[0] == '\0') {
|
||||
size_t len = sizeof(s_api_key);
|
||||
nvs_get_str(nvs, MIMI_NVS_KEY_API_KEY, s_api_key, &len);
|
||||
}
|
||||
if (strcmp(s_model, MIMI_LLM_DEFAULT_MODEL) == 0) {
|
||||
size_t len = sizeof(s_model);
|
||||
nvs_get_str(nvs, MIMI_NVS_KEY_MODEL, s_model, &len);
|
||||
}
|
||||
nvs_close(nvs);
|
||||
}
|
||||
}
|
||||
|
||||
if (s_api_key[0]) {
|
||||
ESP_LOGI(TAG, "LLM proxy initialized (model: %s)", s_model);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "No API key. Use CLI: set_api_key <KEY>");
|
||||
ESP_LOGW(TAG, "No API key. Set MIMI_SECRET_API_KEY in mimi_secrets.h");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -467,30 +448,3 @@ esp_err_t llm_chat_tools(const char *system_prompt,
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* ── NVS helpers ──────────────────────────────────────────────── */
|
||||
|
||||
esp_err_t llm_set_api_key(const char *api_key)
|
||||
{
|
||||
nvs_handle_t nvs;
|
||||
ESP_ERROR_CHECK(nvs_open(MIMI_NVS_LLM, NVS_READWRITE, &nvs));
|
||||
ESP_ERROR_CHECK(nvs_set_str(nvs, MIMI_NVS_KEY_API_KEY, api_key));
|
||||
ESP_ERROR_CHECK(nvs_commit(nvs));
|
||||
nvs_close(nvs);
|
||||
|
||||
strncpy(s_api_key, api_key, sizeof(s_api_key) - 1);
|
||||
ESP_LOGI(TAG, "API key saved");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t llm_set_model(const char *model)
|
||||
{
|
||||
nvs_handle_t nvs;
|
||||
ESP_ERROR_CHECK(nvs_open(MIMI_NVS_LLM, NVS_READWRITE, &nvs));
|
||||
ESP_ERROR_CHECK(nvs_set_str(nvs, MIMI_NVS_KEY_MODEL, model));
|
||||
ESP_ERROR_CHECK(nvs_commit(nvs));
|
||||
nvs_close(nvs);
|
||||
|
||||
strncpy(s_model, model, sizeof(s_model) - 1);
|
||||
ESP_LOGI(TAG, "Model set to: %s", s_model);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "mimi_config.h"
|
||||
|
||||
/**
|
||||
* Initialize the LLM proxy. Reads API key and model from NVS.
|
||||
* Initialize the LLM proxy.
|
||||
*/
|
||||
esp_err_t llm_proxy_init(void);
|
||||
|
||||
@@ -24,16 +24,6 @@ esp_err_t llm_proxy_init(void);
|
||||
esp_err_t llm_chat(const char *system_prompt, const char *messages_json,
|
||||
char *response_buf, size_t buf_size);
|
||||
|
||||
/**
|
||||
* Save the Anthropic API key to NVS.
|
||||
*/
|
||||
esp_err_t llm_set_api_key(const char *api_key);
|
||||
|
||||
/**
|
||||
* Save the model identifier to NVS.
|
||||
*/
|
||||
esp_err_t llm_set_model(const char *model);
|
||||
|
||||
/* ── Tool Use Support ──────────────────────────────────────────── */
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -134,10 +134,10 @@ void app_main(void)
|
||||
|
||||
ESP_LOGI(TAG, "All services started!");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "WiFi connection timeout. Configure via CLI: wifi_set <SSID> <PASS>");
|
||||
ESP_LOGW(TAG, "WiFi connection timeout. Check MIMI_SECRET_WIFI_SSID in mimi_secrets.h");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "No WiFi credentials. Configure via CLI: wifi_set <SSID> <PASS>");
|
||||
ESP_LOGW(TAG, "No WiFi credentials. Set MIMI_SECRET_WIFI_SSID in mimi_secrets.h");
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "MimiClaw ready. Type 'help' for CLI commands.");
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/* MimiClaw Global Configuration */
|
||||
|
||||
/* Build-time secrets (highest priority, override NVS) */
|
||||
/* Build-time secrets (sole configuration method) */
|
||||
#if __has_include("mimi_secrets.h")
|
||||
#include "mimi_secrets.h"
|
||||
#endif
|
||||
@@ -88,18 +88,3 @@
|
||||
#define MIMI_CLI_PRIO 3
|
||||
#define MIMI_CLI_CORE 0
|
||||
|
||||
/* NVS Namespaces */
|
||||
#define MIMI_NVS_WIFI "wifi_config"
|
||||
#define MIMI_NVS_TG "tg_config"
|
||||
#define MIMI_NVS_LLM "llm_config"
|
||||
#define MIMI_NVS_PROXY "proxy_config"
|
||||
#define MIMI_NVS_SEARCH "search_config"
|
||||
|
||||
/* NVS Keys */
|
||||
#define MIMI_NVS_KEY_SSID "ssid"
|
||||
#define MIMI_NVS_KEY_PASS "password"
|
||||
#define MIMI_NVS_KEY_TG_TOKEN "bot_token"
|
||||
#define MIMI_NVS_KEY_API_KEY "api_key"
|
||||
#define MIMI_NVS_KEY_MODEL "model"
|
||||
#define MIMI_NVS_KEY_PROXY_HOST "host"
|
||||
#define MIMI_NVS_KEY_PROXY_PORT "port"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
* MimiClaw Build-time Secrets
|
||||
*
|
||||
* This is the ONLY way to configure MimiClaw.
|
||||
* Copy this file to mimi_secrets.h and fill in your values.
|
||||
* Non-empty values here take HIGHEST priority (override NVS/CLI).
|
||||
* Leave empty ("") to use NVS values set via CLI.
|
||||
* After any change, rebuild: idf.py fullclean && idf.py build
|
||||
*
|
||||
* cp mimi_secrets.h.example mimi_secrets.h
|
||||
*/
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "nvs.h"
|
||||
#include "esp_tls.h"
|
||||
#include "esp_crt_bundle.h"
|
||||
|
||||
@@ -21,26 +20,14 @@ __attribute__((constructor)) static void proxy_log_level(void)
|
||||
esp_log_level_set(TAG, ESP_LOG_WARN);
|
||||
}
|
||||
|
||||
/* ── Config (cached from NVS) ─────────────────────────────────── */
|
||||
|
||||
static char s_proxy_host[64] = {0};
|
||||
static uint16_t s_proxy_port = 0;
|
||||
|
||||
esp_err_t http_proxy_init(void)
|
||||
{
|
||||
/* Build-time secrets take highest priority */
|
||||
if (MIMI_SECRET_PROXY_HOST[0] != '\0' && MIMI_SECRET_PROXY_PORT[0] != '\0') {
|
||||
strncpy(s_proxy_host, MIMI_SECRET_PROXY_HOST, sizeof(s_proxy_host) - 1);
|
||||
s_proxy_port = (uint16_t)atoi(MIMI_SECRET_PROXY_PORT);
|
||||
} else {
|
||||
nvs_handle_t nvs;
|
||||
esp_err_t err = nvs_open(MIMI_NVS_PROXY, NVS_READONLY, &nvs);
|
||||
if (err == ESP_OK) {
|
||||
size_t len = sizeof(s_proxy_host);
|
||||
nvs_get_str(nvs, MIMI_NVS_KEY_PROXY_HOST, s_proxy_host, &len);
|
||||
nvs_get_u16(nvs, MIMI_NVS_KEY_PROXY_PORT, &s_proxy_port);
|
||||
nvs_close(nvs);
|
||||
}
|
||||
}
|
||||
|
||||
if (s_proxy_host[0] && s_proxy_port) {
|
||||
@@ -56,36 +43,6 @@ bool http_proxy_is_enabled(void)
|
||||
return s_proxy_host[0] != '\0' && s_proxy_port != 0;
|
||||
}
|
||||
|
||||
esp_err_t http_proxy_set(const char *host, uint16_t port)
|
||||
{
|
||||
nvs_handle_t nvs;
|
||||
ESP_ERROR_CHECK(nvs_open(MIMI_NVS_PROXY, NVS_READWRITE, &nvs));
|
||||
ESP_ERROR_CHECK(nvs_set_str(nvs, MIMI_NVS_KEY_PROXY_HOST, host));
|
||||
ESP_ERROR_CHECK(nvs_set_u16(nvs, MIMI_NVS_KEY_PROXY_PORT, port));
|
||||
ESP_ERROR_CHECK(nvs_commit(nvs));
|
||||
nvs_close(nvs);
|
||||
|
||||
strncpy(s_proxy_host, host, sizeof(s_proxy_host) - 1);
|
||||
s_proxy_port = port;
|
||||
ESP_LOGI(TAG, "Proxy set to %s:%d", s_proxy_host, s_proxy_port);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t http_proxy_clear(void)
|
||||
{
|
||||
nvs_handle_t nvs;
|
||||
ESP_ERROR_CHECK(nvs_open(MIMI_NVS_PROXY, NVS_READWRITE, &nvs));
|
||||
nvs_erase_key(nvs, MIMI_NVS_KEY_PROXY_HOST);
|
||||
nvs_erase_key(nvs, MIMI_NVS_KEY_PROXY_PORT);
|
||||
nvs_commit(nvs);
|
||||
nvs_close(nvs);
|
||||
|
||||
s_proxy_host[0] = '\0';
|
||||
s_proxy_port = 0;
|
||||
ESP_LOGI(TAG, "Proxy cleared");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* ── Proxied TLS connection ───────────────────────────────────── */
|
||||
|
||||
struct proxy_conn {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* Initialize proxy module — loads config from NVS.
|
||||
* Initialize proxy module.
|
||||
*/
|
||||
esp_err_t http_proxy_init(void);
|
||||
|
||||
@@ -14,16 +14,6 @@ esp_err_t http_proxy_init(void);
|
||||
*/
|
||||
bool http_proxy_is_enabled(void);
|
||||
|
||||
/**
|
||||
* Save proxy host and port to NVS.
|
||||
*/
|
||||
esp_err_t http_proxy_set(const char *host, uint16_t port);
|
||||
|
||||
/**
|
||||
* Remove proxy config from NVS.
|
||||
*/
|
||||
esp_err_t http_proxy_clear(void);
|
||||
|
||||
/* ── Proxied HTTPS connection ─────────────────────────────────── */
|
||||
|
||||
typedef struct proxy_conn proxy_conn_t;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp_http_client.h"
|
||||
#include "esp_crt_bundle.h"
|
||||
#include "nvs.h"
|
||||
#include "cJSON.h"
|
||||
|
||||
static const char *TAG = "telegram";
|
||||
@@ -257,21 +256,10 @@ static void telegram_poll_task(void *arg)
|
||||
|
||||
esp_err_t telegram_bot_init(void)
|
||||
{
|
||||
/* Build-time secret takes highest priority */
|
||||
if (s_bot_token[0] == '\0') {
|
||||
nvs_handle_t nvs;
|
||||
esp_err_t err = nvs_open(MIMI_NVS_TG, NVS_READONLY, &nvs);
|
||||
if (err == ESP_OK) {
|
||||
size_t len = sizeof(s_bot_token);
|
||||
nvs_get_str(nvs, MIMI_NVS_KEY_TG_TOKEN, s_bot_token, &len);
|
||||
nvs_close(nvs);
|
||||
}
|
||||
}
|
||||
|
||||
if (s_bot_token[0]) {
|
||||
ESP_LOGI(TAG, "Telegram bot token loaded (len=%d)", (int)strlen(s_bot_token));
|
||||
} else {
|
||||
ESP_LOGW(TAG, "No Telegram bot token. Use CLI: set_tg_token <TOKEN>");
|
||||
ESP_LOGW(TAG, "No Telegram bot token. Set MIMI_SECRET_TG_TOKEN in mimi_secrets.h");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -369,15 +357,3 @@ esp_err_t telegram_send_message(const char *chat_id, const char *text)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t telegram_set_token(const char *token)
|
||||
{
|
||||
nvs_handle_t nvs;
|
||||
ESP_ERROR_CHECK(nvs_open(MIMI_NVS_TG, NVS_READWRITE, &nvs));
|
||||
ESP_ERROR_CHECK(nvs_set_str(nvs, MIMI_NVS_KEY_TG_TOKEN, token));
|
||||
ESP_ERROR_CHECK(nvs_commit(nvs));
|
||||
nvs_close(nvs);
|
||||
|
||||
strncpy(s_bot_token, token, sizeof(s_bot_token) - 1);
|
||||
ESP_LOGI(TAG, "Telegram bot token saved");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
/**
|
||||
* Initialize the Telegram bot.
|
||||
* Reads bot token from NVS.
|
||||
*/
|
||||
esp_err_t telegram_bot_init(void);
|
||||
|
||||
@@ -21,7 +20,3 @@ esp_err_t telegram_bot_start(void);
|
||||
*/
|
||||
esp_err_t telegram_send_message(const char *chat_id, const char *text);
|
||||
|
||||
/**
|
||||
* Save the Telegram bot token to NVS.
|
||||
*/
|
||||
esp_err_t telegram_set_token(const char *token);
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "esp_http_client.h"
|
||||
#include "esp_crt_bundle.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "nvs.h"
|
||||
#include "cJSON.h"
|
||||
|
||||
static const char *TAG = "web_search";
|
||||
@@ -44,40 +43,18 @@ static esp_err_t http_event_handler(esp_http_client_event_t *evt)
|
||||
|
||||
esp_err_t tool_web_search_init(void)
|
||||
{
|
||||
/* Build-time secret takes highest priority */
|
||||
if (MIMI_SECRET_SEARCH_KEY[0] != '\0') {
|
||||
strncpy(s_search_key, MIMI_SECRET_SEARCH_KEY, sizeof(s_search_key) - 1);
|
||||
} else {
|
||||
nvs_handle_t nvs;
|
||||
esp_err_t err = nvs_open(MIMI_NVS_SEARCH, NVS_READONLY, &nvs);
|
||||
if (err == ESP_OK) {
|
||||
size_t len = sizeof(s_search_key);
|
||||
nvs_get_str(nvs, MIMI_NVS_KEY_API_KEY, s_search_key, &len);
|
||||
nvs_close(nvs);
|
||||
}
|
||||
}
|
||||
|
||||
if (s_search_key[0]) {
|
||||
ESP_LOGI(TAG, "Web search initialized (key configured)");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "No search API key. Use CLI: set_search_key <KEY>");
|
||||
ESP_LOGW(TAG, "No search API key. Set MIMI_SECRET_SEARCH_KEY in mimi_secrets.h");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t tool_web_search_set_key(const char *api_key)
|
||||
{
|
||||
nvs_handle_t nvs;
|
||||
ESP_ERROR_CHECK(nvs_open(MIMI_NVS_SEARCH, NVS_READWRITE, &nvs));
|
||||
ESP_ERROR_CHECK(nvs_set_str(nvs, MIMI_NVS_KEY_API_KEY, api_key));
|
||||
ESP_ERROR_CHECK(nvs_commit(nvs));
|
||||
nvs_close(nvs);
|
||||
|
||||
strncpy(s_search_key, api_key, sizeof(s_search_key) - 1);
|
||||
ESP_LOGI(TAG, "Search API key saved");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* ── URL-encode a query string ────────────────────────────────── */
|
||||
|
||||
static size_t url_encode(const char *src, char *dst, size_t dst_size)
|
||||
@@ -237,7 +214,7 @@ static esp_err_t search_via_proxy(const char *path, search_buf_t *sb)
|
||||
esp_err_t tool_web_search_execute(const char *input_json, char *output, size_t output_size)
|
||||
{
|
||||
if (s_search_key[0] == '\0') {
|
||||
snprintf(output, output_size, "Error: No search API key configured. Use set_search_key command.");
|
||||
snprintf(output, output_size, "Error: No search API key configured. Set MIMI_SECRET_SEARCH_KEY in mimi_secrets.h");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* Initialize web search tool — loads API key from NVS.
|
||||
* Initialize web search tool.
|
||||
*/
|
||||
esp_err_t tool_web_search_init(void);
|
||||
|
||||
@@ -18,7 +18,3 @@ esp_err_t tool_web_search_init(void);
|
||||
*/
|
||||
esp_err_t tool_web_search_execute(const char *input_json, char *output, size_t output_size);
|
||||
|
||||
/**
|
||||
* Save Brave Search API key to NVS.
|
||||
*/
|
||||
esp_err_t tool_web_search_set_key(const char *api_key);
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_netif.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "nvs.h"
|
||||
|
||||
static const char *TAG = "wifi";
|
||||
|
||||
@@ -72,34 +70,15 @@ esp_err_t wifi_manager_init(void)
|
||||
|
||||
esp_err_t wifi_manager_start(void)
|
||||
{
|
||||
wifi_config_t wifi_cfg = {0};
|
||||
|
||||
/* Build-time secrets take highest priority */
|
||||
if (MIMI_SECRET_WIFI_SSID[0] != '\0') {
|
||||
strncpy((char *)wifi_cfg.sta.ssid, MIMI_SECRET_WIFI_SSID, sizeof(wifi_cfg.sta.ssid) - 1);
|
||||
strncpy((char *)wifi_cfg.sta.password, MIMI_SECRET_WIFI_PASS, sizeof(wifi_cfg.sta.password) - 1);
|
||||
} else {
|
||||
/* Fall back to NVS */
|
||||
nvs_handle_t nvs;
|
||||
esp_err_t err = nvs_open(MIMI_NVS_WIFI, NVS_READONLY, &nvs);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "No WiFi credentials. Use CLI: wifi_set <SSID> <PASS>");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
size_t len = sizeof(wifi_cfg.sta.ssid);
|
||||
err = nvs_get_str(nvs, MIMI_NVS_KEY_SSID, (char *)wifi_cfg.sta.ssid, &len);
|
||||
if (err != ESP_OK) {
|
||||
nvs_close(nvs);
|
||||
ESP_LOGW(TAG, "SSID not found in NVS");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
len = sizeof(wifi_cfg.sta.password);
|
||||
nvs_get_str(nvs, MIMI_NVS_KEY_PASS, (char *)wifi_cfg.sta.password, &len);
|
||||
nvs_close(nvs);
|
||||
if (MIMI_SECRET_WIFI_SSID[0] == '\0') {
|
||||
ESP_LOGW(TAG, "No WiFi credentials. Set MIMI_SECRET_WIFI_SSID in mimi_secrets.h");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
wifi_config_t wifi_cfg = {0};
|
||||
strncpy((char *)wifi_cfg.sta.ssid, MIMI_SECRET_WIFI_SSID, sizeof(wifi_cfg.sta.ssid) - 1);
|
||||
strncpy((char *)wifi_cfg.sta.password, MIMI_SECRET_WIFI_PASS, sizeof(wifi_cfg.sta.password) - 1);
|
||||
|
||||
ESP_LOGI(TAG, "Connecting to SSID: %s", wifi_cfg.sta.ssid);
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg));
|
||||
@@ -126,18 +105,6 @@ bool wifi_manager_is_connected(void)
|
||||
return s_connected;
|
||||
}
|
||||
|
||||
esp_err_t wifi_manager_set_credentials(const char *ssid, const char *password)
|
||||
{
|
||||
nvs_handle_t nvs;
|
||||
ESP_ERROR_CHECK(nvs_open(MIMI_NVS_WIFI, NVS_READWRITE, &nvs));
|
||||
ESP_ERROR_CHECK(nvs_set_str(nvs, MIMI_NVS_KEY_SSID, ssid));
|
||||
ESP_ERROR_CHECK(nvs_set_str(nvs, MIMI_NVS_KEY_PASS, password));
|
||||
ESP_ERROR_CHECK(nvs_commit(nvs));
|
||||
nvs_close(nvs);
|
||||
ESP_LOGI(TAG, "WiFi credentials saved for SSID: %s", ssid);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
const char *wifi_manager_get_ip(void)
|
||||
{
|
||||
return s_ip_str;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
/**
|
||||
* Initialize WiFi subsystem (STA mode).
|
||||
* Reads SSID/password from NVS. If not set, waits for serial configuration.
|
||||
*/
|
||||
esp_err_t wifi_manager_init(void);
|
||||
|
||||
@@ -31,11 +30,6 @@ esp_err_t wifi_manager_wait_connected(uint32_t timeout_ms);
|
||||
*/
|
||||
bool wifi_manager_is_connected(void);
|
||||
|
||||
/**
|
||||
* Save WiFi credentials to NVS.
|
||||
*/
|
||||
esp_err_t wifi_manager_set_credentials(const char *ssid, const char *password);
|
||||
|
||||
/**
|
||||
* Get the current IP address string (or "0.0.0.0" if not connected).
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user