feat: add AI endpoint manager plugin with configuration and routing capabilities
Some checks failed
CI / Determine matrix (push) Has been cancelled
CI / Sanitizer (ASan+UBSan) / ubuntu-24.04 (push) Has been cancelled
CI / Coverage (gcovr) / ubuntu-24.04 (push) Has been cancelled
CI / ${{ matrix.os }} / ${{ matrix.build_type }} (push) Has been cancelled

- Introduced `ai_endpoint_mgr` plugin to manage multiple AI provider endpoints.
- Added configuration reference documentation for `config.toml`.
- Implemented endpoint loading, active endpoint switching, and model mutation.
- Included error handling for missing endpoints and configuration failures.
- Developed unit tests covering various scenarios including error paths and concurrency.
This commit is contained in:
2026-06-03 21:07:25 +08:00
parent 28ae90a6cc
commit 4745ce1f1c
18 changed files with 1570 additions and 34 deletions

View File

@@ -35,6 +35,42 @@ typedef struct {
void (*free_result)(dstalk_chat_result_t* result);
} dstalk_ai_service_t;
/* ---- AI endpoint manager 服务 vtable / AI endpoint manager service vtable ---- */
/* 以服务名称 "ai_endpoint_mgr" 注册;用于按名称路由到多个 provider/model endpoint。 / Registered as "ai_endpoint_mgr"; routes named endpoints to provider/model configs. */
typedef struct {
/* 返回已配置 endpoint 数量 / Return configured endpoint count. */
int (*count)(void);
/* 返回 endpoint 列表 JSON调用方用 dstalk_free 释放 / Return endpoint list JSON; caller frees with dstalk_free. */
char* (*list_json)(void);
/* 获取当前 active endpoint 名称 / Get current active endpoint name.
返回的指针指向 thread_local 存储区,调用方不需要释放。该指针在同线程下一次
get_active 调用前或 active endpoint 状态变化前有效;跨线程并发调用各自拥有
独立的 thread_local 副本,互不干扰。
The returned pointer points to thread-local storage; caller must not free it.
Valid until the next get_active call on the same thread or until the active
endpoint changes. Concurrent calls from different threads each have their own
independent thread-local copy. */
const char* (*get_active)(void);
/* 设置当前 active endpoint / Set current active endpoint. */
int (*set_active)(const char* endpoint_name);
/* 设置 endpoint 模型名endpoint_name 为空时修改 active endpoint / Set endpoint model; null endpoint_name updates active endpoint. */
int (*set_model)(const char* endpoint_name, const char* model);
/* 在指定 endpoint 上执行阻塞 chat / Run blocking chat on a named endpoint. */
dstalk_chat_result_t (*chat)(
const char* endpoint_name,
const dstalk_message_t* history, int history_len,
const char* user_input,
const char* tools_json);
/* 在指定 endpoint 上执行流式 chat / Run streaming chat on a named endpoint. */
dstalk_chat_result_t (*chat_stream)(
const char* endpoint_name,
const dstalk_message_t* history, int history_len,
const char* user_input,
dstalk_stream_cb cb, void* userdata);
/* 释放 endpoint manager 返回的 chat result / Free chat result returned by endpoint manager. */
void (*free_result)(dstalk_chat_result_t* result);
} dstalk_ai_endpoint_mgr_t;
/* ---- 会话服务 vtable / Session service vtable ---- */
/* 以服务名称 "session" 注册 / Registered under service name "session" */
typedef struct {