W20: Tool Calling 闭环 + Stream+Tools + 回归测试 + session auto-save + ASan CI (W20.1-W20.6)
- W20.1: CLI tool_calls→execute→result→re-call 循环(5轮上限) - W20.2: deepseek 流式 tool_calls 增量解析(configure 缓存,无 ABI break) - W20.3: plugin_loader 回归测试 5 块 32 断言(路径/原子性/mock 日志) - W20.4: plugin_loader ABI 契约校验(name/version/on_init 字段验证) - W20.5: ASan/UBSan CMake preset + CI sanitizer job(PR-only Linux) - W20.6: session auto-save(on_shutdown 写 %APPDATA%/dstalk/session.json) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <mutex>
|
||||
@@ -287,6 +288,24 @@ static dstalk_session_service_t g_session_service = {
|
||||
session_token_count
|
||||
};
|
||||
|
||||
// ============================================================
|
||||
// W20.6: 默认会话保存路径(平台标准目录)
|
||||
// ============================================================
|
||||
|
||||
static std::string get_default_session_path() {
|
||||
#ifdef _WIN32
|
||||
char* buf = nullptr;
|
||||
size_t len = 0;
|
||||
_dupenv_s(&buf, &len, "APPDATA");
|
||||
std::string dir = buf ? std::string(buf) + "/dstalk" : "dstalk";
|
||||
free(buf);
|
||||
#else
|
||||
const char* home = std::getenv("HOME");
|
||||
std::string dir = home ? std::string(home) + "/.dstalk" : "/tmp/dstalk";
|
||||
#endif
|
||||
return dir + "/session.json";
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 插件生命周期
|
||||
// ============================================================
|
||||
@@ -304,7 +323,13 @@ static int on_init(const dstalk_host_api_t* host) {
|
||||
g_file_io.store(static_cast<const dstalk_file_io_service_t*>(raw), std::memory_order_release);
|
||||
|
||||
// 注册自身服务
|
||||
return host->register_service("session", 1, &g_session_service);
|
||||
int ret = host->register_service("session", 1, &g_session_service);
|
||||
if (ret != 0) return ret;
|
||||
|
||||
// W20.6: 从默认路径恢复会话(文件不存在则静默失败)
|
||||
session_load(get_default_session_path().c_str());
|
||||
|
||||
return 0;
|
||||
} catch (const std::exception& e) {
|
||||
const dstalk_host_api_t* h = g_host.load(std::memory_order_acquire);
|
||||
if (h) h->log(DSTALK_LOG_ERROR, "on_init[session]: %s", e.what());
|
||||
@@ -318,6 +343,9 @@ static int on_init(const dstalk_host_api_t* host) {
|
||||
|
||||
static void on_shutdown() {
|
||||
try {
|
||||
// W20.6: 清空前自动保存到默认路径
|
||||
session_save(get_default_session_path().c_str());
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_session_mutex);
|
||||
rebuild_cached_history_locked();
|
||||
g_cached_history.clear();
|
||||
|
||||
Reference in New Issue
Block a user