diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1d5a363e..4a948e55 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -85,6 +85,22 @@ async def main(): asyncio.run(main()) ``` +### 5. Build Rust CLI (Optional) + +The Rust CLI (`ov`) provides a high-performance command-line client for interacting with OpenViking Server. + +**Prerequisites**: Rust >= 1.88 + +```bash +# Build and install from source +cargo install --path crates/ov_cli + +# Or use the quick install script (downloads pre-built binary) +curl -fsSL https://raw.githubusercontent.com/volcengine/OpenViking/main/crates/ov_cli/install.sh | bash +``` + +After installation, run `ov --help` to see all available commands. CLI connection config goes in `~/.openviking/ovcli.conf`. + --- ## Project Structure @@ -92,6 +108,7 @@ asyncio.run(main()) ``` openviking/ ├── pyproject.toml # Project configuration +├── Cargo.toml # Rust workspace configuration ├── third_party/ # Third-party dependencies │ └── agfs/ # AGFS filesystem │ @@ -117,6 +134,11 @@ openviking/ │ │ ├── session.py # Session core │ │ └── compressor.py # Compression │ │ +│ ├── server/ # HTTP server +│ │ ├── app.py # FastAPI app factory +│ │ ├── bootstrap.py # Entry point (openviking-server) +│ │ └── routers/ # API routers +│ │ │ ├── storage/ # Storage layer │ │ ├── viking_fs.py # VikingFS │ │ └── vectordb/ # Vector database @@ -126,7 +148,21 @@ openviking/ │ │ │ └── prompts/ # Prompt templates │ +├── crates/ # Rust components +│ └── ov_cli/ # Rust CLI client +│ ├── src/ # CLI source code +│ └── install.sh # Quick install script +│ +├── src/ # C++ extensions (pybind11) +│ ├── tests/ # Test suite +│ ├── client/ # Client tests +│ ├── server/ # Server tests +│ ├── session/ # Session tests +│ ├── parse/ # Parser tests +│ ├── vectordb/ # Vector database tests +│ └── integration/ # Integration tests +│ └── docs/ # Documentation ├── en/ # English docs └── zh/ # Chinese docs @@ -190,48 +226,50 @@ mypy openviking/ # Run all tests pytest +# Run specific test module +pytest tests/client/ -v +pytest tests/server/ -v +pytest tests/parse/ -v + # Run specific test file -pytest tests/test_parser.py +pytest tests/client/test_lifecycle.py + +# Run specific test +pytest tests/client/test_lifecycle.py::TestClientInitialization::test_initialize_success + +# Run by keyword +pytest -k "search" -v # Run with coverage pytest --cov=openviking --cov-report=term-missing - -# Run with verbose output -pytest -v ``` ### Writing Tests -Place test files in `tests/` directory with `test_*.py` naming: +Tests are organized in subdirectories under `tests/`. The project uses `asyncio_mode = "auto"`, so async tests do **not** need the `@pytest.mark.asyncio` decorator: ```python -# tests/test_client.py -import pytest +# tests/client/test_example.py from openviking import AsyncOpenViking + class TestAsyncOpenViking: - @pytest.mark.asyncio - async def test_initialize(self, tmp_path): - client = AsyncOpenViking(path=str(tmp_path / "data")) - await client.initialize() - assert client._viking_fs is not None - await client.close() - - @pytest.mark.asyncio - async def test_add_resource(self, tmp_path): - client = AsyncOpenViking(path=str(tmp_path / "data")) - await client.initialize() + async def test_initialize(self, uninitialized_client: AsyncOpenViking): + await uninitialized_client.initialize() + assert uninitialized_client._service is not None + await uninitialized_client.close() + async def test_add_resource(self, client: AsyncOpenViking): result = await client.add_resource( "./test.md", reason="test document" ) assert result["status"] == "success" assert "root_uri" in result - - await client.close() ``` +Common fixtures are defined in `tests/conftest.py`, including `client` (initialized `AsyncOpenViking`), `uninitialized_client`, `temp_dir`, etc. + --- ## Contribution Workflow diff --git a/CONTRIBUTING_CN.md b/CONTRIBUTING_CN.md index 9875050b..6cd07452 100644 --- a/CONTRIBUTING_CN.md +++ b/CONTRIBUTING_CN.md @@ -84,6 +84,22 @@ async def main(): asyncio.run(main()) ``` +### 5. 构建 Rust CLI(可选) + +Rust CLI (`ov`) 提供高性能的命令行客户端,用于连接 OpenViking Server 进行操作。 + +**前置要求**:Rust >= 1.88 + +```bash +# 从源码编译安装 +cargo install --path crates/ov_cli + +# 或者使用一键安装脚本(下载预编译二进制) +curl -fsSL https://raw.githubusercontent.com/volcengine/OpenViking/main/crates/ov_cli/install.sh | bash +``` + +安装后通过 `ov --help` 查看所有可用命令。CLI 连接配置见 `~/.openviking/ovcli.conf`。 + --- ## 项目结构 @@ -91,6 +107,7 @@ asyncio.run(main()) ``` openviking/ ├── pyproject.toml # 项目配置 +├── Cargo.toml # Rust workspace 配置 ├── third_party/ # 第三方依赖 │ └── agfs/ # AGFS 文件系统 │ @@ -116,6 +133,11 @@ openviking/ │ │ ├── session.py # 会话核心 │ │ └── compressor.py # 压缩 │ │ +│ ├── server/ # HTTP 服务端 +│ │ ├── app.py # FastAPI 应用工厂 +│ │ ├── bootstrap.py # 启动入口 (openviking-server) +│ │ └── routers/ # API 路由 +│ │ │ ├── storage/ # 存储层 │ │ ├── viking_fs.py # VikingFS │ │ └── vectordb/ # 向量数据库 @@ -125,7 +147,21 @@ openviking/ │ │ │ └── prompts/ # 提示词模板 │ +├── crates/ # Rust 组件 +│ └── ov_cli/ # Rust CLI 客户端 +│ ├── src/ # CLI 源码 +│ └── install.sh # 一键安装脚本 +│ +├── src/ # C++ 扩展 (pybind11) +│ ├── tests/ # 测试套件 +│ ├── client/ # 客户端测试 +│ ├── server/ # 服务端测试 +│ ├── session/ # 会话测试 +│ ├── parse/ # 解析器测试 +│ ├── vectordb/ # 向量数据库测试 +│ └── integration/ # 集成测试 +│ └── docs/ # 文档 ├── en/ # 英文文档 └── zh/ # 中文文档 @@ -189,48 +225,50 @@ mypy openviking/ # 运行所有测试 pytest +# 运行特定测试模块 +pytest tests/client/ -v +pytest tests/server/ -v +pytest tests/parse/ -v + # 运行特定测试文件 -pytest tests/test_parser.py +pytest tests/client/test_lifecycle.py + +# 运行特定测试 +pytest tests/client/test_lifecycle.py::TestClientInitialization::test_initialize_success + +# 按关键字运行 +pytest -k "search" -v # 运行并生成覆盖率报告 pytest --cov=openviking --cov-report=term-missing - -# 详细输出模式运行 -pytest -v ``` ### 编写测试 -将测试文件放在 `tests/` 目录下,命名为 `test_*.py`: +测试按模块组织在 `tests/` 的子目录中。项目使用 `asyncio_mode = "auto"`,异步测试**不需要** `@pytest.mark.asyncio` 装饰器: ```python -# tests/test_client.py -import pytest +# tests/client/test_example.py from openviking import AsyncOpenViking + class TestAsyncOpenViking: - @pytest.mark.asyncio - async def test_initialize(self, tmp_path): - client = AsyncOpenViking(path=str(tmp_path / "data")) - await client.initialize() - assert client._viking_fs is not None - await client.close() - - @pytest.mark.asyncio - async def test_add_resource(self, tmp_path): - client = AsyncOpenViking(path=str(tmp_path / "data")) - await client.initialize() + async def test_initialize(self, uninitialized_client: AsyncOpenViking): + await uninitialized_client.initialize() + assert uninitialized_client._service is not None + await uninitialized_client.close() + async def test_add_resource(self, client: AsyncOpenViking): result = await client.add_resource( "./test.md", reason="test document" ) assert result["status"] == "success" assert "root_uri" in result - - await client.close() ``` +常用 fixture 定义在 `tests/conftest.py` 中,包括 `client`(已初始化的 `AsyncOpenViking`)、`uninitialized_client`、`temp_dir` 等。 + --- ## 贡献流程 diff --git a/examples/k8s-helm/templates/deployment.yaml b/examples/k8s-helm/templates/deployment.yaml index 6adedee0..95427b7c 100644 --- a/examples/k8s-helm/templates/deployment.yaml +++ b/examples/k8s-helm/templates/deployment.yaml @@ -24,7 +24,7 @@ spec: - /bin/sh - -c - | - exec uv run --with openviking openviking serve \ + exec uv run --with openviking openviking-server \ --host {{ .Values.server.host }} \ --port {{ .Values.server.port }} \ --config /etc/openviking/ov.conf diff --git a/examples/multi_tenant/admin_workflow.sh b/examples/multi_tenant/admin_workflow.sh index 8d13628c..71f36bc9 100755 --- a/examples/multi_tenant/admin_workflow.sh +++ b/examples/multi_tenant/admin_workflow.sh @@ -10,7 +10,7 @@ # 1. Configure & start the server with root_api_key: # Copy ov.conf.example to ov.conf, fill in your model API keys, then: # -# openviking serve --config ./ov.conf +# openviking-server --config ./ov.conf # # The key config for multi-tenant auth: # { diff --git a/examples/server_client/README.md b/examples/server_client/README.md index fd9e47d6..e7da8876 100644 --- a/examples/server_client/README.md +++ b/examples/server_client/README.md @@ -23,9 +23,9 @@ uv sync # 参见 ov.conf.example 了解完整配置项 # 2. 启动 Server(另开终端) -openviking serve # 从默认路径读取 ov.conf -openviking serve --config ./ov.conf # 指定配置文件 -openviking serve --host 0.0.0.0 --port 1933 # 覆盖 host/port +openviking-server # 从默认路径读取 ov.conf +openviking-server --config ./ov.conf # 指定配置文件 +openviking-server --host 0.0.0.0 --port 1933 # 覆盖 host/port # 3. 配置 CLI 连接(ovcli.conf) # CLI 读取配置的优先级: @@ -89,16 +89,16 @@ pyproject.toml # 项目依赖 ```bash # 基本启动(从 ~/.openviking/ov.conf 或 $OPENVIKING_CONFIG_FILE 读取配置) -openviking serve +openviking-server # 指定配置文件 -openviking serve --config ./ov.conf +openviking-server --config ./ov.conf # 覆盖 host/port -openviking serve --host 0.0.0.0 --port 1933 +openviking-server --host 0.0.0.0 --port 1933 ``` -`serve` 命令支持 `--config`、`--host`、`--port` 三个选项。认证密钥等其他配置通过 ov.conf 的 `server` 段设置。 +`openviking-server` 命令支持 `--config`、`--host`、`--port` 三个选项。认证密钥等其他配置通过 ov.conf 的 `server` 段设置。 ### Python 脚本 diff --git a/examples/server_client/client_async.py b/examples/server_client/client_async.py index ea96854d..28715a58 100644 --- a/examples/server_client/client_async.py +++ b/examples/server_client/client_async.py @@ -5,7 +5,7 @@ 使用 AsyncHTTPClient 通过 HTTP 连接远程 Server,演示完整 API。 前置条件: - 先启动 Server: openviking serve + 先启动 Server: openviking-server 运行: uv run client_async.py diff --git a/examples/server_client/client_cli.sh b/examples/server_client/client_cli.sh index 691eed72..5ec71946 100755 --- a/examples/server_client/client_cli.sh +++ b/examples/server_client/client_cli.sh @@ -13,9 +13,9 @@ # b) ~/.openviking/ov.conf # default path # See ov.conf.example for template. # -# openviking serve # default: localhost:1933 -# openviking serve --port 8080 # custom port -# openviking serve --config /path/to/ov.conf # explicit config path +# openviking-server # default: localhost:1933 +# openviking-server --port 8080 # custom port +# openviking-server --config /path/to/ov.conf # explicit config path # # 2. Configure CLI connection (ovcli.conf): # CLI reads ovcli.conf from (priority high → low): diff --git a/examples/server_client/client_sync.py b/examples/server_client/client_sync.py index 797433e0..6a1d47c9 100644 --- a/examples/server_client/client_sync.py +++ b/examples/server_client/client_sync.py @@ -5,7 +5,7 @@ 使用 SyncHTTPClient 通过 HTTP 连接远程 Server,演示完整 API。 前置条件: - 先启动 Server: openviking serve + 先启动 Server: openviking-server 运行: uv run client_sync.py