feat: add OpenAI-compatible AI provider plugin with SSE streaming support
- Implemented the OpenAI-compatible AI provider plugin, including configuration, chat, and chat_stream functionalities. - Added support for SSE streaming and tool calls. - Integrated Boost.JSON for JSON handling. - Created CMake configuration for the plugin. - Added error handling and logging throughout the plugin.
This commit is contained in:
@@ -11,16 +11,19 @@ option(DSTALK_BUILD_GUI "Build the SDL3 GUI frontend" OFF)
|
||||
option(DSTALK_BUILD_WEB "Build the web UI frontend" OFF)
|
||||
option(DSTALK_BUILD_TESTS "Build dstalk tests" ON)
|
||||
|
||||
add_subdirectory(dstalk-core)
|
||||
add_subdirectory(dstalk-cli)
|
||||
add_subdirectory(plugins)
|
||||
add_subdirectory(dstalk_core)
|
||||
add_subdirectory(dstalk_cli)
|
||||
# 插件按依赖层级分三个目录 / Plugins split into three directories by dependency tier
|
||||
add_subdirectory(plugins_base)
|
||||
add_subdirectory(plugins_middle)
|
||||
add_subdirectory(plugins_upper)
|
||||
|
||||
if(DSTALK_BUILD_GUI)
|
||||
add_subdirectory(dstalk-gui)
|
||||
add_subdirectory(dstalk_gui)
|
||||
endif()
|
||||
|
||||
if(DSTALK_BUILD_WEB)
|
||||
add_subdirectory(dstalk-web)
|
||||
add_subdirectory(dstalk_web)
|
||||
endif()
|
||||
|
||||
if(DSTALK_BUILD_TESTS)
|
||||
|
||||
16
README.md
16
README.md
@@ -16,7 +16,7 @@ dstalk 是一款 AI 编程助手命令行工具, 通过调用大模型在终端
|
||||
┌───────────────────────────────────────────────────────────┐
|
||||
│ 前端层 (Frontends) │
|
||||
│ ┌──────────────────┐ ┌──────────────────────────┐ │
|
||||
│ │ dstalk-cli │ │ dstalk-gui │ │
|
||||
│ │ dstalk_cli │ │ dstalk_gui │ │
|
||||
│ │ ANSI 终端 UI │ │ SDL3 图形化 UI │ │
|
||||
│ └────────┬─────────┘ └─────────────┬─────────────┘ │
|
||||
│ └──────────────┬───────────────┘ │
|
||||
@@ -24,7 +24,7 @@ dstalk 是一款 AI 编程助手命令行工具, 通过调用大模型在终端
|
||||
└──────────────────────────┼─────────────────────────────────┘
|
||||
│
|
||||
┌──────────────────────────▼─────────────────────────────────┐
|
||||
│ 核心层 (dstalk-core.dll) — 插件宿主 │
|
||||
│ 核心层 (dstalk_core.dll) — 插件宿主 │
|
||||
│ ┌──────────────────────────────────────────────────────┐ │
|
||||
│ │ Host: 插件加载 · 服务注册 · 事件总线 · 配置管理 │ │
|
||||
│ └──────────────────────────────────────────────────────┘ │
|
||||
@@ -33,15 +33,15 @@ dstalk 是一款 AI 编程助手命令行工具, 通过调用大模型在终端
|
||||
│ │ (ai) │ │ (ai) │ │ (http) │ │ 客户端 │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
|
||||
│ │ session │ │ context │ │ file-io │ │ tools │ │
|
||||
│ │ session │ │ context │ │ file_io │ │ tools │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- **dstalk-core** —— C11/C++20 插件化宿主 DLL, 负责插件加载、服务注册、事件总线、配置管理
|
||||
- **dstalk-cli** —— 命令行前端, ANSI 终端 UI
|
||||
- **dstalk-gui** —— 图形化前端, SDL3 跨平台窗口
|
||||
- **plugins/** —— 9 个功能插件, 编译为独立 DLL, 通过 C ABI 动态注册服务
|
||||
- **dstalk_core** —— C11/C++20 插件化宿主 DLL, 负责插件加载、服务注册、事件总线、配置管理
|
||||
- **dstalk_cli** —— 命令行前端, ANSI 终端 UI
|
||||
- **dstalk_gui** —— 图形化前端, SDL3 跨平台窗口
|
||||
- **plugins_base/、plugins_middle/、plugins_upper/** —— 9 个功能插件按三层架构分布, 编译为独立 DLL, 通过 C ABI 动态注册服务
|
||||
|
||||
核心与界面完全解耦, 可编写自己的前端或把 AI 能力嵌入到现有工具中。
|
||||
|
||||
@@ -65,7 +65,7 @@ dstalk 是一款 AI 编程助手命令行工具, 通过调用大模型在终端
|
||||
cd tools && setup.bat # 1. 安装工具链 (CMake / Ninja / LLVM / Conan2)
|
||||
build.bat # 2. 编译
|
||||
# 3. 创建 config.toml # 见教程: docs/tutorial/quick-start.md
|
||||
build/dstalk-cli/dstalk-cli.exe # 4. 运行
|
||||
build/dstalk_cli/dstalk_cli.exe # 4. 运行
|
||||
# 5. 输入自然语言 # "帮我写一个 C 程序"
|
||||
```
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ if !errorlevel! neq 0 (
|
||||
echo.
|
||||
echo ============================================
|
||||
echo 编译成功!
|
||||
echo build\dstalk-core\dstalk.dll
|
||||
echo build\dstalk-cli\dstalk-cli.exe
|
||||
echo build\bin\dstalk.dll
|
||||
echo build\bin\dstalk_cli.exe
|
||||
echo ============================================
|
||||
pause
|
||||
|
||||
@@ -13,7 +13,7 @@ dstalk 选择的不是单体架构,而是**以 C ABI 为边界的插件架构*
|
||||
|
||||
2. **能力会增长**。LSP 集成、文件管理、会话持久化、工具调用——这些能力不是 CLI 启动时必须加载的。使用者可能只需要聊天,不需要 LSP。插件架构让能力按需加载,启动更快,内存更省。
|
||||
|
||||
3. **插件作者不是核心团队**。第三方应该能用自己的编译器、自己的 C++ 标准库版本编写插件,而不必须链接 dstalk-core 的静态库。这要求 ABI 稳定。C ABI 是唯一具有跨编译器二进制兼容性的选择。
|
||||
3. **插件作者不是核心团队**。第三方应该能用自己的编译器、自己的 C++ 标准库版本编写插件,而不必须链接 dstalk_core 的静态库。这要求 ABI 稳定。C ABI 是唯一具有跨编译器二进制兼容性的选择。
|
||||
|
||||
**一句话心智模型**: 不要想象一个胖二进制把所有功能静态链接在一起;想象一个内核 (host) + 一圈可插拔的服务单元 (plugin),内核只负责编排,不负责实现。
|
||||
|
||||
@@ -29,7 +29,7 @@ dstalk 的架构由 3 层组成。从上到下看,每一层依赖下一层提
|
||||
│ 实现具体能力:AI 聊天、文件读写、LSP... │
|
||||
│ 通过服务注册表向其他插件暴露自己的功能 │
|
||||
├────────────────────────────────────────────┤
|
||||
│ Host (dstalk-core) │
|
||||
│ Host (dstalk_core) │
|
||||
│ 拥有事件总线、服务注册表、插件加载器、配置 │
|
||||
│ 提供一个 dstalk_host_api_t 接口给所有插件 │
|
||||
├────────────────────────────────────────────┤
|
||||
@@ -48,7 +48,7 @@ Host 拥有四样东西:
|
||||
- **配置存储 (ConfigStore)**: 管理 `config.toml` 的加载和键值查询。
|
||||
- **事件总线 (EventBus)**: 插件间松耦合通信的唯一通道。
|
||||
- **服务注册表 (ServiceRegistry)**: 按名称 + 版本号存储和查找服务 vtable。
|
||||
- **插件加载器 (PluginLoader)**: 扫描 `plugins/` 目录、加载 DLL、按依赖拓扑排序后调用初始化。
|
||||
- **插件加载器 (PluginLoader)**: 扫描 `plugins_base/`、`plugins_middle/`、`plugins_upper/` 三层目录、加载 DLL、按依赖拓扑排序后调用初始化。
|
||||
|
||||
Host 启动时,按严格顺序执行:
|
||||
1. 分配上述四个组件。
|
||||
|
||||
@@ -52,7 +52,7 @@ Host 调用 `load_plugin(path)`,由 `PluginLoader` 执行:
|
||||
{ "http", "config", NULL }
|
||||
```
|
||||
|
||||
依赖名称与目标插件的 `info->name` 字段匹配(如 `"file-io"` 不是 DLL 的文件名),因此依赖声明和插件命名必须一致。
|
||||
依赖名称与目标插件的 `info->name` 字段匹配(如 `"file_io"` 不是 DLL 的文件名),因此依赖声明和插件命名必须一致。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
## 文件清单
|
||||
|
||||
### 1. `plugins/openai/src/openai_plugin.cpp` -- 安全
|
||||
### 1. `plugins_upper/openai/src/openai_plugin.cpp` -- 安全
|
||||
|
||||
| 行号 | 调用 | 内容 | 风险 |
|
||||
|------|------|------|------|
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
**parse_response() 错误路径 (行 135-151)**: HTTP 错误响应体仅用于提取 JSON `error.message` 字段放入 `r.error`,不会输出到日志。原始 response_body 在解析后被 `g_host->free()` 释放。
|
||||
|
||||
### 2. `plugins/anthropic/src/anthropic_plugin.cpp` -- 安全
|
||||
### 2. `plugins_upper/anthropic/src/anthropic_plugin.cpp` -- 安全
|
||||
|
||||
| 行号 | 调用 | 内容 | 风险 |
|
||||
|------|------|------|------|
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
**build_headers_json() (行 59-65)**: 构建 `{"x-api-key":"<key>","anthropic-version":"2023-06-01"}` 仅用于 HTTP 请求,不经过日志路径。
|
||||
|
||||
### 3. `plugins/network/src/network_plugin.cpp` -- 安全
|
||||
### 3. `plugins_middle/network/src/network_plugin.cpp` -- 安全
|
||||
|
||||
| 行号 | 调用 | 内容 | 风险 |
|
||||
|------|------|------|------|
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
**do_post_stream() 异常路径 (行 280-282)**: `catch (std::exception& e)` 将 `e.what()` 赋值给 `result_body`。Beast/ASIO 异常消息为 OS 级别错误描述(如 "Connection refused"),不含 HTTP header/body 内容。
|
||||
|
||||
### 4. `plugins/config/src/config_plugin.cpp` -- 安全
|
||||
### 4. `plugins_base/config/src/config_plugin.cpp` -- 安全
|
||||
|
||||
| 行号 | 调用 | 内容 | 风险 |
|
||||
|------|------|------|------|
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
ConfigStore 仅提供 get/set/load_file,无日志输出。
|
||||
|
||||
### 5. `dstalk-core/src/host.cpp` -- 基础设施(不动)
|
||||
### 5. `dstalk_core/src/host.cpp` -- 基础设施(不动)
|
||||
|
||||
| 行号 | 调用 | 内容 | 风险 |
|
||||
|------|------|------|------|
|
||||
@@ -68,13 +68,13 @@ ConfigStore 仅提供 get/set/load_file,无日志输出。
|
||||
|
||||
该文件是日志基础设施 (`host_log_impl`),仅负责格式化输出。安全性依赖于调用方不传敏感数据(本审计已确认所有调用方均安全)。按 W9.3 禁忌不修改此文件。
|
||||
|
||||
### 6. `dstalk-core/src/plugin_loader.cpp` -- 安全
|
||||
### 6. `dstalk_core/src/plugin_loader.cpp` -- 安全
|
||||
|
||||
| 行号 | 调用 | 内容 | 风险 |
|
||||
|------|------|------|------|
|
||||
| -- | 无任何日志调用 | -- | 无 |
|
||||
|
||||
### 7. `plugins/session/src/session_plugin.cpp` -- 安全
|
||||
### 7. `plugins_middle/session/src/session_plugin.cpp` -- 安全
|
||||
|
||||
| 行号 | 调用 | 内容 | 风险 |
|
||||
|------|------|------|------|
|
||||
@@ -82,7 +82,7 @@ ConfigStore 仅提供 get/set/load_file,无日志输出。
|
||||
|
||||
该插件处理消息内容(role/content)但不记录任何消息数据到日志。
|
||||
|
||||
### 8. `plugins/lsp/src/lsp_plugin.cpp` -- 低风险
|
||||
### 8. `plugins_base/lsp/src/lsp_plugin.cpp` -- 低风险
|
||||
|
||||
| 行号 | 调用 | 内容 | 风险 |
|
||||
|------|------|------|------|
|
||||
|
||||
@@ -32,8 +32,8 @@ build.bat
|
||||
```
|
||||
|
||||
编译产物输出到 `build/` 目录。核心产物:
|
||||
- `build/dstalk-core/dstalk.dll` —— 核心 DLL
|
||||
- `build/dstalk-cli/dstalk-cli.exe` —— 命令行前端
|
||||
- `build/dstalk_core/dstalk.dll` —— 核心 DLL
|
||||
- `build/dstalk_cli/dstalk_cli.exe` —— 命令行前端
|
||||
- `build/plugins/*.dll` —— 功能插件
|
||||
|
||||
---
|
||||
@@ -69,10 +69,10 @@ api.model = "gpt-4o"
|
||||
|
||||
---
|
||||
|
||||
## 4. 运行 dstalk-cli
|
||||
## 4. 运行 dstalk_cli
|
||||
|
||||
```bash
|
||||
build/dstalk-cli/dstalk-cli.exe
|
||||
build/dstalk_cli/dstalk_cli.exe
|
||||
```
|
||||
|
||||
启动后显示欢迎横幅:
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
# ============================================================
|
||||
# dstalk-cli — 命令行前端 (ANSI 转义码)
|
||||
# dstalk_cli — 命令行前端 (ANSI 转义码)
|
||||
# ============================================================
|
||||
|
||||
add_executable(dstalk-cli
|
||||
add_executable(dstalk_cli
|
||||
src/main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(dstalk-cli PROPERTIES
|
||||
set_target_properties(dstalk_cli PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
|
||||
find_package(Boost REQUIRED CONFIG)
|
||||
|
||||
target_link_libraries(dstalk-cli
|
||||
target_link_libraries(dstalk_cli
|
||||
PRIVATE dstalk boost::boost dstalk_boost_config
|
||||
)
|
||||
@@ -480,7 +480,7 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化主机(加载配置 + 自动扫描 plugins/ 目录加载插件) / Init host: load config + auto-scan plugins/ directory
|
||||
// 初始化主机(加载配置 + 自动扫描 plugins_base/middle/upper 目录加载插件) / Init host: load config + auto-scan plugins_base/middle/upper directories
|
||||
if (dstalk_init(config_path) != 0) {
|
||||
std::fprintf(stderr, CLR_RED "[dstalk] 初始化失败\n" CLR_RESET);
|
||||
return EXIT_CONFIG;
|
||||
@@ -1,5 +1,5 @@
|
||||
# ============================================================
|
||||
# dstalk-core — 核心 DLL (插件宿主)
|
||||
# dstalk_core — 核心 DLL (插件宿主)
|
||||
# 包含: 插件管理 / 服务注册 / 事件总线 / 配置存储
|
||||
# ============================================================
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "config_store.hpp"
|
||||
#include "../../plugins/config/include/toml_parse.h"
|
||||
#include "../../plugins_base/config/include/toml_parse.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
@@ -225,14 +225,22 @@ DSTALK_API int dstalk_init(const char* config_path)
|
||||
}
|
||||
}
|
||||
|
||||
// 扫描插件目录 / Scan plugin directory
|
||||
const char* plugin_dir = g_config->get("plugin_dir");
|
||||
if (!plugin_dir) plugin_dir = "plugins";
|
||||
int loaded = load_plugins_from_directory(plugin_dir);
|
||||
// 扫描插件目录 / Scan plugin directories
|
||||
// 优先扫描三级插件目录,回退到单一 plugins/ 目录(构建输出)
|
||||
// Prefer three-tier plugin dirs, fall back to single plugins/ dir (build output)
|
||||
const char* dirs[] = {
|
||||
"plugins_base", "plugins_middle", "plugins_upper",
|
||||
"../plugins_base", "../plugins_middle", "../plugins_upper",
|
||||
"plugins", "../plugins",
|
||||
nullptr
|
||||
};
|
||||
int loaded = 0;
|
||||
for (int i = 0; dirs[i]; ++i) {
|
||||
int n = load_plugins_from_directory(dirs[i]);
|
||||
if (n > 0) loaded += n;
|
||||
}
|
||||
if (loaded <= 0) {
|
||||
host_log(DSTALK_LOG_WARN,
|
||||
"No plugins found in '%s', trying '../plugins'", plugin_dir);
|
||||
loaded = load_plugins_from_directory("../plugins");
|
||||
host_log(DSTALK_LOG_WARN, "No plugins found in any plugin directory");
|
||||
}
|
||||
|
||||
// 初始化所有插件 / Initialize all plugins
|
||||
@@ -78,7 +78,9 @@ int PluginLoader::load_plugin(const char* path)
|
||||
has_dotdot = true;
|
||||
break;
|
||||
}
|
||||
if (comp == "plugins") {
|
||||
std::string comp_str = comp.string();
|
||||
if (comp_str == "plugins" ||
|
||||
comp_str.substr(0, 8) == "plugins_") {
|
||||
in_plugins_dir = true;
|
||||
}
|
||||
}
|
||||
@@ -91,8 +93,8 @@ int PluginLoader::load_plugin(const char* path)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 目录约束:必须位于 'plugins' 目录下或为纯文件名
|
||||
// Directory constraint: must be under a 'plugins' directory or be a plain filename
|
||||
// 目录约束:必须位于 'plugins' 或 'plugins_*' 目录下,或为纯文件名
|
||||
// Directory constraint: must be under a 'plugins' or 'plugins_*' directory, or be a plain filename
|
||||
if (!in_plugins_dir && p.has_parent_path()) {
|
||||
if (host_api_) {
|
||||
host_api_->log(DSTALK_LOG_ERROR,
|
||||
@@ -1,15 +1,15 @@
|
||||
# ============================================================
|
||||
# dstalk-gui — 图形化前端 (SDL3)
|
||||
# dstalk_gui — 图形化前端 (SDL3)
|
||||
# ============================================================
|
||||
|
||||
# 启用 DSTALK_BUILD_GUI=ON 前,确保 deps/conanfile.txt 中包含 sdl 依赖
|
||||
find_package(SDL3 REQUIRED CONFIG)
|
||||
|
||||
add_executable(dstalk-gui
|
||||
add_executable(dstalk_gui
|
||||
src/main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(dstalk-gui
|
||||
target_link_libraries(dstalk_gui
|
||||
PRIVATE
|
||||
dstalk
|
||||
SDL3::SDL3
|
||||
@@ -1,20 +1,20 @@
|
||||
# ============================================================
|
||||
# dstalk-web — Web 前端 / Web frontend (Boost.Beast HTTP + SSE)
|
||||
# dstalk_web — Web 前端 / Web frontend (Boost.Beast HTTP + SSE)
|
||||
# ============================================================
|
||||
|
||||
find_package(Boost REQUIRED CONFIG)
|
||||
|
||||
add_executable(dstalk-web
|
||||
add_executable(dstalk_web
|
||||
src/main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(dstalk-web PROPERTIES
|
||||
set_target_properties(dstalk_web PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
|
||||
target_compile_features(dstalk-web PRIVATE cxx_std_20)
|
||||
target_compile_features(dstalk_web PRIVATE cxx_std_20)
|
||||
|
||||
target_link_libraries(dstalk-web
|
||||
target_link_libraries(dstalk_web
|
||||
PRIVATE
|
||||
dstalk
|
||||
boost::boost
|
||||
@@ -23,5 +23,5 @@ target_link_libraries(dstalk-web
|
||||
|
||||
# Windows: Boost.Asio 需要 Winsock / Boost.Asio requires Winsock
|
||||
if(WIN32)
|
||||
target_link_libraries(dstalk-web PRIVATE ws2_32)
|
||||
target_link_libraries(dstalk_web PRIVATE ws2_32)
|
||||
endif()
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @file main.cpp
|
||||
* @brief Boost.Beast HTTP server frontend for dstalk-web: SSE streaming chat, embedded web UI, CORS support.
|
||||
* dstalk-web 的 Boost.Beast HTTP 服务端:SSE 流式对话、嵌入式网页界面、CORS 支持。
|
||||
* @brief Boost.Beast HTTP server frontend for dstalk_web: SSE streaming chat, embedded web UI, CORS support.
|
||||
* dstalk_web 的 Boost.Beast HTTP 服务端:SSE 流式对话、嵌入式网页界面、CORS 支持。
|
||||
* Copyright (c) 2026 dstalk contributors. GPLv3.
|
||||
*/
|
||||
|
||||
@@ -423,18 +423,18 @@ public:
|
||||
beast::error_code ec;
|
||||
acceptor_.open(ep.protocol(), ec);
|
||||
if (ec) {
|
||||
std::fprintf(stderr, "[dstalk-web] acceptor.open: %s\n", ec.message().c_str());
|
||||
std::fprintf(stderr, "[dstalk_web] acceptor.open: %s\n", ec.message().c_str());
|
||||
return;
|
||||
}
|
||||
acceptor_.set_option(asio::socket_base::reuse_address(true), ec);
|
||||
acceptor_.bind(ep, ec);
|
||||
if (ec) {
|
||||
std::fprintf(stderr, "[dstalk-web] acceptor.bind: %s\n", ec.message().c_str());
|
||||
std::fprintf(stderr, "[dstalk_web] acceptor.bind: %s\n", ec.message().c_str());
|
||||
return;
|
||||
}
|
||||
acceptor_.listen(asio::socket_base::max_listen_connections, ec);
|
||||
if (ec) {
|
||||
std::fprintf(stderr, "[dstalk-web] acceptor.listen: %s\n", ec.message().c_str());
|
||||
std::fprintf(stderr, "[dstalk_web] acceptor.listen: %s\n", ec.message().c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -499,9 +499,9 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化 dstalk 主机(加载配置 + 自动扫描 plugins/ 目录) / Init dstalk host (load config + auto-scan plugins/)
|
||||
// 初始化 dstalk 主机(加载配置 + 自动扫描 plugins_base/middle/upper 目录) / Init dstalk host (load config + auto-scan plugins_base/middle/upper)
|
||||
if (dstalk_init(config_path) != 0) {
|
||||
std::fprintf(stderr, "[dstalk-web] dstalk_init failed\n");
|
||||
std::fprintf(stderr, "[dstalk_web] dstalk_init failed\n");
|
||||
return 3;
|
||||
}
|
||||
|
||||
@@ -512,10 +512,10 @@ int main(int argc, char* argv[])
|
||||
g_session = static_cast<const dstalk_session_service_t*>(dstalk_service_query("session", 1));
|
||||
|
||||
if (!g_ai) {
|
||||
std::fprintf(stderr, "[dstalk-web] AI service not found (check plugins directory)\n");
|
||||
std::fprintf(stderr, "[dstalk_web] AI service not found (check plugins directory)\n");
|
||||
}
|
||||
if (!g_session) {
|
||||
std::fprintf(stderr, "[dstalk-web] Session service not found\n");
|
||||
std::fprintf(stderr, "[dstalk_web] Session service not found\n");
|
||||
}
|
||||
|
||||
// 从配置自动加载 AI 设置 / Auto-load AI settings from config
|
||||
@@ -546,8 +546,8 @@ int main(int argc, char* argv[])
|
||||
listener.run();
|
||||
|
||||
// 打印启动信息 / Print startup message
|
||||
std::printf("[dstalk-web] running at http://%s:%u\n", web_host, web_port);
|
||||
std::printf("[dstalk-web] Press Ctrl+C to stop\n");
|
||||
std::printf("[dstalk_web] running at http://%s:%u\n", web_host, web_port);
|
||||
std::printf("[dstalk_web] Press Ctrl+C to stop\n");
|
||||
|
||||
// 运行事件循环(阻塞直到 g_ioc->stop() 被信号处理函数调用) / Run event loop (blocks until g_ioc->stop() called by signal handler)
|
||||
ioc.run();
|
||||
@@ -556,6 +556,6 @@ int main(int argc, char* argv[])
|
||||
g_ioc = nullptr;
|
||||
dstalk_shutdown();
|
||||
|
||||
std::printf("[dstalk-web] stopped\n");
|
||||
std::printf("[dstalk_web] stopped\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @file web_ui.hpp
|
||||
* @brief Embedded HTML/JS chat UI served by dstalk-web.
|
||||
* 嵌入的 HTML/JS 聊天界面,由 dstalk-web 提供。
|
||||
* @brief Embedded HTML/JS chat UI served by dstalk_web.
|
||||
* 嵌入的 HTML/JS 聊天界面,由 dstalk_web 提供。
|
||||
* Copyright (c) 2026 dstalk contributors. GPLv3.
|
||||
*/
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
# ============================================================
|
||||
# 插件目录 — 所有功能插件 / Plugin directory — all functional plugins
|
||||
# ============================================================
|
||||
|
||||
# 基础插件(无依赖) / Base plugins (no dependencies)
|
||||
add_subdirectory(config)
|
||||
add_subdirectory(file-io)
|
||||
add_subdirectory(lsp)
|
||||
|
||||
# 依赖基础插件的插件 / Plugins depending on base plugins only
|
||||
add_subdirectory(network) # 依赖 config / depends on config
|
||||
add_subdirectory(session) # 依赖 file_io / depends on file_io
|
||||
add_subdirectory(tools) # 依赖 file_io / depends on file_io
|
||||
|
||||
# 依赖其他插件的插件 / Plugins depending on non-base plugins
|
||||
add_subdirectory(context) # 依赖 session / depends on session
|
||||
add_subdirectory(openai) # 依赖 http, config / depends on http, config
|
||||
add_subdirectory(anthropic) # 依赖 http, config / depends on http, config
|
||||
@@ -1,9 +0,0 @@
|
||||
add_library(plugin-file-io SHARED src/file_io_plugin.cpp)
|
||||
|
||||
target_link_libraries(plugin-file-io PRIVATE dstalk)
|
||||
|
||||
set_target_properties(plugin-file-io PROPERTIES
|
||||
PREFIX ""
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/plugins"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/plugins"
|
||||
)
|
||||
7
plugins_base/CMakeLists.txt
Normal file
7
plugins_base/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
# ============================================================
|
||||
# 基础插件(无依赖) / Base plugins (no dependencies)
|
||||
# ============================================================
|
||||
|
||||
add_subdirectory(config)
|
||||
add_subdirectory(file_io)
|
||||
add_subdirectory(lsp)
|
||||
9
plugins_base/file_io/CMakeLists.txt
Normal file
9
plugins_base/file_io/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
add_library(plugin-file_io SHARED src/file_io_plugin.cpp)
|
||||
|
||||
target_link_libraries(plugin-file_io PRIVATE dstalk)
|
||||
|
||||
set_target_properties(plugin-file_io PROPERTIES
|
||||
PREFIX ""
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/plugins"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/plugins"
|
||||
)
|
||||
@@ -91,7 +91,7 @@ static void on_shutdown() {
|
||||
}
|
||||
|
||||
static dstalk_plugin_info_t g_info = {
|
||||
"file-io", // name 名称
|
||||
"file_io", // name 名称
|
||||
"1.0.0", // version 版本
|
||||
"Basic file I/O service", // description 描述
|
||||
DSTALK_API_VERSION, // api_version
|
||||
7
plugins_middle/CMakeLists.txt
Normal file
7
plugins_middle/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
# ============================================================
|
||||
# 依赖基础插件的插件 / Plugins depending on base plugins only
|
||||
# ============================================================
|
||||
|
||||
add_subdirectory(network) # 依赖 config / depends on config
|
||||
add_subdirectory(session) # 依赖 file_io / depends on file_io
|
||||
add_subdirectory(tools) # 依赖 file_io / depends on file_io
|
||||
@@ -89,7 +89,7 @@ static std::unordered_map<std::string, std::string> parse_headers_json(const cha
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// HTTP 客户端实现(改编自 dstalk-core HttpClient) / HTTP Client implementation (adapted from dstalk-core HttpClient)
|
||||
// HTTP 客户端实现(改编自 dstalk_core HttpClient) / HTTP Client implementation (adapted from dstalk_core HttpClient)
|
||||
// ============================================================
|
||||
struct HttpClientCtx {
|
||||
asio::io_context ioc;
|
||||
7
plugins_upper/CMakeLists.txt
Normal file
7
plugins_upper/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
# ============================================================
|
||||
# 依赖其他插件的插件 / Plugins depending on non-base plugins
|
||||
# ============================================================
|
||||
|
||||
add_subdirectory(context) # 依赖 session / depends on session
|
||||
add_subdirectory(openai) # 依赖 http, config / depends on http, config
|
||||
add_subdirectory(anthropic) # 依赖 http, config / depends on http, config
|
||||
@@ -11,10 +11,10 @@ add_library(plugin-openai SHARED
|
||||
target_link_libraries(plugin-openai PRIVATE dstalk)
|
||||
|
||||
# Boost.JSON (header-only)
|
||||
find_package(Boost REQUIRED CONFIG)
|
||||
target_link_libraries(plugin-openai PRIVATE boost::boost dstalk_boost_config)
|
||||
|
||||
set_target_properties(plugin-openai PROPERTIES
|
||||
PREFIX ""
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins
|
||||
)
|
||||
@@ -18,11 +18,11 @@ add_test(NAME dstalk-smoke-test COMMAND dstalk-smoke-test)
|
||||
|
||||
add_executable(dstalk-host-api-test
|
||||
host_api_test.cpp
|
||||
${CMAKE_SOURCE_DIR}/dstalk-core/src/service_registry.cpp
|
||||
${CMAKE_SOURCE_DIR}/dstalk_core/src/service_registry.cpp
|
||||
)
|
||||
|
||||
target_include_directories(dstalk-host-api-test
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/dstalk-core/src
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/dstalk_core/src
|
||||
)
|
||||
|
||||
target_compile_features(dstalk-host-api-test
|
||||
@@ -41,11 +41,11 @@ add_test(NAME dstalk-host-api-test COMMAND dstalk-host-api-test)
|
||||
|
||||
add_executable(dstalk-event-bus-test
|
||||
event_bus_test.cpp
|
||||
${CMAKE_SOURCE_DIR}/dstalk-core/src/event_bus.cpp
|
||||
${CMAKE_SOURCE_DIR}/dstalk_core/src/event_bus.cpp
|
||||
)
|
||||
|
||||
target_include_directories(dstalk-event-bus-test
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/dstalk-core/src
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/dstalk_core/src
|
||||
)
|
||||
|
||||
target_compile_features(dstalk-event-bus-test
|
||||
@@ -60,11 +60,11 @@ add_test(NAME dstalk-event-bus-test COMMAND dstalk-event-bus-test)
|
||||
|
||||
add_executable(dstalk-service-registry-test
|
||||
service_registry_test.cpp
|
||||
${CMAKE_SOURCE_DIR}/dstalk-core/src/service_registry.cpp
|
||||
${CMAKE_SOURCE_DIR}/dstalk_core/src/service_registry.cpp
|
||||
)
|
||||
|
||||
target_include_directories(dstalk-service-registry-test
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/dstalk-core/src
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/dstalk_core/src
|
||||
)
|
||||
|
||||
target_compile_features(dstalk-service-registry-test
|
||||
@@ -95,12 +95,12 @@ add_test(NAME dstalk-context-plugin-test COMMAND dstalk-context-plugin-test)
|
||||
|
||||
add_executable(dstalk-plugin-loader-test
|
||||
plugin_loader_test.cpp
|
||||
${CMAKE_SOURCE_DIR}/dstalk-core/src/plugin_loader.cpp
|
||||
${CMAKE_SOURCE_DIR}/dstalk-core/src/boost_json.cpp
|
||||
${CMAKE_SOURCE_DIR}/dstalk_core/src/plugin_loader.cpp
|
||||
${CMAKE_SOURCE_DIR}/dstalk_core/src/boost_json.cpp
|
||||
)
|
||||
|
||||
target_include_directories(dstalk-plugin-loader-test
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/dstalk-core/src
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/dstalk_core/src
|
||||
)
|
||||
|
||||
target_compile_features(dstalk-plugin-loader-test
|
||||
@@ -134,7 +134,7 @@ add_executable(dstalk-anthropic-plugin-test
|
||||
)
|
||||
|
||||
target_include_directories(dstalk-anthropic-plugin-test
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/dstalk-core/include
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/dstalk_core/include
|
||||
)
|
||||
|
||||
target_compile_definitions(dstalk-anthropic-plugin-test
|
||||
@@ -161,7 +161,7 @@ add_executable(dstalk-openai-plugin-test
|
||||
)
|
||||
|
||||
target_include_directories(dstalk-openai-plugin-test
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/dstalk-core/include
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/dstalk_core/include
|
||||
)
|
||||
|
||||
target_compile_definitions(dstalk-openai-plugin-test
|
||||
@@ -190,7 +190,7 @@ add_executable(dstalk-network-plugin-test
|
||||
)
|
||||
|
||||
target_include_directories(dstalk-network-plugin-test
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/dstalk-core/include
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/dstalk_core/include
|
||||
)
|
||||
|
||||
target_compile_definitions(dstalk-network-plugin-test
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
#define BOOST_JSON_HEADER_ONLY
|
||||
#define BOOST_ALL_NO_LIB
|
||||
#include "../plugins/anthropic/src/anthropic_plugin.cpp"
|
||||
#include "../plugins_upper/anthropic/src/anthropic_plugin.cpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define BOOST_ASIO_DISABLE_STD_TO_ADDRESS
|
||||
#include "../plugins/network/src/network_plugin.cpp"
|
||||
#include "../plugins_middle/network/src/network_plugin.cpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
#define BOOST_JSON_HEADER_ONLY
|
||||
#define BOOST_ALL_NO_LIB
|
||||
#include "../plugins/openai/src/openai_plugin.cpp"
|
||||
#include "../plugins_upper/openai/src/openai_plugin.cpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
@@ -82,8 +82,8 @@ static void reset_log_state() {
|
||||
g_last_log_msg[0] = '\0';
|
||||
}
|
||||
|
||||
// Get the absolute path to the build output plugins/ directory
|
||||
// 获取构建输出 plugins/ 目录的绝对路径
|
||||
// Get the absolute path to the plugin tier directory (plugins_base / middle / upper)
|
||||
// 获取插件层级目录 (plugins_base / middle / upper) 的绝对路径
|
||||
static fs::path get_plugins_dir() {
|
||||
#ifdef DSTALK_TEST_PLUGINS_DIR
|
||||
return fs::path(DSTALK_TEST_PLUGINS_DIR);
|
||||
@@ -121,10 +121,10 @@ int main()
|
||||
CHECK(loader.load_plugin("../plugins/test.dll") == -1,
|
||||
"T1.3: ../ traversal rejected");
|
||||
|
||||
// T1.4: 不在 plugins/ 目录下 / not under plugins/ dir
|
||||
// T1.4: 不在插件 tier 目录下 / not under plugin tier dir
|
||||
auto tmp = fs::temp_directory_path() / "dstalk_test_no_plugins" / "test.dll";
|
||||
CHECK(loader.load_plugin(tmp.string().c_str()) == -1,
|
||||
"T1.4: path not under plugins/ dir rejected");
|
||||
"T1.4: path not under plugin tier dir rejected");
|
||||
|
||||
// T1.5: 路径中间的 .. 段 / .. segment in middle of path
|
||||
CHECK(loader.load_plugin("plugins/../secret/test.dll") == -1,
|
||||
@@ -134,9 +134,9 @@ int main()
|
||||
CHECK(loader.load_plugin("plugins/test") == -1,
|
||||
"T1.6: no extension rejected");
|
||||
|
||||
// T1.7: 合法扩展名但不在 plugins/ 下 / valid extension but not under plugins/
|
||||
// T1.7: 合法扩展名但不在插件 tier 目录下 / valid extension but not under plugin tier dir
|
||||
CHECK(loader.load_plugin("/etc/someconfig.so") == -1,
|
||||
"T1.7: .so extension but not under plugins/ rejected");
|
||||
"T1.7: .so extension but not under plugin tier dir rejected");
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
@@ -149,7 +149,7 @@ int main()
|
||||
fs::path plugins_dir = get_plugins_dir();
|
||||
|
||||
fs::path dll_config = plugins_dir / "plugin-config.dll";
|
||||
fs::path dll_fileio = plugins_dir / "plugin-file-io.dll";
|
||||
fs::path dll_fileio = plugins_dir / "plugin-file_io.dll";
|
||||
|
||||
bool have_plugins = fs::exists(dll_config) && fs::exists(dll_fileio);
|
||||
|
||||
@@ -206,7 +206,7 @@ int main()
|
||||
fs::path plugins_dir = get_plugins_dir();
|
||||
|
||||
std::vector<fs::path> dlls;
|
||||
for (auto name : {"plugin-config.dll", "plugin-file-io.dll",
|
||||
for (auto name : {"plugin-config.dll", "plugin-file_io.dll",
|
||||
"plugin-context.dll", "plugin-session.dll"}) {
|
||||
fs::path p = plugins_dir / name;
|
||||
if (fs::exists(p)) dlls.push_back(p);
|
||||
|
||||
@@ -58,7 +58,7 @@ int main()
|
||||
<< "model = \"gpt-4o\"\n";
|
||||
}
|
||||
|
||||
// 初始化主机(会自动扫描 plugins/ 加载插件)/ Init host (auto-scans plugins/ to load plugins)
|
||||
// 初始化主机(会自动扫描 plugins_base/middle/upper 加载插件)/ Init host (auto-scans plugins_base/middle/upper to load plugins)
|
||||
if (dstalk_init(config_path.string().c_str()) != 0) {
|
||||
std::cerr << "dstalk_init failed\n";
|
||||
return 1;
|
||||
@@ -112,7 +112,7 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
std::cerr << "[WARN] file_io service not found (plugin may not be in plugins/ dir)\n";
|
||||
std::cerr << "[WARN] file_io service not found (plugin may not be in plugins_base/ dir)\n";
|
||||
}
|
||||
|
||||
// 测试服务查询: session / Test service query: session
|
||||
|
||||
28
模块目录和功能说明.md
28
模块目录和功能说明.md
@@ -4,19 +4,19 @@
|
||||
|
||||
| 目录 | 功能说明 |
|
||||
|------|---------|
|
||||
| `dstalk-core/` | 核心网关库(dstalk.dll / libdstalk.so),提供插件加载、服务注册、事件总线、配置存储、日志、内存管理 |
|
||||
| `dstalk_core/` | 核心网关库(dstalk.dll / libdstalk.so),提供插件加载、服务注册、事件总线、配置存储、日志、内存管理 |
|
||||
|
||||
## 二、前端模块
|
||||
|
||||
| 目录 | 功能说明 |
|
||||
|------|---------|
|
||||
| `dstalk-cli/` | 命令行前端:ANSI 终端交互、命令解析、流式对话、工具调用、批处理/管道模式 |
|
||||
| `dstalk-gui/` | 图形界面前端:SDL3 窗口化界面、暗色主题、流式对话(默认关闭) |
|
||||
| `dstalk-web/` | Web 前端:Boost.Beast HTTP + SSE 流式推送、内嵌 HTML/CSS/JS 聊天界面(默认关闭) |
|
||||
| `dstalk_cli/` | 命令行前端:ANSI 终端交互、命令解析、流式对话、工具调用、批处理/管道模式 |
|
||||
| `dstalk_gui/` | 图形界面前端:SDL3 窗口化界面、暗色主题、流式对话(默认关闭) |
|
||||
| `dstalk_web/` | Web 前端:Boost.Beast HTTP + SSE 流式推送、内嵌 HTML/CSS/JS 聊天界面(默认关闭) |
|
||||
|
||||
## 三、插件模块
|
||||
|
||||
所有插件位于 `plugins/` 目录下,通过 C ABI 与核心网关通信。
|
||||
插件按依赖层级分布在三个目录下,通过 C ABI 与核心网关通信。
|
||||
|
||||
### 3.1 基础插件(无依赖)
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
|
||||
| 目录 | 服务名 | 功能说明 |
|
||||
|------|--------|---------|
|
||||
| `plugins/config/` | `"config"` | TOML 配置文件解析、键值读写 |
|
||||
| `plugins/file-io/` | `"file_io"` | 文件读写服务 |
|
||||
| `plugins/lsp/` | `"lsp"` | 语言服务器协议 JSON-RPC 客户端(诊断、悬停、补全),自行管理子进程 |
|
||||
| `plugins_base/config/` | `"config"` | TOML 配置文件解析、键值读写 |
|
||||
| `plugins_base/file_io/` | `"file_io"` | 文件读写服务 |
|
||||
| `plugins_base/lsp/` | `"lsp"` | 语言服务器协议 JSON-RPC 客户端(诊断、悬停、补全),自行管理子进程 |
|
||||
|
||||
### 3.2 只依赖基础插件的插件
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
|
||||
| 目录 | 服务名 | 功能说明 | 依赖 |
|
||||
|------|--------|---------|------|
|
||||
| `plugins/network/` | `"http"` | HTTP/HTTPS POST 和流式请求(Boost.Beast + OpenSSL) | `config` |
|
||||
| `plugins/session/` | `"session"` | 会话消息历史管理、保存/加载、Token 计数 | `file_io` |
|
||||
| `plugins/tools/` | `"tools"` | 工具注册、Schema 管理、执行分发(内置 file_read/file_write) | `file_io` |
|
||||
| `plugins_middle/network/` | `"http"` | HTTP/HTTPS POST 和流式请求(Boost.Beast + OpenSSL) | `config` |
|
||||
| `plugins_middle/session/` | `"session"` | 会话消息历史管理、保存/加载、Token 计数 | `file_io` |
|
||||
| `plugins_middle/tools/` | `"tools"` | 工具注册、Schema 管理、执行分发(内置 file_read/file_write) | `file_io` |
|
||||
|
||||
### 3.3 依赖其他插件的插件
|
||||
|
||||
@@ -44,9 +44,9 @@
|
||||
|
||||
| 目录 | 服务名 | 功能说明 | 依赖 |
|
||||
|------|--------|---------|------|
|
||||
| `plugins/context/` | `"context"` | Token 计数(UTF-8 字节估算)、上下文窗口裁剪 | `session` |
|
||||
| `plugins/openai/` | `"ai.openai"` | OpenAI 兼容格式 AI 接入(chat/stream/tools、SSE 解析) | `http`、`config` |
|
||||
| `plugins/anthropic/` | `"ai.anthropic"` | Anthropic Claude Messages API 接入(chat/stream、SSE 解析) | `http`、`config` |
|
||||
| `plugins_upper/context/` | `"context"` | Token 计数(UTF-8 字节估算)、上下文窗口裁剪 | `session` |
|
||||
| `plugins_upper/openai/` | `"ai.openai"` | OpenAI 兼容格式 AI 接入(chat/stream/tools、SSE 解析) | `http`、`config` |
|
||||
| `plugins_upper/anthropic/` | `"ai.anthropic"` | Anthropic Claude Messages API 接入(chat/stream、SSE 解析) | `http`、`config` |
|
||||
|
||||
### 3.4 规划中的插件(尚未实现)
|
||||
|
||||
|
||||
14
编码规范和命名规范.md
14
编码规范和命名规范.md
@@ -69,7 +69,7 @@ int ConfigStore::load_file(const char* path)
|
||||
|
||||
| 类型 | 规则 | 示例 |
|
||||
|------|------|------|
|
||||
| 目录名 | 小写英文 + 数字 + 下划线/连字符,字母或下划线开头 | `dstalk-core`、`file-io`、`plugins` |
|
||||
| 目录名 | 小写英文 + 数字 + 下划线/连字符,字母或下划线开头 | `dstalk_core`、`file_io`、`plugins` |
|
||||
| 源文件 | 小写英文 + 下划线,字母开头 | `config_store.cpp`、`openai_plugin.cpp` |
|
||||
| 头文件 | 同源文件规则 | `dstalk_host.h`、`event_bus.hpp` |
|
||||
| 测试文件 | `<模块名>_test.cpp` | `event_bus_test.cpp`、`openai_plugin_test.cpp` |
|
||||
@@ -99,7 +99,7 @@ int ConfigStore::load_file(const char* path)
|
||||
|
||||
| 类型 | 规则 | 示例 |
|
||||
|------|------|------|
|
||||
| 插件目录 | 功能名,小写 + 连字符 | `plugins/openai/`、`plugins/file-io/` |
|
||||
| 插件目录 | 功能名,小写 + 下划线 | `plugins_upper/openai/`、`plugins_base/file_io/` |
|
||||
| 插件源文件 | `<功能名>_plugin.cpp` | `openai_plugin.cpp`、`session_plugin.cpp` |
|
||||
| CMake 目标 | `plugin-<功能名>` | `plugin-openai`、`plugin-network` |
|
||||
| 服务注册名 | 小写 + 点号分级 | `"ai.openai"`、`"http"`、`"session"` |
|
||||
@@ -116,13 +116,13 @@ int ConfigStore::load_file(const char* path)
|
||||
|
||||
### 4.1 目录 README
|
||||
|
||||
- `dstalk/`(根目录)和所有二级目录(`dstalk-core/`、`dstalk-cli/`、`plugins/` 等)必须有 `README.md`
|
||||
- 三级目录(如 `plugins/openai/`)如内容简单可暂不添加
|
||||
- `dstalk/`(根目录)和所有二级目录(`dstalk_core/`、`dstalk_cli/`、`plugins_base/`、`plugins_middle/`、`plugins_upper/` 等)必须有 `README.md`
|
||||
- 三级目录(如 `plugins_upper/openai/`)如内容简单可暂不添加
|
||||
|
||||
### 4.2 include 路径
|
||||
|
||||
- 公共头文件放在 `dstalk-core/include/dstalk/` 下
|
||||
- 私有实现头文件放在 `dstalk-core/src/` 下
|
||||
- 公共头文件放在 `dstalk_core/include/dstalk/` 下
|
||||
- 私有实现头文件放在 `dstalk_core/src/` 下
|
||||
- 插件不得被 core 反向依赖(core 禁止 `#include` 插件目录下的文件)
|
||||
|
||||
### 4.3 内存管理
|
||||
@@ -135,4 +135,4 @@ int ConfigStore::load_file(const char* path)
|
||||
|
||||
- 所有目标输出到 `${CMAKE_BINARY_DIR}/bin`(可执行文件)或 `${CMAKE_BINARY_DIR}/plugins`(插件 DLL)
|
||||
- 新前端通过 `option(DSTALK_BUILD_XXX)` 控制,默认 OFF
|
||||
- 插件在 `plugins/CMakeLists.txt` 中按依赖顺序 `add_subdirectory`
|
||||
- 插件在 `plugins_base/CMakeLists.txt`、`plugins_middle/CMakeLists.txt`、`plugins_upper/CMakeLists.txt` 中按依赖顺序 `add_subdirectory`
|
||||
|
||||
Reference in New Issue
Block a user