- New plugins_upper/ai_common/ static library: shared PluginConfig, ToolCallAccum, StreamContext, secure_zero, extract_host_port, serialize_tool_calls, free_chat_result - Refactored openai/anthropic plugins to use dstalk_ai:: namespace from ai_common - Fixed anthropic g_config raw pointer → std::atomic (data race) - Added SSE parse error counter with threshold abort (kMaxSseParseErrors=5) - Fixed missing closing brace in both plugins' error-body catch block - Updated test targets: ai_common include path + link, using namespace dstalk_ai - plugin_loader_test: added stub_unreg + service_registry.cpp for unregister_service - Includes pre-existing uncommitted changes from prior waves Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
40 lines
1.2 KiB
C++
40 lines
1.2 KiB
C++
/*
|
|
* @file ai_common.cpp
|
|
* @brief Shared utility implementations for AI provider plugins.
|
|
* AI 提供者插件的共享工具函数实现。
|
|
* Copyright (c) 2026 dstalk contributors. GPLv3.
|
|
*/
|
|
|
|
#include "ai_common.hpp"
|
|
|
|
namespace dstalk_ai {
|
|
|
|
void secure_zero(void* p, size_t n) {
|
|
volatile char* vp = static_cast<volatile char*>(p);
|
|
while (n--) *vp++ = 0;
|
|
}
|
|
|
|
bool extract_host_port(const std::string& url,
|
|
std::string& scheme_out, std::string& host_out,
|
|
std::string& port_out, std::string& target_out)
|
|
{
|
|
size_t scheme_end = url.find("://");
|
|
if (scheme_end == std::string::npos) return false;
|
|
scheme_out = url.substr(0, scheme_end);
|
|
std::string rest = url.substr(scheme_end + 3);
|
|
size_t slash = rest.find('/');
|
|
std::string authority = (slash != std::string::npos) ? rest.substr(0, slash) : rest;
|
|
target_out = (slash != std::string::npos) ? rest.substr(slash) : "/";
|
|
size_t colon = authority.rfind(':');
|
|
if (colon != std::string::npos) {
|
|
host_out = authority.substr(0, colon);
|
|
port_out = authority.substr(colon + 1);
|
|
} else {
|
|
host_out = authority;
|
|
port_out = (scheme_out == "https") ? "443" : "80";
|
|
}
|
|
return true;
|
|
}
|
|
|
|
} // namespace dstalk_ai
|