diff --git a/src/core/reload.c b/src/core/reload.c index 17c64e5..cbad861 100644 --- a/src/core/reload.c +++ b/src/core/reload.c @@ -87,6 +87,7 @@ int try_config_reload(config_t **pcfg) return -1; } provider_router_set_live_config(new_cfg); + provider_anthropic_set_live_config(new_cfg); provider_openai_set_live_config(new_cfg); provider_local_set_live_config(new_cfg); tool_set_config(new_cfg); diff --git a/src/providers/anthropic.c b/src/providers/anthropic.c index 2801427..2e4789f 100644 --- a/src/providers/anthropic.c +++ b/src/providers/anthropic.c @@ -414,6 +414,17 @@ const provider_t *provider_anthropic_get(void) return &anthropic_provider; } +void provider_anthropic_set_live_config(const config_t *cfg) +{ + if (cfg && s_anth_api_key) + s_anth_cfg = cfg; +} + +const config_t *anthropic_live_config_for_test(void) +{ + return s_anth_cfg; +} + #ifdef SHELLCLAW_TEST int anthropic_parse_response_for_test(const char *json, provider_response_t *response) { diff --git a/src/providers/provider.h b/src/providers/provider.h index 6b8fa1a..0040b32 100644 --- a/src/providers/provider.h +++ b/src/providers/provider.h @@ -124,6 +124,10 @@ void provider_stub_b_set_chat_error_message(const char *message); /** Anthropic (Claude) provider. Messages API, tool_use. */ const provider_t *provider_anthropic_get(void); +/** After SIGHUP or dashboard reload: refresh model and max_tokens without re-init. */ +void provider_anthropic_set_live_config(const config_t *cfg); +/** Config pointer Anthropic chat reads. NULL until init. For tests. */ +const config_t *anthropic_live_config_for_test(void); /** OpenAI provider. Chat Completions, tool_calls (function calling). */ const provider_t *provider_openai_get(void); diff --git a/tests/test_reload.c b/tests/test_reload.c index 37e7a75..7c07693 100644 --- a/tests/test_reload.c +++ b/tests/test_reload.c @@ -2,12 +2,15 @@ * @file test_reload.c * @brief Unit tests for SIGHUP config reload and stale config queue. */ +#define _POSIX_C_SOURCE 200809L #include "test_runner.h" #include "core/reload.h" #include "core/bootstrap.h" #include "core/config.h" +#include "providers/provider.h" #include +#include #include static config_t *load_minimal_config(const char *path, const char *model) @@ -212,8 +215,49 @@ static int test_try_config_reload_ignores_stale_caller_pointer(void) return 0; } +static int test_try_config_reload_updates_anthropic_model(void) +{ + char path[128]; + config_t *cfg = NULL; + const provider_t *anth; + const config_t *live; + + ASSERT(test_runner_mkstemp_path("shellclaw_test_reload", path, sizeof(path)) == 0); + cfg = load_config_with_tokens(path, "model-before", 111); + ASSERT(cfg != NULL); + bootstrap_set_config_path(path); + bootstrap_set_cfg(cfg); + ASSERT(setenv("ANTHROPIC_API_KEY", "test-key-not-sent", 1) == 0); + anth = provider_anthropic_get(); + ASSERT(anth != NULL && anth->init != NULL && anth->cleanup != NULL); + ASSERT(anth->init(cfg) == 0); + live = anthropic_live_config_for_test(); + ASSERT(live != NULL); + ASSERT(strcmp(config_agent_model(live), "model-before") == 0); + ASSERT(config_agent_max_tokens(live) == 111); + { + FILE *f = fopen(path, "w"); + ASSERT(f); + fprintf(f, "[agent]\nmodel = \"model-after\"\nmax_tokens = 222\n"); + fclose(f); + } + ASSERT(try_config_reload(&cfg) == 0); + live = anthropic_live_config_for_test(); + ASSERT(live != NULL); + ASSERT(strcmp(config_agent_model(live), "model-after") == 0); + ASSERT(config_agent_max_tokens(live) == 222); + anth->cleanup(); + stale_free_all(); + config_free(cfg); + bootstrap_set_cfg(NULL); + unsetenv("ANTHROPIC_API_KEY"); + remove(path); + return 0; +} + int main(void) { + RUN(test_try_config_reload_updates_anthropic_model()); RUN(test_on_hup_sets_reload_flag()); RUN(test_stale_enqueue_null_is_noop()); RUN(test_stale_enqueue_preserves_old_config());