W22: coverage metric + network tests + Tool stream feedback + stdin pipe + session path + dependency check (W22.1-W22.6)
Some checks failed
Some checks failed
- W22.1: gcovr 覆盖率度量 + CI coverage job(40% 阈值 warning) - W22.2: network_plugin 单元测试(parse_headers_json/extract_host_port/SSE/异常保护) - W22.3: Tool Calling 流式反馈(chat_stream + "[工具调用]/[工具结果]" 状态行) - W22.4: --prompt stdin pipe(--prompt - 从 stdin 读取) - W22.5: session 路径健壮化(static 缓存 + mkdir + fallback) - W22.6: 插件依赖拓扑静态校验(validate_dependencies 循环/缺失检测) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -406,9 +406,16 @@ int main(int argc, char* argv[])
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (std::strcmp(argv[i], "--batch") == 0) {
|
||||
batch_mode = true;
|
||||
} else if (std::strcmp(argv[i], "--prompt") == 0 && i + 1 < argc && argv[i+1][0] != '-') {
|
||||
prompt_arg = argv[++i];
|
||||
} else if (std::strcmp(argv[i], "--prompt") == 0) {
|
||||
batch_mode = true;
|
||||
if (i + 1 < argc && argv[i+1][0] != '-') {
|
||||
prompt_arg = argv[++i];
|
||||
} else if (i + 1 < argc && std::strcmp(argv[i+1], "-") == 0) {
|
||||
++i;
|
||||
prompt_arg = "-"; // stdin sentinel
|
||||
} else {
|
||||
prompt_arg = "-"; // --prompt without value → read stdin
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -524,10 +531,25 @@ int main(int argc, char* argv[])
|
||||
|
||||
// ---- --prompt 批处理模式 (非交互) ----
|
||||
if (prompt_arg) {
|
||||
if (prompt_arg[0] == '\0') {
|
||||
std::fprintf(stderr, "empty prompt\n");
|
||||
dstalk_shutdown();
|
||||
return EXIT_FATAL;
|
||||
std::string prompt_text;
|
||||
if (std::strcmp(prompt_arg, "-") == 0) {
|
||||
// --prompt - or --prompt (no arg): read prompt from stdin
|
||||
char buf[4096];
|
||||
while (std::fgets(buf, sizeof(buf), stdin)) {
|
||||
prompt_text += buf;
|
||||
}
|
||||
if (prompt_text.empty()) {
|
||||
std::fprintf(stderr, "empty prompt\n");
|
||||
dstalk_shutdown();
|
||||
return EXIT_FATAL;
|
||||
}
|
||||
} else {
|
||||
if (prompt_arg[0] == '\0') {
|
||||
std::fprintf(stderr, "empty prompt\n");
|
||||
dstalk_shutdown();
|
||||
return EXIT_FATAL;
|
||||
}
|
||||
prompt_text = prompt_arg;
|
||||
}
|
||||
if (!g_ai || !g_session) {
|
||||
std::fprintf(stderr, CLR_RED "[ERROR] AI or session service unavailable\n" CLR_RESET);
|
||||
@@ -536,7 +558,7 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
int history_count = 0;
|
||||
const dstalk_message_t* history = g_session->history(&history_count);
|
||||
dstalk_chat_result_t result = g_ai->chat(history, history_count, prompt_arg, nullptr);
|
||||
dstalk_chat_result_t result = g_ai->chat(history, history_count, prompt_text.c_str(), nullptr);
|
||||
if (result.ok) {
|
||||
std::printf("%s\n", result.content ? result.content : "");
|
||||
g_ai->free_result(&result);
|
||||
@@ -654,8 +676,10 @@ int main(int argc, char* argv[])
|
||||
? boost::json::value_to<std::string>(*id_j) : "";
|
||||
|
||||
// 执行工具
|
||||
std::printf(CLR_DIM "[工具调用] %s...\n" CLR_RESET, tool_name.c_str());
|
||||
char* exec_result = g_tools->execute(tool_name.c_str(), tool_args.c_str());
|
||||
if (exec_result) {
|
||||
std::printf(CLR_DIM "[工具结果] ok\n" CLR_RESET);
|
||||
dstalk_message_t tool_msg = {
|
||||
"tool",
|
||||
exec_result,
|
||||
@@ -666,6 +690,7 @@ int main(int argc, char* argv[])
|
||||
dstalk_free(exec_result);
|
||||
any_executed = true;
|
||||
} else {
|
||||
std::printf(CLR_DIM "[工具结果] fail\n" CLR_RESET);
|
||||
// 单工具失败:log + skip
|
||||
std::fprintf(stderr, CLR_YELLOW "[WARN] tool '%s' returned null, skipping\n" CLR_RESET,
|
||||
tool_name.c_str());
|
||||
@@ -674,20 +699,16 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (!any_executed) break;
|
||||
|
||||
// 重新调用 AI(chat 非流式,此时 history 已包含工具结果)
|
||||
// 重新调用 AI(chat_stream 流式,此时 history 已包含工具结果)
|
||||
history_count = 0;
|
||||
history = g_session->history(&history_count);
|
||||
char* tools_json = g_tools->get_tools_json();
|
||||
|
||||
g_ai->free_result(&result);
|
||||
result = g_ai->chat(history, history_count, nullptr, tools_json);
|
||||
|
||||
if (tools_json) dstalk_free(tools_json);
|
||||
bool tool_stream_first = true;
|
||||
result = g_ai->chat_stream(history, history_count, nullptr, on_stream_token, &tool_stream_first);
|
||||
|
||||
if (result.ok) {
|
||||
if (result.content && result.content[0]) {
|
||||
std::printf("%s\n", result.content);
|
||||
}
|
||||
std::printf(CLR_RESET "\n");
|
||||
dstalk_message_t ai_followup = {
|
||||
"assistant",
|
||||
result.content,
|
||||
|
||||
Reference in New Issue
Block a user