From e30ef4a50897c88e5deef84c31943ac2d507bd1a Mon Sep 17 00:00:00 2001 From: qin-ctx Date: Thu, 12 Feb 2026 11:49:33 +0800 Subject: [PATCH 1/2] =?UTF-8?q?refactor(client):=20=E6=8B=86=E5=88=86=20HT?= =?UTF-8?q?TP=20=E5=AE=A2=E6=88=B7=E7=AB=AF=EF=BC=8C=E5=88=86=E7=A6=BB?= =?UTF-8?q?=E5=B5=8C=E5=85=A5=E6=A8=A1=E5=BC=8F=E4=B8=8E=20HTTP=20?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 HTTPClient 重命名为 AsyncHTTPClient,新增 SyncHTTPClient 同步封装 - AsyncOpenViking/SyncOpenViking 仅保留嵌入模式,HTTP 模式使用独立的 AsyncHTTPClient/SyncHTTPClient - HTTP 客户端支持从 ovcli.conf 自动加载 url/api_key - 移除客户端构造函数中的 user 参数,统一使用默认用户 - 简化 CLIContext,直接使用 SyncHTTPClient - 简化 VikingFS._uri_to_path 实现 - 更新文档、示例和测试适配新 API --- .../design/server_client/server-cli-design.md | 10 +- docs/en/api/01-overview.md | 89 +++++-- docs/en/api/02-resources.md | 43 +--- docs/en/api/03-filesystem.md | 126 +-------- docs/en/api/04-skills.md | 42 +-- docs/en/api/05-sessions.md | 55 +--- docs/en/api/06-retrieval.md | 43 +--- docs/en/api/07-system.md | 51 +--- docs/en/concepts/01-architecture.md | 2 +- docs/en/faq/faq.md | 8 +- docs/en/getting-started/02-quickstart.md | 52 +--- .../getting-started/03-quickstart-server.md | 6 +- docs/en/guides/01-configuration.md | 60 ++++- docs/en/guides/03-deployment.md | 2 +- docs/en/guides/04-authentication.md | 4 +- docs/en/guides/05-monitoring.md | 4 +- docs/zh/api/01-overview.md | 91 +++++-- docs/zh/api/02-resources.md | 43 +--- docs/zh/api/03-filesystem.md | 126 +-------- docs/zh/api/04-skills.md | 42 +-- docs/zh/api/05-sessions.md | 55 +--- docs/zh/api/06-retrieval.md | 43 +--- docs/zh/api/07-system.md | 51 +--- docs/zh/concepts/01-architecture.md | 2 +- docs/zh/faq/faq.md | 8 +- docs/zh/getting-started/02-quickstart.md | 52 +--- .../getting-started/03-quickstart-server.md | 6 +- docs/zh/guides/01-configuration.md | 77 +++++- docs/zh/guides/03-deployment.md | 2 +- docs/zh/guides/04-authentication.md | 4 +- docs/zh/guides/05-monitoring.md | 4 +- examples/chatmem/chatmem.py | 2 +- .../docs/2026-02-03-chatmem-implementation.md | 5 +- examples/chatmem/docs/COMPARISON.md | 2 +- examples/memex/cli.py | 5 +- examples/memex/client.py | 5 - examples/memex/config.py | 2 - examples/quick_start.py | 2 +- examples/server_client/README.md | 10 +- examples/server_client/client_async.py | 4 +- examples/server_client/client_cli.sh | 1 - examples/server_client/client_sync.py | 6 +- openviking/__init__.py | 4 + openviking/async_client.py | 55 +--- openviking/cli/context.py | 56 +--- openviking/client.py | 4 +- openviking/client/__init__.py | 8 +- openviking/client/base.py | 4 +- openviking/client/http.py | 49 +++- openviking/client/local.py | 4 +- openviking/client/session.py | 4 +- openviking/client/sync_http.py | 241 ++++++++++++++++++ openviking/storage/viking_fs.py | 15 +- tests/README.md | 4 +- tests/cli/test_cli.py | 6 +- tests/client/test_lifecycle.py | 13 +- tests/conftest.py | 5 +- tests/integration/conftest.py | 3 +- tests/integration/test_full_workflow.py | 3 +- tests/integration/test_http_integration.py | 53 ++-- tests/server/conftest.py | 2 +- tests/server/test_http_client_sdk.py | 10 +- 62 files changed, 791 insertions(+), 999 deletions(-) create mode 100644 openviking/client/sync_http.py diff --git a/docs/design/server_client/server-cli-design.md b/docs/design/server_client/server-cli-design.md index 477b8bc6..32ce0261 100644 --- a/docs/design/server_client/server-cli-design.md +++ b/docs/design/server_client/server-cli-design.md @@ -345,10 +345,10 @@ OpenViking 提供三种接口,面向不同使用场景: ```python # 构造函数参数 -client = OpenViking(url="http://localhost:1933", api_key="your-api-key", user="alice") +client = SyncHTTPClient(url="http://localhost:1933", api_key="your-api-key") ``` -SDK 构造函数只接受 `url`、`api_key`、`path`、`user` 参数。不支持 `config` 参数,也不支持 `vectordb_url`/`agfs_url` 参数。 +SDK 构造函数只接受 `url`、`api_key`、`path` 参数。不支持 `config` 参数,也不支持 `vectordb_url`/`agfs_url` 参数。 #### CLI 配置 @@ -358,7 +358,6 @@ CLI 通过 `ovcli.conf` 配置文件管理连接信息,不使用 `--url`、`-- { "url": "http://localhost:1933", "api_key": "sk-xxx", - "user": "alice", "output": "table" } ``` @@ -652,7 +651,7 @@ class UsageInfo: **session**(Python CLI 返回 Session 对象,HTTP API 返回 JSON) ```python # Python CLI -session = client.session(user="alice") +session = client.session() session.id # "session-abc123" session.user # "alice" session.created_at # datetime @@ -871,7 +870,6 @@ export OPENVIKING_CLI_CONFIG_FILE=~/.openviking/ovcli.conf # { # "url": "http://localhost:1933", # "api_key": "sk-xxx", -# "user": "alice", # "output": "table" # } @@ -1024,7 +1022,7 @@ for r in results.data.results: print(f"{r.uri}: {r.score:.2f}") # 会话管理(OOP 模式) -session = client.session(user="alice") +session = client.session() session.add_message("user", "What is OpenViking?") results = client.search("What is OpenViking?", session=session) diff --git a/docs/en/api/01-overview.md b/docs/en/api/01-overview.md index 0fcde97b..3d8b49d8 100644 --- a/docs/en/api/01-overview.md +++ b/docs/en/api/01-overview.md @@ -21,31 +21,52 @@ client = ov.OpenViking(path="./data") client.initialize() ``` +Embedded mode uses `ov.conf` to configure embedding, vlm, storage, and other modules. Default path: `~/.openviking/ov.conf`. You can also specify the path via environment variable: + +```bash +export OPENVIKING_CONFIG_FILE=/path/to/ov.conf +``` + +Minimal configuration example: + +```json +{ + "embedding": { + "dense": { + "api_base": "", + "api_key": "", + "provider": "", + "dimension": 1024, + "model": "" + } + }, + "vlm": { + "api_base": "", + "api_key": "", + "provider": "", + "model": "" + } +} +``` + +For full configuration options and provider-specific examples, see the [Configuration Guide](../guides/01-configuration.md). + ### HTTP Mode ```python -client = ov.OpenViking( +client = ov.SyncHTTPClient( url="http://localhost:1933", api_key="your-key", ) client.initialize() ``` -### Direct HTTP (curl) +When `url` is not explicitly provided, the HTTP client automatically loads connection info from `ovcli.conf`. This config file is shared between the HTTP client and CLI. Default path: `~/.openviking/ovcli.conf`. You can also specify the path via environment variable: ```bash -curl http://localhost:1933/api/v1/fs/ls?uri=viking:// \ - -H "X-API-Key: your-key" +export OPENVIKING_CLI_CONFIG_FILE=/path/to/ovcli.conf ``` -### CLI Mode - -The CLI connects to an OpenViking server and exposes all operations as shell commands. - -**Configuration** - -Create `~/.openviking/ovcli.conf` (or set `OPENVIKING_CLI_CONFIG_FILE` environment variable): - ```json { "url": "http://localhost:1933", @@ -53,6 +74,25 @@ Create `~/.openviking/ovcli.conf` (or set `OPENVIKING_CLI_CONFIG_FILE` environme } ``` +| Field | Description | Default | +|-------|-------------|---------| +| `url` | Server address | (required) | +| `api_key` | API key | `null` (no auth) | +| `output` | Default output format: `"table"` or `"json"` | `"table"` | + +See the [Configuration Guide](../guides/01-configuration.md#ovcliconf) for details. + +### Direct HTTP (curl) + +```bash +curl http://localhost:1933/api/v1/fs/ls?uri=viking:// \ + -H "X-API-Key: your-key" +``` + +### CLI Mode + +The CLI connects to an OpenViking server and exposes all operations as shell commands. The CLI also loads connection info from `ovcli.conf` (shared with the HTTP client). + **Basic Usage** ```bash @@ -74,15 +114,32 @@ openviking --json ls viking://resources/ openviking -o json ls viking://resources/ ``` -## Client Lifecycle +## Lifecycle + +**Embedded Mode** ```python -client = ov.OpenViking(path="./data") # or url="http://..." -client.initialize() # Required before any operations +import openviking as ov + +client = ov.OpenViking(path="./data") +client.initialize() + +# ... use client ... + +client.close() +``` + +**HTTP Mode** + +```python +import openviking as ov + +client = ov.SyncHTTPClient(url="http://localhost:1933") +client.initialize() # ... use client ... -client.close() # Release resources +client.close() ``` ## Authentication diff --git a/docs/en/api/02-resources.md b/docs/en/api/02-resources.md index 33ec8f04..eff4d56f 100644 --- a/docs/en/api/02-resources.md +++ b/docs/en/api/02-resources.md @@ -46,14 +46,9 @@ Add a resource to the knowledge base. | wait | bool | No | False | Wait for semantic processing to complete | | timeout | float | No | None | Timeout in seconds (only used when wait=True) | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - result = client.add_resource( "./documents/guide.md", reason="User guide documentation" @@ -61,7 +56,6 @@ result = client.add_resource( print(f"Added: {result['root_uri']}") client.wait_processed() -client.close() ``` **HTTP API** @@ -103,7 +97,7 @@ openviking add-resource ./documents/guide.md --reason "User guide documentation" **Example: Add from URL** -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python result = client.add_resource( @@ -136,7 +130,7 @@ openviking add-resource https://example.com/api-docs.md --to viking://resources/ **Example: Wait for Processing** -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # Option 1: Wait inline @@ -187,21 +181,14 @@ Export a resource tree as a `.ovpack` file. | uri | str | Yes | - | Viking URI to export | | to | str | Yes | - | Target file path | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - path = client.export_ovpack( "viking://resources/my-project/", "./exports/my-project.ovpack" ) print(f"Exported to: {path}") - -client.close() ``` **HTTP API** @@ -253,14 +240,9 @@ Import a `.ovpack` file. | force | bool | No | False | Overwrite existing resources | | vectorize | bool | No | True | Trigger vectorization after import | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - uri = client.import_ovpack( "./exports/my-project.ovpack", "viking://resources/imported/", @@ -270,7 +252,6 @@ uri = client.import_ovpack( print(f"Imported to: {uri}") client.wait_processed() -client.close() ``` **HTTP API** @@ -315,7 +296,7 @@ openviking import ./exports/my-project.ovpack viking://resources/imported/ --for ### List Resources -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # List all resources @@ -388,7 +369,7 @@ openviking ls viking://resources/ --recursive ### Read Resource Content -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # L0: Abstract @@ -444,7 +425,7 @@ openviking read viking://resources/docs/api.md ### Move Resources -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python client.mv( @@ -492,7 +473,7 @@ openviking mv viking://resources/old-project/ viking://resources/new-project/ ### Delete Resources -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # Delete single file @@ -544,7 +525,7 @@ openviking rm viking://resources/old-project/ --recursive ### Create Links -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # Link related resources @@ -616,7 +597,7 @@ openviking link viking://resources/docs/auth/ viking://resources/docs/security/ ### Get Relations -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python relations = client.relations("viking://resources/docs/auth/") @@ -658,7 +639,7 @@ openviking relations viking://resources/docs/auth/ ### Remove Links -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python client.unlink( diff --git a/docs/en/api/03-filesystem.md b/docs/en/api/03-filesystem.md index a4dac8ca..e1a762e2 100644 --- a/docs/en/api/03-filesystem.md +++ b/docs/en/api/03-filesystem.md @@ -14,19 +14,12 @@ Read L0 abstract (~100 tokens summary). |-----------|------|----------|---------|-------------| | uri | str | Yes | - | Viking URI (must be a directory) | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - abstract = client.abstract("viking://resources/docs/") print(f"Abstract: {abstract}") # Output: "Documentation for the project API, covering authentication, endpoints..." - -client.close() ``` **HTTP API** @@ -68,18 +61,11 @@ Read L1 overview, applies to directories. |-----------|------|----------|---------|-------------| | uri | str | Yes | - | Viking URI (must be a directory) | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - overview = client.overview("viking://resources/docs/") print(f"Overview:\n{overview}") - -client.close() ``` **HTTP API** @@ -121,18 +107,11 @@ Read L2 full content. |-----------|------|----------|---------|-------------| | uri | str | Yes | - | Viking URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - content = client.read("viking://resources/docs/api.md") print(f"Content:\n{content}") - -client.close() ``` **HTTP API** @@ -190,20 +169,13 @@ List directory contents. } ``` -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - entries = client.ls("viking://resources/") for entry in entries: type_str = "dir" if entry['isDir'] else "file" print(f"{entry['name']} - {type_str}") - -client.close() ``` **HTTP API** @@ -263,20 +235,13 @@ Get directory tree structure. |-----------|------|----------|---------|-------------| | uri | str | Yes | - | Viking URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - entries = client.tree("viking://resources/") for entry in entries: type_str = "dir" if entry['isDir'] else "file" print(f"{entry['rel_path']} - {type_str}") - -client.close() ``` **HTTP API** @@ -333,19 +298,12 @@ Get file or directory status information. |-----------|------|----------|---------|-------------| | uri | str | Yes | - | Viking URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - info = client.stat("viking://resources/docs/api.md") print(f"Size: {info['size']}") print(f"Is directory: {info['isDir']}") - -client.close() ``` **HTTP API** @@ -394,17 +352,10 @@ Create a directory. |-----------|------|----------|---------|-------------| | uri | str | Yes | - | Viking URI for the new directory | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - client.mkdir("viking://resources/new-project/") - -client.close() ``` **HTTP API** @@ -453,21 +404,14 @@ Remove file or directory. | uri | str | Yes | - | Viking URI to remove | | recursive | bool | No | False | Remove directory recursively | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # Remove single file client.rm("viking://resources/docs/old.md") # Remove directory recursively client.rm("viking://resources/old-project/", recursive=True) - -client.close() ``` **HTTP API** @@ -517,20 +461,13 @@ Move file or directory. | from_uri | str | Yes | - | Source Viking URI | | to_uri | str | Yes | - | Destination Viking URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - client.mv( "viking://resources/old-name/", "viking://resources/new-name/" ) - -client.close() ``` **HTTP API** @@ -582,14 +519,9 @@ Search content by pattern. | pattern | str | Yes | - | Search pattern (regex) | | case_insensitive | bool | No | False | Ignore case | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - results = client.grep( "viking://resources/", "authentication", @@ -600,8 +532,6 @@ print(f"Found {results['count']} matches") for match in results['matches']: print(f" {match['uri']}:{match['line']}") print(f" {match['content']}") - -client.close() ``` **HTTP API** @@ -659,14 +589,9 @@ Match files by pattern. | pattern | str | Yes | - | Glob pattern (e.g., `**/*.md`) | | uri | str | No | "viking://" | Starting URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # Find all markdown files results = client.glob("**/*.md", "viking://resources/") print(f"Found {results['count']} markdown files:") @@ -676,8 +601,6 @@ for uri in results['matches']: # Find all Python files results = client.glob("**/*.py", "viking://resources/") print(f"Found {results['count']} Python files") - -client.close() ``` **HTTP API** @@ -732,14 +655,9 @@ Create relations between resources. | uris | str or List[str] | Yes | - | Target URI(s) | | reason | str | No | "" | Reason for the link | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # Single link client.link( "viking://resources/docs/auth/", @@ -756,8 +674,6 @@ client.link( ], reason="Related documentation" ) - -client.close() ``` **HTTP API** @@ -819,20 +735,13 @@ Get relations for a resource. |-----------|------|----------|---------|-------------| | uri | str | Yes | - | Viking URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - relations = client.relations("viking://resources/docs/auth/") for rel in relations: print(f"Related: {rel['uri']}") print(f" Reason: {rel['reason']}") - -client.close() ``` **HTTP API** @@ -878,20 +787,13 @@ Remove a relation. | from_uri | str | Yes | - | Source URI | | uri | str | Yes | - | Target URI to unlink | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - client.unlink( "viking://resources/docs/auth/", "viking://resources/docs/security/" ) - -client.close() ``` **HTTP API** diff --git a/docs/en/api/04-skills.md b/docs/en/api/04-skills.md index de3f0516..9d036085 100644 --- a/docs/en/api/04-skills.md +++ b/docs/en/api/04-skills.md @@ -57,14 +57,9 @@ description: Skill description - Single file: Path to `SKILL.md` file - Directory: Path to directory containing `SKILL.md` (auxiliary files included) -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - skill = { "name": "search-web", "description": "Search the web for current information", @@ -81,8 +76,6 @@ Search the web for current information. result = client.add_skill(skill) print(f"Added: {result['uri']}") - -client.close() ``` **HTTP API** @@ -127,14 +120,9 @@ openviking add-skill ./my-skill/ [--wait] **Example: Add from MCP Tool** -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # MCP tool format is auto-detected and converted mcp_tool = { "name": "calculator", @@ -153,8 +141,6 @@ mcp_tool = { result = client.add_skill(mcp_tool) print(f"Added: {result['uri']}") - -client.close() ``` **HTTP API** @@ -183,14 +169,9 @@ curl -X POST http://localhost:1933/api/v1/skills \ **Example: Add from SKILL.md File** -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # Add from file path result = client.add_skill("./skills/search-web/SKILL.md") print(f"Added: {result['uri']}") @@ -199,8 +180,6 @@ print(f"Added: {result['uri']}") result = client.add_skill("./skills/code-runner/") print(f"Added: {result['uri']}") print(f"Auxiliary files: {result['auxiliary_files']}") - -client.close() ``` **HTTP API** @@ -269,14 +248,9 @@ Concrete examples of skill invocation. ### List Skills -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # List all skills skills = client.ls("viking://agent/skills/") for skill in skills: @@ -285,8 +259,6 @@ for skill in skills: # Simple list (names only) names = client.ls("viking://agent/skills/", simple=True) print(names) - -client.close() ``` **HTTP API** @@ -298,7 +270,7 @@ curl -X GET "http://localhost:1933/api/v1/fs/ls?uri=viking://agent/skills/" \ ### Read Skill Content -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python uri = "viking://agent/skills/search-web/" @@ -334,7 +306,7 @@ curl -X GET "http://localhost:1933/api/v1/content/read?uri=viking://agent/skills ### Search Skills -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # Semantic search for skills @@ -365,7 +337,7 @@ curl -X POST http://localhost:1933/api/v1/search/find \ ### Remove Skills -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python client.rm("viking://agent/skills/old-skill/", recursive=True) diff --git a/docs/en/api/05-sessions.md b/docs/en/api/05-sessions.md index 1c8d266d..d2ff520d 100644 --- a/docs/en/api/05-sessions.md +++ b/docs/en/api/05-sessions.md @@ -14,19 +14,12 @@ Create a new session. |-----------|------|----------|---------|-------------| | session_id | str | No | None | Session ID. Creates new session with auto-generated ID if None | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data", user="alice") -client.initialize() - # Create new session (auto-generated ID) session = client.session() print(f"Session URI: {session.uri}") - -client.close() ``` **HTTP API** @@ -66,19 +59,12 @@ openviking session new List all sessions. -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - sessions = client.ls("viking://session/") for s in sessions: print(f"{s['name']}") - -client.close() ``` **HTTP API** @@ -123,20 +109,13 @@ Get session details. |-----------|------|----------|---------|-------------| | session_id | str | Yes | - | Session ID | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # Load existing session session = client.session(session_id="a1b2c3d4") session.load() print(f"Loaded {len(session.messages)} messages") - -client.close() ``` **HTTP API** @@ -182,17 +161,10 @@ Delete a session. |-----------|------|----------|---------|-------------| | session_id | str | Yes | - | Session ID to delete | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - client.rm("viking://session/a1b2c3d4/", recursive=True) - -client.close() ``` **HTTP API** @@ -264,15 +236,11 @@ ToolPart( ) ``` -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov from openviking.message import TextPart -client = ov.OpenViking(path="./data") -client.initialize() - session = client.session() # Add user message @@ -284,8 +252,6 @@ session.add_message("user", [ session.add_message("assistant", [ TextPart(text="You can use OAuth 2.0 for authentication...") ]) - -client.close() ``` **HTTP API** @@ -345,14 +311,9 @@ Commit a session by archiving messages and extracting memories. |-----------|------|----------|---------|-------------| | session_id | str | Yes | - | Session ID to commit | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - session = client.session(session_id="a1b2c3d4") session.load() @@ -360,8 +321,6 @@ session.load() result = session.commit() print(f"Status: {result['status']}") print(f"Memories extracted: {result['memories_extracted']}") - -client.close() ``` **HTTP API** @@ -447,7 +406,7 @@ viking://session/{session_id}/ ## Full Example -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python import openviking as ov diff --git a/docs/en/api/06-retrieval.md b/docs/en/api/06-retrieval.md index 8685e915..b7b11ba1 100644 --- a/docs/en/api/06-retrieval.md +++ b/docs/en/api/06-retrieval.md @@ -54,14 +54,9 @@ class MatchedContext: relations: List[RelatedContext] # Related contexts ``` -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - results = client.find("how to authenticate users") for ctx in results.resources: @@ -70,8 +65,6 @@ for ctx in results.resources: print(f"Type: {ctx.context_type}") print(f"Abstract: {ctx.abstract[:100]}...") print("---") - -client.close() ``` **HTTP API** @@ -122,7 +115,7 @@ openviking find "how to authenticate users" [--uri viking://resources/] [--limit **Example: Search with Target URI** -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # Search only in resources @@ -192,15 +185,11 @@ Search with session context and intent analysis. | score_threshold | float | No | None | Minimum relevance score threshold | | filter | Dict | No | None | Metadata filters | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov from openviking.message import TextPart -client = ov.OpenViking(path="./data") -client.initialize() - # Create session with conversation context session = client.session() session.add_message("user", [ @@ -219,8 +208,6 @@ results = client.search( for ctx in results.resources: print(f"Found: {ctx.uri}") print(f"Abstract: {ctx.abstract[:200]}...") - -client.close() ``` **HTTP API** @@ -275,7 +262,7 @@ openviking search "best practices" [--session-id abc123] [--limit 10] **Example: Search Without Session** -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # search can also be used without session @@ -313,14 +300,9 @@ Search content by pattern (regex). | pattern | str | Yes | - | Search pattern (regex) | | case_insensitive | bool | No | False | Ignore case | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - results = client.grep( "viking://resources/", "authentication", @@ -331,8 +313,6 @@ print(f"Found {results['count']} matches") for match in results['matches']: print(f" {match['uri']}:{match['line']}") print(f" {match['content']}") - -client.close() ``` **HTTP API** @@ -390,14 +370,9 @@ Match files by glob pattern. | pattern | str | Yes | - | Glob pattern (e.g., `**/*.md`) | | uri | str | No | "viking://" | Starting URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # Find all markdown files results = client.glob("**/*.md", "viking://resources/") print(f"Found {results['count']} markdown files:") @@ -407,8 +382,6 @@ for uri in results['matches']: # Find all Python files results = client.glob("**/*.py", "viking://resources/") print(f"Found {results['count']} Python files") - -client.close() ``` **HTTP API** @@ -466,7 +439,7 @@ Query -> Intent Analysis -> Vector Search (L0) -> Rerank (L1) -> Results ### Read Content Progressively -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python results = client.find("authentication") @@ -505,7 +478,7 @@ curl -X GET "http://localhost:1933/api/v1/content/read?uri=viking://resources/do ### Get Related Resources -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python results = client.find("OAuth implementation") diff --git a/docs/en/api/07-system.md b/docs/en/api/07-system.md index acfe80b8..79ad5558 100644 --- a/docs/en/api/07-system.md +++ b/docs/en/api/07-system.md @@ -8,19 +8,12 @@ OpenViking provides system health, observability, and debug APIs for monitoring Basic health check endpoint. No authentication required. -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # Check if system is healthy if client.observer.is_healthy(): print("System OK") - -client.close() ``` **HTTP API** @@ -53,17 +46,10 @@ openviking health Get system status including initialization state and user info. -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - print(client.observer.system) - -client.close() ``` **HTTP API** @@ -108,22 +94,15 @@ Wait for all asynchronous processing (embedding, semantic generation) to complet |-----------|------|----------|---------|-------------| | timeout | float | No | None | Timeout in seconds | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # Add resources client.add_resource("./docs/") # Wait for all processing to complete status = client.wait_processed() print(f"Processing complete: {status}") - -client.close() ``` **HTTP API** @@ -172,14 +151,9 @@ The observer API provides detailed component-level monitoring. Get queue system status (embedding and semantic processing queues). -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - print(client.observer.queue) # Output: # [queue] (healthy) @@ -187,8 +161,6 @@ print(client.observer.queue) # Embedding 0 0 10 0 10 # Semantic 0 0 10 0 10 # TOTAL 0 0 20 0 20 - -client.close() ``` **HTTP API** @@ -229,7 +201,7 @@ openviking observer queue Get VikingDB status (collections, indexes, vector counts). -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python print(client.observer.vikingdb) @@ -282,7 +254,7 @@ openviking observer vikingdb Get VLM (Vision Language Model) token usage status. -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python print(client.observer.vlm) @@ -331,7 +303,7 @@ openviking observer vlm Get overall system status including all components. -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python print(client.observer.system) @@ -404,20 +376,13 @@ openviking observer system Quick health check for the entire system. -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - if client.observer.is_healthy(): print("System OK") else: print(client.observer.system) - -client.close() ``` **HTTP API** diff --git a/docs/en/concepts/01-architecture.md b/docs/en/concepts/01-architecture.md index 1c88186f..88a136f1 100644 --- a/docs/en/concepts/01-architecture.md +++ b/docs/en/concepts/01-architecture.md @@ -140,7 +140,7 @@ For team sharing, production deployment, and cross-language integration: ```python # Python SDK connects to OpenViking Server -client = OpenViking(url="http://localhost:1933", api_key="xxx") +client = SyncHTTPClient(url="http://localhost:1933", api_key="xxx") ``` ```bash diff --git a/docs/en/faq/faq.md b/docs/en/faq/faq.md index f5b41558..4cc8a9f9 100644 --- a/docs/en/faq/faq.md +++ b/docs/en/faq/faq.md @@ -124,11 +124,11 @@ client = ov.AsyncOpenViking(path="./my_data") await client.initialize() # Async client - HTTP client mode -client = ov.AsyncOpenViking(url="http://localhost:1933", api_key="your-key") +client = ov.AsyncHTTPClient(url="http://localhost:1933", api_key="your-key") await client.initialize() ``` -The SDK constructor only accepts `url`, `api_key`, `path`, and `user` parameters. Other configuration (embedding, vlm, etc.) is managed through the `ov.conf` config file. +The SDK constructor only accepts `url`, `api_key`, and `path` parameters. Other configuration (embedding, vlm, etc.) is managed through the `ov.conf` config file. ### What file formats are supported? @@ -347,7 +347,7 @@ This strategy finds semantically matching fragments while understanding the comp 1. **Batch processing**: Adding multiple resources at once is more efficient than one by one 2. **Set appropriate `batch_size`**: Adjust batch processing size in Embedding configuration 3. **Use local storage**: Use `local` backend during development to reduce network latency -4. **Async operations**: Fully utilize `AsyncOpenViking`'s async capabilities +4. **Async operations**: Fully utilize `AsyncOpenViking` / `AsyncHTTPClient`'s async capabilities ## Deployment @@ -363,7 +363,7 @@ This strategy finds semantically matching fragments while understanding the comp client = ov.AsyncOpenViking(path="./data") # HTTP client mode (connects to a remote server) -client = ov.AsyncOpenViking(url="http://localhost:1933", api_key="your-key") +client = ov.AsyncHTTPClient(url="http://localhost:1933", api_key="your-key") ``` ### Is OpenViking open source? diff --git a/docs/en/getting-started/02-quickstart.md b/docs/en/getting-started/02-quickstart.md index 373751c6..2edec0f4 100644 --- a/docs/en/getting-started/02-quickstart.md +++ b/docs/en/getting-started/02-quickstart.md @@ -53,57 +53,7 @@ Create a configuration file `~/.openviking/ov.conf`: } ``` -### Configuration Examples - -
-Example 1: Using Volcengine (Doubao Models) - -```json -{ - "embedding": { - "dense": { - "api_base" : "https://ark.cn-beijing.volces.com/api/v3", - "api_key" : "your-volcengine-api-key", - "provider" : "volcengine", - "dimension": 1024, - "model" : "doubao-embedding-vision-250615" - } - }, - "vlm": { - "api_base" : "https://ark.cn-beijing.volces.com/api/v3", - "api_key" : "your-volcengine-api-key", - "provider" : "volcengine", - "model" : "doubao-seed-1-8-251228" - } -} -``` - -
- -
-Example 2: Using OpenAI Models - -```json -{ - "embedding": { - "dense": { - "api_base" : "https://api.openai.com/v1", - "api_key" : "your-openai-api-key", - "provider" : "openai", - "dimension": 3072, - "model" : "text-embedding-3-large" - } - }, - "vlm": { - "api_base" : "https://api.openai.com/v1", - "api_key" : "your-openai-api-key", - "provider" : "openai", - "model" : "gpt-4-vision-preview" - } -} -``` - -
+For complete examples for each model provider, see [Configuration Guide - Examples](../guides/01-configuration.md#configuration-examples). ### Environment Variables diff --git a/docs/en/getting-started/03-quickstart-server.md b/docs/en/getting-started/03-quickstart-server.md index 3876045e..8f617bf0 100644 --- a/docs/en/getting-started/03-quickstart-server.md +++ b/docs/en/getting-started/03-quickstart-server.md @@ -40,7 +40,7 @@ curl http://localhost:1933/health ```python import openviking as ov -client = ov.OpenViking(url="http://localhost:1933") +client = ov.SyncHTTPClient(url="http://localhost:1933") ``` If the server has authentication enabled, pass the API key: @@ -48,7 +48,7 @@ If the server has authentication enabled, pass the API key: ```python import openviking as ov -client = ov.OpenViking(url="http://localhost:1933", api_key="your-key") +client = ov.SyncHTTPClient(url="http://localhost:1933", api_key="your-key") ``` **Full example:** @@ -56,7 +56,7 @@ client = ov.OpenViking(url="http://localhost:1933", api_key="your-key") ```python import openviking as ov -client = ov.OpenViking(url="http://localhost:1933") +client = ov.SyncHTTPClient(url="http://localhost:1933") try: client.initialize() diff --git a/docs/en/guides/01-configuration.md b/docs/en/guides/01-configuration.md index 6049f0a1..6442210e 100644 --- a/docs/en/guides/01-configuration.md +++ b/docs/en/guides/01-configuration.md @@ -39,6 +39,59 @@ Create `~/.openviking/ov.conf` in your project directory: } ``` +## Configuration Examples + +
+Volcengine (Doubao Models) + +```json +{ + "embedding": { + "dense": { + "api_base" : "https://ark.cn-beijing.volces.com/api/v3", + "api_key" : "your-volcengine-api-key", + "provider" : "volcengine", + "dimension": 1024, + "model" : "doubao-embedding-vision-250615", + "input": "multimodal" + } + }, + "vlm": { + "api_base" : "https://ark.cn-beijing.volces.com/api/v3", + "api_key" : "your-volcengine-api-key", + "provider" : "volcengine", + "model" : "doubao-seed-1-8-251228" + } +} +``` + +
+ +
+OpenAI Models + +```json +{ + "embedding": { + "dense": { + "api_base" : "https://api.openai.com/v1", + "api_key" : "your-openai-api-key", + "provider" : "openai", + "dimension": 3072, + "model" : "text-embedding-3-large" + } + }, + "vlm": { + "api_base" : "https://api.openai.com/v1", + "api_key" : "your-openai-api-key", + "provider" : "openai", + "model" : "gpt-4-vision-preview" + } +} +``` + +
+ ## Configuration Sections ### embedding @@ -241,7 +294,7 @@ OpenViking uses two config files: | File | Purpose | Default Path | |------|---------|-------------| | `ov.conf` | SDK embedded mode + server config | `~/.openviking/ov.conf` | -| `ovcli.conf` | CLI connection to remote server | `~/.openviking/ovcli.conf` | +| `ovcli.conf` | HTTP client and CLI connection to remote server | `~/.openviking/ovcli.conf` | When config files are at the default path, OpenViking loads them automatically — no additional setup needed. @@ -262,7 +315,7 @@ The config sections documented above (embedding, vlm, rerank, storage) all belon ### ovcli.conf -Config file for CLI to connect to a remote server: +Config file for the HTTP client (`SyncHTTPClient` / `AsyncHTTPClient`) and CLI to connect to a remote server: ```json { @@ -346,8 +399,7 @@ For startup and deployment details see [Deployment](./03-deployment.md), for aut "port": 1933, "api_key": "string", "cors_origins": ["*"] - }, - "user": "string" + } } ``` diff --git a/docs/en/guides/03-deployment.md b/docs/en/guides/03-deployment.md index b44547ec..5141247c 100644 --- a/docs/en/guides/03-deployment.md +++ b/docs/en/guides/03-deployment.md @@ -101,7 +101,7 @@ python -m openviking serve ```python import openviking as ov -client = ov.OpenViking(url="http://localhost:1933", api_key="your-key") +client = ov.SyncHTTPClient(url="http://localhost:1933", api_key="your-key") client.initialize() results = client.find("how to use openviking") diff --git a/docs/en/guides/04-authentication.md b/docs/en/guides/04-authentication.md index b91e6433..335ede61 100644 --- a/docs/en/guides/04-authentication.md +++ b/docs/en/guides/04-authentication.md @@ -40,12 +40,12 @@ curl http://localhost:1933/api/v1/fs/ls?uri=viking:// \ -H "Authorization: Bearer your-secret-key" ``` -**Python SDK** +**Python SDK (HTTP)** ```python import openviking as ov -client = ov.OpenViking( +client = ov.SyncHTTPClient( url="http://localhost:1933", api_key="your-secret-key" ) diff --git a/docs/en/guides/05-monitoring.md b/docs/en/guides/05-monitoring.md index d89f4ee7..90f0ea69 100644 --- a/docs/en/guides/05-monitoring.md +++ b/docs/en/guides/05-monitoring.md @@ -18,7 +18,7 @@ curl http://localhost:1933/health ### Overall System Health -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python status = client.get_status() @@ -60,7 +60,7 @@ Check individual components: ### Quick Health Check -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python if client.is_healthy(): diff --git a/docs/zh/api/01-overview.md b/docs/zh/api/01-overview.md index 560afc6b..29bec07f 100644 --- a/docs/zh/api/01-overview.md +++ b/docs/zh/api/01-overview.md @@ -21,31 +21,52 @@ client = ov.OpenViking(path="./data") client.initialize() ``` +嵌入式模式通过 `ov.conf` 配置 embedding、vlm、storage 等模块。默认路径 `~/.openviking/ov.conf`,也可通过环境变量指定: + +```bash +export OPENVIKING_CONFIG_FILE=/path/to/ov.conf +``` + +最小配置示例: + +```json +{ + "embedding": { + "dense": { + "api_base": "", + "api_key": "", + "provider": "", + "dimension": 1024, + "model": "" + } + }, + "vlm": { + "api_base": "", + "api_key": "", + "provider": "", + "model": "" + } +} +``` + +完整配置选项和各服务商示例见 [配置指南](../guides/01-configuration.md)。 + ### HTTP 模式 ```python -client = ov.OpenViking( +client = ov.SyncHTTPClient( url="http://localhost:1933", api_key="your-key", ) client.initialize() ``` -### 直接 HTTP(curl) +未显式传入 `url` 时,HTTP 客户端会自动从 `ovcli.conf` 读取连接信息。`ovcli.conf` 是 HTTP 客户端和 CLI 共享的配置文件,默认路径 `~/.openviking/ovcli.conf`,也可通过环境变量指定: ```bash -curl http://localhost:1933/api/v1/fs/ls?uri=viking:// \ - -H "X-API-Key: your-key" +export OPENVIKING_CLI_CONFIG_FILE=/path/to/ovcli.conf ``` -### CLI 模式 - -CLI 连接到 OpenViking 服务端,将所有操作暴露为 Shell 命令。 - -**配置** - -创建 `~/.openviking/ovcli.conf`(或设置 `OPENVIKING_CLI_CONFIG_FILE` 环境变量): - ```json { "url": "http://localhost:1933", @@ -53,6 +74,25 @@ CLI 连接到 OpenViking 服务端,将所有操作暴露为 Shell 命令。 } ``` +| 字段 | 说明 | 默认值 | +|------|------|--------| +| `url` | 服务端地址 | (必填) | +| `api_key` | API Key | `null`(无认证) | +| `output` | 默认输出格式:`"table"` 或 `"json"` | `"table"` | + +详见 [配置指南](../guides/01-configuration.md#ovcliconf)。 + +### 直接 HTTP(curl) + +```bash +curl http://localhost:1933/api/v1/fs/ls?uri=viking:// \ + -H "X-API-Key: your-key" +``` + +### CLI 模式 + +CLI 连接到 OpenViking 服务端,将所有操作暴露为 Shell 命令。CLI 同样从 `ovcli.conf` 读取连接信息(与 HTTP 客户端共享)。 + **基本用法** ```bash @@ -74,15 +114,32 @@ openviking --json ls viking://resources/ openviking -o json ls viking://resources/ ``` -## 客户端生命周期 +## 生命周期 + +**嵌入式模式** ```python -client = ov.OpenViking(path="./data") # or url="http://..." -client.initialize() # Required before any operations +import openviking as ov + +client = ov.OpenViking(path="./data") +client.initialize() + +# ... 使用 client ... + +client.close() +``` + +**HTTP 模式** + +```python +import openviking as ov + +client = ov.SyncHTTPClient(url="http://localhost:1933") +client.initialize() -# ... use client ... +# ... 使用 client ... -client.close() # Release resources +client.close() ``` ## 认证 diff --git a/docs/zh/api/02-resources.md b/docs/zh/api/02-resources.md index 5887e6fc..440e2fa3 100644 --- a/docs/zh/api/02-resources.md +++ b/docs/zh/api/02-resources.md @@ -46,14 +46,9 @@ Input -> Parser -> TreeBuilder -> AGFS -> SemanticQueue -> Vector Index | wait | bool | 否 | False | 等待语义处理完成 | | timeout | float | 否 | None | 超时时间(秒),仅在 wait=True 时生效 | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - result = client.add_resource( "./documents/guide.md", reason="User guide documentation" @@ -61,7 +56,6 @@ result = client.add_resource( print(f"Added: {result['root_uri']}") client.wait_processed() -client.close() ``` **HTTP API** @@ -103,7 +97,7 @@ openviking add-resource ./documents/guide.md --reason "User guide documentation" **示例:从 URL 添加** -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python result = client.add_resource( @@ -136,7 +130,7 @@ openviking add-resource https://example.com/api-docs.md --to viking://resources/ **示例:等待处理完成** -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # 方式 1:内联等待 @@ -187,21 +181,14 @@ openviking add-resource ./documents/guide.md --wait | uri | str | 是 | - | 要导出的 Viking URI | | to | str | 是 | - | 目标文件路径 | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - path = client.export_ovpack( "viking://resources/my-project/", "./exports/my-project.ovpack" ) print(f"Exported to: {path}") - -client.close() ``` **HTTP API** @@ -253,14 +240,9 @@ openviking export viking://resources/my-project/ ./exports/my-project.ovpack | force | bool | 否 | False | 覆盖已有资源 | | vectorize | bool | 否 | True | 导入后触发向量化 | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - uri = client.import_ovpack( "./exports/my-project.ovpack", "viking://resources/imported/", @@ -270,7 +252,6 @@ uri = client.import_ovpack( print(f"Imported to: {uri}") client.wait_processed() -client.close() ``` **HTTP API** @@ -315,7 +296,7 @@ openviking import ./exports/my-project.ovpack viking://resources/imported/ --for ### 列出资源 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # 列出所有资源 @@ -388,7 +369,7 @@ openviking ls viking://resources/ --recursive ### 读取资源内容 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # L0:摘要 @@ -444,7 +425,7 @@ openviking read viking://resources/docs/api.md ### 移动资源 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python client.mv( @@ -492,7 +473,7 @@ openviking mv viking://resources/old-project/ viking://resources/new-project/ ### 删除资源 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # 删除单个文件 @@ -544,7 +525,7 @@ openviking rm viking://resources/old-project/ --recursive ### 创建链接 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # 链接相关资源 @@ -616,7 +597,7 @@ openviking link viking://resources/docs/auth/ viking://resources/docs/security/ ### 获取关联 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python relations = client.relations("viking://resources/docs/auth/") @@ -658,7 +639,7 @@ openviking relations viking://resources/docs/auth/ ### 删除链接 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python client.unlink( diff --git a/docs/zh/api/03-filesystem.md b/docs/zh/api/03-filesystem.md index 871cc8ed..75c94f9a 100644 --- a/docs/zh/api/03-filesystem.md +++ b/docs/zh/api/03-filesystem.md @@ -14,19 +14,12 @@ OpenViking 提供类 Unix 的文件系统操作来管理上下文。 |------|------|------|--------|------| | uri | str | 是 | - | Viking URI(必须是目录) | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - abstract = client.abstract("viking://resources/docs/") print(f"Abstract: {abstract}") # Output: "Documentation for the project API, covering authentication, endpoints..." - -client.close() ``` **HTTP API** @@ -68,18 +61,11 @@ openviking abstract viking://resources/docs/ |------|------|------|--------|------| | uri | str | 是 | - | Viking URI(必须是目录) | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - overview = client.overview("viking://resources/docs/") print(f"Overview:\n{overview}") - -client.close() ``` **HTTP API** @@ -121,18 +107,11 @@ openviking overview viking://resources/docs/ |------|------|------|--------|------| | uri | str | 是 | - | Viking URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - content = client.read("viking://resources/docs/api.md") print(f"Content:\n{content}") - -client.close() ``` **HTTP API** @@ -190,20 +169,13 @@ openviking read viking://resources/docs/api.md } ``` -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - entries = client.ls("viking://resources/") for entry in entries: type_str = "dir" if entry['isDir'] else "file" print(f"{entry['name']} - {type_str}") - -client.close() ``` **HTTP API** @@ -263,20 +235,13 @@ openviking ls viking://resources/ [--simple] [--recursive] |------|------|------|--------|------| | uri | str | 是 | - | Viking URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - entries = client.tree("viking://resources/") for entry in entries: type_str = "dir" if entry['isDir'] else "file" print(f"{entry['rel_path']} - {type_str}") - -client.close() ``` **HTTP API** @@ -333,19 +298,12 @@ openviking tree viking://resources/my-project/ |------|------|------|--------|------| | uri | str | 是 | - | Viking URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - info = client.stat("viking://resources/docs/api.md") print(f"Size: {info['size']}") print(f"Is directory: {info['isDir']}") - -client.close() ``` **HTTP API** @@ -394,17 +352,10 @@ openviking stat viking://resources/my-project/docs/api.md |------|------|------|--------|------| | uri | str | 是 | - | 新目录的 Viking URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - client.mkdir("viking://resources/new-project/") - -client.close() ``` **HTTP API** @@ -453,21 +404,14 @@ openviking mkdir viking://resources/new-project/ | uri | str | 是 | - | 要删除的 Viking URI | | recursive | bool | 否 | False | 递归删除目录 | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # 删除单个文件 client.rm("viking://resources/docs/old.md") # 递归删除目录 client.rm("viking://resources/old-project/", recursive=True) - -client.close() ``` **HTTP API** @@ -517,20 +461,13 @@ openviking rm viking://resources/old.md [--recursive] | from_uri | str | 是 | - | 源 Viking URI | | to_uri | str | 是 | - | 目标 Viking URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - client.mv( "viking://resources/old-name/", "viking://resources/new-name/" ) - -client.close() ``` **HTTP API** @@ -582,14 +519,9 @@ openviking mv viking://resources/old-name/ viking://resources/new-name/ | pattern | str | 是 | - | 搜索模式(正则表达式) | | case_insensitive | bool | 否 | False | 忽略大小写 | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - results = client.grep( "viking://resources/", "authentication", @@ -600,8 +532,6 @@ print(f"Found {results['count']} matches") for match in results['matches']: print(f" {match['uri']}:{match['line']}") print(f" {match['content']}") - -client.close() ``` **HTTP API** @@ -659,14 +589,9 @@ openviking grep viking://resources/ "authentication" [--ignore-case] | pattern | str | 是 | - | Glob 模式(例如 `**/*.md`) | | uri | str | 否 | "viking://" | 起始 URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # 查找所有 Markdown 文件 results = client.glob("**/*.md", "viking://resources/") print(f"Found {results['count']} markdown files:") @@ -676,8 +601,6 @@ for uri in results['matches']: # 查找所有 Python 文件 results = client.glob("**/*.py", "viking://resources/") print(f"Found {results['count']} Python files") - -client.close() ``` **HTTP API** @@ -732,14 +655,9 @@ openviking glob "**/*.md" [--uri viking://resources/] | uris | str 或 List[str] | 是 | - | 目标 URI | | reason | str | 否 | "" | 关联原因 | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # 单个关联 client.link( "viking://resources/docs/auth/", @@ -756,8 +674,6 @@ client.link( ], reason="Related documentation" ) - -client.close() ``` **HTTP API** @@ -819,20 +735,13 @@ openviking link viking://resources/docs/auth/ viking://resources/docs/security/ |------|------|------|--------|------| | uri | str | 是 | - | Viking URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - relations = client.relations("viking://resources/docs/auth/") for rel in relations: print(f"Related: {rel['uri']}") print(f" Reason: {rel['reason']}") - -client.close() ``` **HTTP API** @@ -878,20 +787,13 @@ openviking relations viking://resources/docs/auth/ | from_uri | str | 是 | - | 源 URI | | uri | str | 是 | - | 要取消关联的目标 URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - client.unlink( "viking://resources/docs/auth/", "viking://resources/docs/security/" ) - -client.close() ``` **HTTP API** diff --git a/docs/zh/api/04-skills.md b/docs/zh/api/04-skills.md index cc7ca644..9a0f3259 100644 --- a/docs/zh/api/04-skills.md +++ b/docs/zh/api/04-skills.md @@ -57,14 +57,9 @@ description: Skill description - 单个文件:指向 `SKILL.md` 文件的路径 - 目录:指向包含 `SKILL.md` 的目录路径(辅助文件会一并包含) -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - skill = { "name": "search-web", "description": "Search the web for current information", @@ -81,8 +76,6 @@ Search the web for current information. result = client.add_skill(skill) print(f"Added: {result['uri']}") - -client.close() ``` **HTTP API** @@ -127,14 +120,9 @@ openviking add-skill ./my-skill/ [--wait] **示例:从 MCP Tool 添加** -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # MCP tool 格式会被自动检测并转换 mcp_tool = { "name": "calculator", @@ -153,8 +141,6 @@ mcp_tool = { result = client.add_skill(mcp_tool) print(f"Added: {result['uri']}") - -client.close() ``` **HTTP API** @@ -183,14 +169,9 @@ curl -X POST http://localhost:1933/api/v1/skills \ **示例:从 SKILL.md 文件添加** -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # 从文件路径添加 result = client.add_skill("./skills/search-web/SKILL.md") print(f"Added: {result['uri']}") @@ -199,8 +180,6 @@ print(f"Added: {result['uri']}") result = client.add_skill("./skills/code-runner/") print(f"Added: {result['uri']}") print(f"Auxiliary files: {result['auxiliary_files']}") - -client.close() ``` **HTTP API** @@ -269,14 +248,9 @@ Concrete examples of skill invocation. ### 列出技能 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # 列出所有技能 skills = client.ls("viking://agent/skills/") for skill in skills: @@ -285,8 +259,6 @@ for skill in skills: # 简单列表(仅名称) names = client.ls("viking://agent/skills/", simple=True) print(names) - -client.close() ``` **HTTP API** @@ -298,7 +270,7 @@ curl -X GET "http://localhost:1933/api/v1/fs/ls?uri=viking://agent/skills/" \ ### 读取技能内容 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python uri = "viking://agent/skills/search-web/" @@ -334,7 +306,7 @@ curl -X GET "http://localhost:1933/api/v1/content/read?uri=viking://agent/skills ### 搜索技能 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # 语义搜索技能 @@ -365,7 +337,7 @@ curl -X POST http://localhost:1933/api/v1/search/find \ ### 删除技能 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python client.rm("viking://agent/skills/old-skill/", recursive=True) diff --git a/docs/zh/api/05-sessions.md b/docs/zh/api/05-sessions.md index 8c64e074..7573492e 100644 --- a/docs/zh/api/05-sessions.md +++ b/docs/zh/api/05-sessions.md @@ -14,19 +14,12 @@ |------|------|------|--------|------| | session_id | str | 否 | None | 会话 ID。如果为 None,则创建一个自动生成 ID 的新会话 | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data", user="alice") -client.initialize() - # 创建新会话(自动生成 ID) session = client.session() print(f"Session URI: {session.uri}") - -client.close() ``` **HTTP API** @@ -66,19 +59,12 @@ openviking session new 列出所有会话。 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - sessions = client.ls("viking://session/") for s in sessions: print(f"{s['name']}") - -client.close() ``` **HTTP API** @@ -123,20 +109,13 @@ openviking session list |------|------|------|--------|------| | session_id | str | 是 | - | 会话 ID | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # 加载已有会话 session = client.session(session_id="a1b2c3d4") session.load() print(f"Loaded {len(session.messages)} messages") - -client.close() ``` **HTTP API** @@ -182,17 +161,10 @@ openviking session get a1b2c3d4 |------|------|------|--------|------| | session_id | str | 是 | - | 要删除的会话 ID | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - client.rm("viking://session/a1b2c3d4/", recursive=True) - -client.close() ``` **HTTP API** @@ -264,15 +236,11 @@ ToolPart( ) ``` -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov from openviking.message import TextPart -client = ov.OpenViking(path="./data") -client.initialize() - session = client.session() # 添加用户消息 @@ -284,8 +252,6 @@ session.add_message("user", [ session.add_message("assistant", [ TextPart(text="You can use OAuth 2.0 for authentication...") ]) - -client.close() ``` **HTTP API** @@ -345,14 +311,9 @@ openviking session add-message a1b2c3d4 --role user --content "How do I authenti |------|------|------|--------|------| | session_id | str | 是 | - | 要提交的会话 ID | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - session = client.session(session_id="a1b2c3d4") session.load() @@ -360,8 +321,6 @@ session.load() result = session.commit() print(f"Status: {result['status']}") print(f"Memories extracted: {result['memories_extracted']}") - -client.close() ``` **HTTP API** @@ -447,7 +406,7 @@ viking://session/{session_id}/ ## 完整示例 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python import openviking as ov diff --git a/docs/zh/api/06-retrieval.md b/docs/zh/api/06-retrieval.md index c7adee11..0c4268a2 100644 --- a/docs/zh/api/06-retrieval.md +++ b/docs/zh/api/06-retrieval.md @@ -54,14 +54,9 @@ class MatchedContext: relations: List[RelatedContext] # 关联上下文 ``` -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - results = client.find("how to authenticate users") for ctx in results.resources: @@ -70,8 +65,6 @@ for ctx in results.resources: print(f"Type: {ctx.context_type}") print(f"Abstract: {ctx.abstract[:100]}...") print("---") - -client.close() ``` **HTTP API** @@ -122,7 +115,7 @@ openviking find "how to authenticate users" [--uri viking://resources/] [--limit **示例:使用 Target URI 搜索** -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # 仅在资源中搜索 @@ -192,15 +185,11 @@ curl -X POST http://localhost:1933/api/v1/search/find \ | score_threshold | float | 否 | None | 最低相关性分数阈值 | | filter | Dict | 否 | None | 元数据过滤器 | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov from openviking.message import TextPart -client = ov.OpenViking(path="./data") -client.initialize() - # 创建带对话上下文的会话 session = client.session() session.add_message("user", [ @@ -219,8 +208,6 @@ results = client.search( for ctx in results.resources: print(f"Found: {ctx.uri}") print(f"Abstract: {ctx.abstract[:200]}...") - -client.close() ``` **HTTP API** @@ -275,7 +262,7 @@ openviking search "best practices" [--session-id abc123] [--limit 10] **示例:不使用会话的搜索** -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python # search 也可以在没有会话的情况下使用 @@ -313,14 +300,9 @@ curl -X POST http://localhost:1933/api/v1/search/search \ | pattern | str | 是 | - | 搜索模式(正则表达式) | | case_insensitive | bool | 否 | False | 忽略大小写 | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - results = client.grep( "viking://resources/", "authentication", @@ -331,8 +313,6 @@ print(f"Found {results['count']} matches") for match in results['matches']: print(f" {match['uri']}:{match['line']}") print(f" {match['content']}") - -client.close() ``` **HTTP API** @@ -390,14 +370,9 @@ openviking grep viking://resources/ "authentication" [--ignore-case] | pattern | str | 是 | - | Glob 模式(例如 `**/*.md`) | | uri | str | 否 | "viking://" | 起始 URI | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # 查找所有 markdown 文件 results = client.glob("**/*.md", "viking://resources/") print(f"Found {results['count']} markdown files:") @@ -407,8 +382,6 @@ for uri in results['matches']: # 查找所有 Python 文件 results = client.glob("**/*.py", "viking://resources/") print(f"Found {results['count']} Python files") - -client.close() ``` **HTTP API** @@ -466,7 +439,7 @@ openviking glob "**/*.md" [--uri viking://resources/] ### 渐进式读取内容 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python results = client.find("authentication") @@ -505,7 +478,7 @@ curl -X GET "http://localhost:1933/api/v1/content/read?uri=viking://resources/do ### 获取关联资源 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python results = client.find("OAuth implementation") diff --git a/docs/zh/api/07-system.md b/docs/zh/api/07-system.md index f637eb9f..8f744272 100644 --- a/docs/zh/api/07-system.md +++ b/docs/zh/api/07-system.md @@ -8,19 +8,12 @@ OpenViking 提供系统健康检查、可观测性和调试 API,用于监控 基础健康检查端点。无需认证。 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # 检查系统是否健康 if client.observer.is_healthy(): print("System OK") - -client.close() ``` **HTTP API** @@ -53,17 +46,10 @@ openviking health 获取系统状态,包括初始化状态和用户信息。 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - print(client.observer.system) - -client.close() ``` **HTTP API** @@ -108,22 +94,15 @@ openviking status |------|------|------|--------|------| | timeout | float | 否 | None | 超时时间(秒) | -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - # 添加资源 client.add_resource("./docs/") # 等待所有处理完成 status = client.wait_processed() print(f"Processing complete: {status}") - -client.close() ``` **HTTP API** @@ -172,14 +151,9 @@ Observer API 提供详细的组件级监控。 获取队列系统状态(embedding 和语义处理队列)。 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - print(client.observer.queue) # Output: # [queue] (healthy) @@ -187,8 +161,6 @@ print(client.observer.queue) # Embedding 0 0 10 0 10 # Semantic 0 0 10 0 10 # TOTAL 0 0 20 0 20 - -client.close() ``` **HTTP API** @@ -229,7 +201,7 @@ openviking observer queue 获取 VikingDB 状态(集合、索引、向量数量)。 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python print(client.observer.vikingdb) @@ -282,7 +254,7 @@ openviking observer vikingdb 获取 VLM(视觉语言模型)token 使用状态。 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python print(client.observer.vlm) @@ -331,7 +303,7 @@ openviking observer vlm 获取整体系统状态,包括所有组件。 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python print(client.observer.system) @@ -404,20 +376,13 @@ openviking observer system 快速检查整个系统的健康状态。 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python -import openviking as ov - -client = ov.OpenViking(path="./data") -client.initialize() - if client.observer.is_healthy(): print("System OK") else: print(client.observer.system) - -client.close() ``` **HTTP API** diff --git a/docs/zh/concepts/01-architecture.md b/docs/zh/concepts/01-architecture.md index 2ec4aea5..101917f3 100644 --- a/docs/zh/concepts/01-architecture.md +++ b/docs/zh/concepts/01-architecture.md @@ -139,7 +139,7 @@ client = OpenViking(path="./data") ```python # Python SDK 连接 OpenViking Server -client = OpenViking(url="http://localhost:1933", api_key="xxx") +client = SyncHTTPClient(url="http://localhost:1933", api_key="xxx") ``` ```bash diff --git a/docs/zh/faq/faq.md b/docs/zh/faq/faq.md index c05dcf5c..d3f7ba3b 100644 --- a/docs/zh/faq/faq.md +++ b/docs/zh/faq/faq.md @@ -124,11 +124,11 @@ client = ov.AsyncOpenViking(path="./my_data") await client.initialize() # 异步客户端 - 服务模式 -client = ov.AsyncOpenViking(url="http://localhost:1933", api_key="your-key") +client = ov.AsyncHTTPClient(url="http://localhost:1933", api_key="your-key") await client.initialize() ``` -SDK 构造函数仅接受 `url`、`api_key`、`path`、`user` 参数。其他配置(embedding、vlm 等)通过 `ov.conf` 配置文件管理。 +SDK 构造函数仅接受 `url`、`api_key`、`path` 参数。其他配置(embedding、vlm 等)通过 `ov.conf` 配置文件管理。 ### 支持哪些文件格式? @@ -347,7 +347,7 @@ OpenViking 使用分数传播机制: 1. **批量处理**:一次添加多个资源比逐个添加更高效 2. **合理设置 `batch_size`**:Embedding 配置中调整批处理大小 3. **使用本地存储**:开发阶段使用 `local` 后端减少网络延迟 -4. **异步操作**:充分利用 `AsyncOpenViking` 的异步特性 +4. **异步操作**:充分利用 `AsyncOpenViking` / `AsyncHTTPClient` 的异步特性 ## 部署相关 @@ -363,7 +363,7 @@ OpenViking 使用分数传播机制: client = ov.AsyncOpenViking(path="./data") # 服务模式 -client = ov.AsyncOpenViking(url="http://localhost:1933", api_key="your-key") +client = ov.AsyncHTTPClient(url="http://localhost:1933", api_key="your-key") ``` ### OpenViking 是开源的吗? diff --git a/docs/zh/getting-started/02-quickstart.md b/docs/zh/getting-started/02-quickstart.md index 9ed53b81..30d8b407 100644 --- a/docs/zh/getting-started/02-quickstart.md +++ b/docs/zh/getting-started/02-quickstart.md @@ -53,57 +53,7 @@ OpenViking 支持多种模型服务: } ``` -### 配置示例 - -
-示例 1:使用火山引擎(豆包模型) - -```json -{ - "embedding": { - "dense": { - "api_base" : "https://ark.cn-beijing.volces.com/api/v3", - "api_key" : "your-volcengine-api-key", - "provider" : "volcengine", - "dimension": 1024, - "model" : "doubao-embedding-vision-250615" - } - }, - "vlm": { - "api_base" : "https://ark.cn-beijing.volces.com/api/v3", - "api_key" : "your-volcengine-api-key", - "provider" : "volcengine", - "model" : "doubao-seed-1-8-251228" - } -} -``` - -
- -
-示例 2:使用 OpenAI 模型 - -```json -{ - "embedding": { - "dense": { - "api_base" : "https://api.openai.com/v1", - "api_key" : "your-openai-api-key", - "provider" : "openai", - "dimension": 3072, - "model" : "text-embedding-3-large" - } - }, - "vlm": { - "api_base" : "https://api.openai.com/v1", - "api_key" : "your-openai-api-key", - "provider" : "openai", - "model" : "gpt-4-vision-preview" - } -} -``` - -
+各模型服务的完整配置示例请参见 [配置指南 - 配置示例](../guides/01-configuration.md#配置示例)。 ### 设置环境变量 diff --git a/docs/zh/getting-started/03-quickstart-server.md b/docs/zh/getting-started/03-quickstart-server.md index 7542cfe6..9ae99689 100644 --- a/docs/zh/getting-started/03-quickstart-server.md +++ b/docs/zh/getting-started/03-quickstart-server.md @@ -40,7 +40,7 @@ curl http://localhost:1933/health ```python import openviking as ov -client = ov.OpenViking(url="http://localhost:1933") +client = ov.SyncHTTPClient(url="http://localhost:1933") ``` 如果服务端启用了认证,需要传入 `api_key`: @@ -48,7 +48,7 @@ client = ov.OpenViking(url="http://localhost:1933") ```python import openviking as ov -client = ov.OpenViking(url="http://localhost:1933", api_key="your-key") +client = ov.SyncHTTPClient(url="http://localhost:1933", api_key="your-key") ``` **完整示例:** @@ -56,7 +56,7 @@ client = ov.OpenViking(url="http://localhost:1933", api_key="your-key") ```python import openviking as ov -client = ov.OpenViking(url="http://localhost:1933") +client = ov.SyncHTTPClient(url="http://localhost:1933") try: client.initialize() diff --git a/docs/zh/guides/01-configuration.md b/docs/zh/guides/01-configuration.md index 96ddfce4..7ee66762 100644 --- a/docs/zh/guides/01-configuration.md +++ b/docs/zh/guides/01-configuration.md @@ -23,26 +23,76 @@ OpenViking 使用 JSON 配置文件(`ov.conf`)进行设置。配置文件支 }, "embedding": { "dense": { - "model": "doubao-embedding-vision-250615", - "api_key": "{your-api-key}", - "api_base": "https://ark.cn-beijing.volces.com/api/v3", + "api_base" : "", + "api_key" : "", + "provider" : "", "dimension": 1024, - "provider": "volcengine", + "model" : "" + } + }, + "vlm": { + "api_base" : "", + "api_key" : "", + "provider" : "", + "model" : "" + } +} + +``` + +## 配置示例 + +
+火山引擎(豆包模型) + +```json +{ + "embedding": { + "dense": { + "api_base" : "https://ark.cn-beijing.volces.com/api/v3", + "api_key" : "your-volcengine-api-key", + "provider" : "volcengine", + "dimension": 1024, + "model" : "doubao-embedding-vision-250615", "input": "multimodal" } }, "vlm": { - "model": "doubao-seed-1-8-251228", - "api_key": "{your-api-key}", - "api_base": "https://ark.cn-beijing.volces.com/api/v3", - "temperature": 0.0, - "max_retries": 2, - "provider": "volcengine" + "api_base" : "https://ark.cn-beijing.volces.com/api/v3", + "api_key" : "your-volcengine-api-key", + "provider" : "volcengine", + "model" : "doubao-seed-1-8-251228" } } +``` + +
+ +
+OpenAI 模型 +```json +{ + "embedding": { + "dense": { + "api_base" : "https://api.openai.com/v1", + "api_key" : "your-openai-api-key", + "provider" : "openai", + "dimension": 3072, + "model" : "text-embedding-3-large" + } + }, + "vlm": { + "api_base" : "https://api.openai.com/v1", + "api_key" : "your-openai-api-key", + "provider" : "openai", + "model" : "gpt-4-vision-preview" + } +} ``` +
+ ## 配置部分 ### embedding @@ -247,7 +297,7 @@ OpenViking 使用两个配置文件: | 配置文件 | 用途 | 默认路径 | |---------|------|---------| | `ov.conf` | SDK 嵌入模式 + 服务端配置 | `~/.openviking/ov.conf` | -| `ovcli.conf` | CLI 连接远程服务端 | `~/.openviking/ovcli.conf` | +| `ovcli.conf` | HTTP 客户端和 CLI 连接远程服务端 | `~/.openviking/ovcli.conf` | 配置文件放在默认路径时,OpenViking 自动加载,无需额外设置。 @@ -268,7 +318,7 @@ python -m openviking serve --config /path/to/ov.conf ### ovcli.conf -CLI 工具连接远程服务端的配置文件: +HTTP 客户端(`SyncHTTPClient` / `AsyncHTTPClient`)和 CLI 工具连接远程服务端的配置文件: ```json { @@ -352,8 +402,7 @@ CLI 工具连接远程服务端的配置文件: "port": 1933, "api_key": "string", "cors_origins": ["string"] - }, - "user": "string" + } } ``` diff --git a/docs/zh/guides/03-deployment.md b/docs/zh/guides/03-deployment.md index d0185eb0..9b7cd5b8 100644 --- a/docs/zh/guides/03-deployment.md +++ b/docs/zh/guides/03-deployment.md @@ -101,7 +101,7 @@ python -m openviking serve ```python import openviking as ov -client = ov.OpenViking(url="http://localhost:1933", api_key="your-key") +client = ov.SyncHTTPClient(url="http://localhost:1933", api_key="your-key") client.initialize() results = client.find("how to use openviking") diff --git a/docs/zh/guides/04-authentication.md b/docs/zh/guides/04-authentication.md index 635d801a..aad7a4f8 100644 --- a/docs/zh/guides/04-authentication.md +++ b/docs/zh/guides/04-authentication.md @@ -40,12 +40,12 @@ curl http://localhost:1933/api/v1/fs/ls?uri=viking:// \ -H "Authorization: Bearer your-secret-key" ``` -**Python SDK** +**Python SDK (HTTP)** ```python import openviking as ov -client = ov.OpenViking( +client = ov.SyncHTTPClient( url="http://localhost:1933", api_key="your-secret-key" ) diff --git a/docs/zh/guides/05-monitoring.md b/docs/zh/guides/05-monitoring.md index 7b3f4ad1..54359b86 100644 --- a/docs/zh/guides/05-monitoring.md +++ b/docs/zh/guides/05-monitoring.md @@ -18,7 +18,7 @@ curl http://localhost:1933/health ### 整体系统健康状态 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python status = client.get_status() @@ -60,7 +60,7 @@ curl http://localhost:1933/api/v1/observer/system \ ### 快速健康检查 -**Python SDK** +**Python SDK (Embedded / HTTP)** ```python if client.is_healthy(): diff --git a/examples/chatmem/chatmem.py b/examples/chatmem/chatmem.py index ec0f7ec7..e4b0c784 100644 --- a/examples/chatmem/chatmem.py +++ b/examples/chatmem/chatmem.py @@ -336,7 +336,7 @@ def run(self): config_dict = json.load(f) config = OpenVikingConfig.from_dict(config_dict) - self.client = SyncOpenViking(path=self.data_path, config=config, user="default") + self.client = SyncOpenViking(path=self.data_path, config=config) self.client.initialize() # Create/load session diff --git a/examples/chatmem/docs/2026-02-03-chatmem-implementation.md b/examples/chatmem/docs/2026-02-03-chatmem-implementation.md index 91610490..64cb0051 100644 --- a/examples/chatmem/docs/2026-02-03-chatmem-implementation.md +++ b/examples/chatmem/docs/2026-02-03-chatmem-implementation.md @@ -282,7 +282,6 @@ def run(self): # Create/load session self.session = self.client.session( - user="default", session_id=self.session_id ) self.session.load() @@ -432,7 +431,7 @@ client = SyncOpenViking(path='./data', config=config) client.initialize() # Create session -session = client.session(user="test", session_id="test-123") +session = client.session(session_id="test-123") # Add messages session.add_message("user", [TextPart("Hello")]) @@ -1070,7 +1069,7 @@ self.session = None # In run() self.client = SyncOpenViking(path=data_path, config=config) self.client.initialize() -self.session = self.client.session(user="default", session_id=session_id) +self.session = self.client.session(session_id=session_id) self.session.load() # Recording messages diff --git a/examples/chatmem/docs/COMPARISON.md b/examples/chatmem/docs/COMPARISON.md index 1c45f7f1..90d03c13 100644 --- a/examples/chatmem/docs/COMPARISON.md +++ b/examples/chatmem/docs/COMPARISON.md @@ -82,7 +82,7 @@ self.session = None # In run() self.client = SyncOpenViking(path=data_path, config=config) self.client.initialize() -self.session = self.client.session(user="default", session_id=session_id) +self.session = self.client.session(session_id=session_id) self.session.load() # Recording messages diff --git a/examples/memex/cli.py b/examples/memex/cli.py index 49d19dc0..8b36119b 100644 --- a/examples/memex/cli.py +++ b/examples/memex/cli.py @@ -3,7 +3,7 @@ Memex CLI - Personal Knowledge Assistant Usage: - python -m memex.cli [--data-path PATH] [--user USER] + python -m memex.cli [--data-path PATH] Commands: /help Show help @@ -425,14 +425,11 @@ def main(): default="./ov.conf", help="Path to OpenViking config file (default: ./ov.conf)", ) - parser.add_argument("--user", default="default", help="User name (default: default)") - args = parser.parse_args() config = MemexConfig( data_path=args.data_path, config_path=args.config_path, - user=args.user, ) cli = MemexCLI(config) diff --git a/examples/memex/client.py b/examples/memex/client.py index 241cc279..f4c7df93 100644 --- a/examples/memex/client.py +++ b/examples/memex/client.py @@ -7,7 +7,6 @@ from config import MemexConfig import openviking as ov -from openviking.session.user_id import UserIdentifier class MemexClient: @@ -33,13 +32,9 @@ def client(self) -> ov.SyncOpenViking: def initialize(self) -> None: """Initialize the OpenViking client.""" ov_config = self.config.get_openviking_config() - user = UserIdentifier( - ov_config.default_account, ov_config.default_user, ov_config.default_agent - ) self._client = ov.SyncOpenViking( path=self.config.data_path, config=ov_config, - user=user, ) self._client.initialize() diff --git a/examples/memex/config.py b/examples/memex/config.py index b82b419b..5df10e5a 100644 --- a/examples/memex/config.py +++ b/examples/memex/config.py @@ -18,7 +18,6 @@ class MemexConfig: # OpenViking settings data_path: str = "./memex_data" config_path: str = "./ov.conf" - user: str = "default" # LLM settings (for RAG, read from ov.conf) llm_temperature: float = 0.7 @@ -45,7 +44,6 @@ def from_env(cls) -> "MemexConfig": return cls( data_path=os.getenv("MEMEX_DATA_PATH", "./memex_data"), config_path=os.getenv("MEMEX_CONFIG_PATH", "./ov.conf"), - user=os.getenv("MEMEX_USER", "default"), llm_temperature=float(os.getenv("MEMEX_LLM_TEMPERATURE", "0.7")), llm_max_tokens=int(os.getenv("MEMEX_LLM_MAX_TOKENS", "2048")), search_top_k=int(os.getenv("MEMEX_SEARCH_TOP_K", "5")), diff --git a/examples/quick_start.py b/examples/quick_start.py index 5113a248..cc455980 100644 --- a/examples/quick_start.py +++ b/examples/quick_start.py @@ -1,7 +1,7 @@ import openviking as ov client = ov.OpenViking(path="./data") -# client = ov.OpenViking(url="http://localhost:1933") # HTTP mode: connect to OpenViking Server +# client = ov.SyncHTTPClient(url="http://localhost:1933") # HTTP mode: connect to OpenViking Server try: client.initialize() diff --git a/examples/server_client/README.md b/examples/server_client/README.md index c4ab6046..850a2d1b 100644 --- a/examples/server_client/README.md +++ b/examples/server_client/README.md @@ -42,8 +42,8 @@ bash client_cli.sh # CLI 使用示例 ## 文件说明 ``` -client_sync.py # 同步客户端示例(SyncOpenViking HTTP mode) -client_async.py # 异步客户端示例(AsyncOpenViking HTTP mode) +client_sync.py # 同步客户端示例(SyncHTTPClient) +client_async.py # 异步客户端示例(AsyncHTTPClient) client_cli.sh # CLI 使用示例(覆盖所有命令和参数) ov.conf.example # Server/SDK 配置文件模板(ov.conf) ovcli.conf.example # CLI 连接配置文件模板(ovcli.conf) @@ -73,14 +73,12 @@ pyproject.toml # 项目依赖 |------|------|--------| | `url` | Server 地址 | (必填) | | `api_key` | API Key 认证 | `null`(无认证) | -| `user` | 默认用户名 | `"default"` | | `output` | 默认输出格式:`"table"` 或 `"json"` | `"table"` | ```json { "url": "http://localhost:1933", "api_key": null, - "user": "default", "output": "table" } ``` @@ -116,7 +114,7 @@ main() ```python import openviking as ov -client = ov.OpenViking(url="http://localhost:1933", api_key="your-key") +client = ov.SyncHTTPClient(url="http://localhost:1933", api_key="your-key") client.initialize() client.add_resource(path="./document.md") @@ -131,7 +129,7 @@ client.close() ```python import openviking as ov -client = ov.AsyncOpenViking(url="http://localhost:1933", api_key="your-key") +client = ov.AsyncHTTPClient(url="http://localhost:1933", api_key="your-key") await client.initialize() await client.add_resource(path="./document.md") diff --git a/examples/server_client/client_async.py b/examples/server_client/client_async.py index fc2093eb..660ac764 100644 --- a/examples/server_client/client_async.py +++ b/examples/server_client/client_async.py @@ -2,7 +2,7 @@ """ OpenViking 异步客户端示例 (HTTP mode) -使用 AsyncOpenViking 通过 HTTP 连接远程 Server,演示完整 API。 +使用 AsyncHTTPClient 通过 HTTP 连接远程 Server,演示完整 API。 前置条件: 先启动 Server: openviking serve @@ -37,7 +37,7 @@ async def main(): parser.add_argument("--api-key", default=None, help="API key") args = parser.parse_args() - client = ov.AsyncOpenViking(url=args.url, api_key=args.api_key) + client = ov.AsyncHTTPClient(url=args.url, api_key=args.api_key) try: # ── Connect ── diff --git a/examples/server_client/client_cli.sh b/examples/server_client/client_cli.sh index 6d345548..dd40d8d8 100755 --- a/examples/server_client/client_cli.sh +++ b/examples/server_client/client_cli.sh @@ -178,7 +178,6 @@ SESSION_ID=$(openviking --json session new | python3 -c " import sys, json; print(json.load(sys.stdin)['result']['session_id']) ") echo " session_id: $SESSION_ID" -# openviking session new --user "alice" # with custom user section "7.2 Add Messages" openviking session add-message "$SESSION_ID" \ diff --git a/examples/server_client/client_sync.py b/examples/server_client/client_sync.py index 12ed42ab..c0297db7 100644 --- a/examples/server_client/client_sync.py +++ b/examples/server_client/client_sync.py @@ -2,7 +2,7 @@ """ OpenViking 同步客户端示例 (HTTP mode) -使用 SyncOpenViking 通过 HTTP 连接远程 Server,演示完整 API。 +使用 SyncHTTPClient 通过 HTTP 连接远程 Server,演示完整 API。 前置条件: 先启动 Server: openviking serve @@ -63,7 +63,7 @@ def main(): parser.add_argument("--api-key", default=None, help="API key") args = parser.parse_args() - client = ov.OpenViking(url=args.url, api_key=args.api_key) + client = ov.SyncHTTPClient(url=args.url, api_key=args.api_key) try: # ── Connect ── @@ -182,7 +182,7 @@ def main(): ctx_results = spin( "Searching with session context...", - client.search, "how to use it", session=session, limit=3, + client.search, "how to use it", session_id=session.session_id, limit=3, ) if hasattr(ctx_results, "resources") and ctx_results.resources: for r in ctx_results.resources: diff --git a/openviking/__init__.py b/openviking/__init__.py index f9c7d73c..b5da2e4a 100644 --- a/openviking/__init__.py +++ b/openviking/__init__.py @@ -7,6 +7,8 @@ """ from openviking.async_client import AsyncOpenViking +from openviking.client.http import AsyncHTTPClient +from openviking.client.sync_http import SyncHTTPClient from openviking.session import Session from openviking.session.user_id import UserIdentifier from openviking.sync_client import SyncOpenViking @@ -27,6 +29,8 @@ "OpenViking", "SyncOpenViking", "AsyncOpenViking", + "SyncHTTPClient", + "AsyncHTTPClient", "Session", "UserIdentifier", ] diff --git a/openviking/async_client.py b/openviking/async_client.py index ea3aa83c..3376ab94 100644 --- a/openviking/async_client.py +++ b/openviking/async_client.py @@ -1,15 +1,15 @@ # Copyright (c) 2026 Beijing Volcano Engine Technology Co., Ltd. # SPDX-License-Identifier: Apache-2.0 """ -Async OpenViking client implementation. +Async OpenViking client implementation (embedded mode only). -Supports both embedded mode (LocalClient) and HTTP mode (HTTPClient). +For HTTP mode, use AsyncHTTPClient or SyncHTTPClient. """ import threading from typing import Any, Dict, List, Optional, Union -from openviking.client import HTTPClient, LocalClient, Session +from openviking.client import LocalClient, Session from openviking.client.base import BaseClient from openviking.service.debug_service import SystemStatus from openviking.session.user_id import UserIdentifier @@ -20,36 +20,20 @@ class AsyncOpenViking: """ - OpenViking main client class (Asynchronous). + OpenViking main client class (Asynchronous, embedded mode only). - Supports two deployment modes: - - Embedded mode: Uses local storage and auto-starts services (singleton) - - HTTP mode: Connects to remote OpenViking Server via HTTP API (not singleton) + Uses local storage and auto-starts services (singleton). + For HTTP mode, use AsyncHTTPClient or SyncHTTPClient instead. Examples: - # 1. Embedded mode (loads config from ov.conf) client = AsyncOpenViking(path="./data") await client.initialize() - - # 2. HTTP mode (connects to OpenViking Server) - client = AsyncOpenViking( - url="http://localhost:8000", - api_key="your-api-key", - user="alice" - ) - await client.initialize() """ _instance: Optional["AsyncOpenViking"] = None _lock = threading.Lock() def __new__(cls, *args, **kwargs): - # HTTP mode: no singleton - url = kwargs.get("url") - if url: - return object.__new__(cls) - - # Embedded mode: use singleton if cls._instance is None: with cls._lock: if cls._instance is None: @@ -59,41 +43,26 @@ def __new__(cls, *args, **kwargs): def __init__( self, path: Optional[str] = None, - url: Optional[str] = None, - api_key: Optional[str] = None, - user: Optional[UserIdentifier] = None, **kwargs, ): """ - Initialize OpenViking client. + Initialize OpenViking client (embedded mode). Args: - path: Local storage path for embedded mode (overrides ov.conf storage path). - url: OpenViking Server URL for HTTP mode. - api_key: API key for HTTP mode authentication. - user: UserIdentifier object for session management. + path: Local storage path (overrides ov.conf storage path). **kwargs: Additional configuration parameters. """ # Singleton guard for repeated initialization if hasattr(self, "_singleton_initialized") and self._singleton_initialized: return - if isinstance(user, str): - user = UserIdentifier.the_default_user(user) - self.user = user or UserIdentifier.the_default_user() + self.user = UserIdentifier.the_default_user() self._initialized = False self._singleton_initialized = True - # Create the appropriate client - if url: - # HTTP mode - self._client: BaseClient = HTTPClient(url=url, api_key=api_key, user=self.user) - else: - # Embedded mode - LocalClient loads config from ov.conf singleton - self._client: BaseClient = LocalClient( - path=path, - user=self.user, - ) + self._client: BaseClient = LocalClient( + path=path, + ) # ============= Lifecycle methods ============= diff --git a/openviking/cli/context.py b/openviking/cli/context.py index 989b8df1..a389a067 100644 --- a/openviking/cli/context.py +++ b/openviking/cli/context.py @@ -7,70 +7,34 @@ import typer -from openviking.utils.config.config_loader import ( - DEFAULT_CONFIG_DIR, - DEFAULT_OVCLI_CONF, - OPENVIKING_CLI_CONFIG_ENV, - require_config, -) - if TYPE_CHECKING: - from openviking.sync_client import SyncOpenViking + from openviking.client.sync_http import SyncHTTPClient class CliConfigError(ValueError): """Raised when required CLI configuration is missing or invalid.""" -def build_sync_client(**kwargs) -> "SyncOpenViking": - """Create SyncOpenViking lazily to keep CLI import lightweight.""" - from openviking.sync_client import SyncOpenViking - - return SyncOpenViking(**kwargs) - - @dataclass class CLIContext: """Shared state for one CLI invocation.""" json_output: bool = False output_format: str = "table" - _client: Optional["SyncOpenViking"] = field(default=None, init=False, repr=False) + _client: Optional["SyncHTTPClient"] = field(default=None, init=False, repr=False) - def get_client_http_only(self) -> "SyncOpenViking": - """Create an HTTP client from ovcli.conf.""" + def get_client_http_only(self) -> "SyncHTTPClient": + """Create an HTTP client (auto-loads ovcli.conf).""" if self._client is not None: return self._client - try: - cli_config = require_config( - None, - OPENVIKING_CLI_CONFIG_ENV, - DEFAULT_OVCLI_CONF, - "CLI", - ) - except FileNotFoundError: - default_path = DEFAULT_CONFIG_DIR / DEFAULT_OVCLI_CONF - raise CliConfigError( - f"CLI configuration file not found.\n" - f"Please create {default_path} or set {OPENVIKING_CLI_CONFIG_ENV}.\n" - f"Example content: " - f'{{"url": "http://localhost:1933", "api_key": null}}' - ) - - url = cli_config.get("url") - if not url: - default_path = DEFAULT_CONFIG_DIR / DEFAULT_OVCLI_CONF - raise CliConfigError( - f'"url" is required in {default_path}.\n' - f'Example: {{"url": "http://localhost:1933"}}' - ) + from openviking.client.sync_http import SyncHTTPClient - self._client = build_sync_client( - url=url, - api_key=cli_config.get("api_key"), - user=cli_config.get("user"), - ) + try: + self._client = SyncHTTPClient() + except ValueError as e: + raise CliConfigError(str(e)) from e + self._client.initialize() return self._client def close_client(self) -> None: diff --git a/openviking/client.py b/openviking/client.py index 43afabc2..34d5e673 100644 --- a/openviking/client.py +++ b/openviking/client.py @@ -6,6 +6,8 @@ """ from openviking.async_client import AsyncOpenViking +from openviking.client.http import AsyncHTTPClient +from openviking.client.sync_http import SyncHTTPClient from openviking.sync_client import SyncOpenViking -__all__ = ["SyncOpenViking", "AsyncOpenViking"] +__all__ = ["SyncOpenViking", "AsyncOpenViking", "SyncHTTPClient", "AsyncHTTPClient"] diff --git a/openviking/client/__init__.py b/openviking/client/__init__.py index c6fba72d..c4ab52cf 100644 --- a/openviking/client/__init__.py +++ b/openviking/client/__init__.py @@ -2,17 +2,19 @@ # SPDX-License-Identifier: Apache-2.0 """OpenViking Client module. -Provides client implementations for both embedded (LocalClient) and HTTP (HTTPClient) modes. +Provides client implementations for embedded (LocalClient) and HTTP (AsyncHTTPClient/SyncHTTPClient) modes. """ from openviking.client.base import BaseClient -from openviking.client.http import HTTPClient +from openviking.client.http import AsyncHTTPClient from openviking.client.local import LocalClient from openviking.client.session import Session +from openviking.client.sync_http import SyncHTTPClient __all__ = [ "BaseClient", - "HTTPClient", + "AsyncHTTPClient", + "SyncHTTPClient", "LocalClient", "Session", ] diff --git a/openviking/client/base.py b/openviking/client/base.py index 08430452..b5cc8061 100644 --- a/openviking/client/base.py +++ b/openviking/client/base.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 """Base client interface for OpenViking. -Defines the abstract base class that both LocalClient and HTTPClient implement. +Defines the abstract base class that both LocalClient and AsyncHTTPClient implement. """ from abc import ABC, abstractmethod @@ -12,7 +12,7 @@ class BaseClient(ABC): """Abstract base class for OpenViking clients. - Both LocalClient (embedded mode) and HTTPClient (HTTP mode) implement this interface. + Both LocalClient (embedded mode) and AsyncHTTPClient (HTTP mode) implement this interface. """ # ============= Lifecycle ============= diff --git a/openviking/client/http.py b/openviking/client/http.py index d464a105..2f201633 100644 --- a/openviking/client/http.py +++ b/openviking/client/http.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 Beijing Volcano Engine Technology Co., Ltd. # SPDX-License-Identifier: Apache-2.0 -"""HTTP Client for OpenViking. +"""Async HTTP Client for OpenViking. Implements BaseClient interface using HTTP calls to OpenViking Server. """ @@ -10,6 +10,12 @@ import httpx from openviking.client.base import BaseClient +from openviking.utils.config.config_loader import ( + DEFAULT_OVCLI_CONF, + OPENVIKING_CLI_CONFIG_ENV, + load_json_config, + resolve_config_path, +) from openviking.exceptions import ( AlreadyExistsError, DeadlineExceededError, @@ -56,7 +62,7 @@ class _HTTPObserver: Provides the same interface as the local observer but fetches data via HTTP. """ - def __init__(self, client: "HTTPClient"): + def __init__(self, client: "AsyncHTTPClient"): self._client = client self._cache = {} @@ -102,28 +108,45 @@ def is_healthy(self) -> bool: return status.get("is_healthy", False) -class HTTPClient(BaseClient): - """HTTP Client for OpenViking Server. +class AsyncHTTPClient(BaseClient): + """Async HTTP Client for OpenViking Server. Implements BaseClient interface using HTTP calls. + Supports auto-loading url/api_key from ovcli.conf when not provided. + + Examples: + # Explicit url + client = AsyncHTTPClient(url="http://localhost:1933", api_key="key") + + # Auto-load from ~/.openviking/ovcli.conf + client = AsyncHTTPClient() """ def __init__( self, - url: str, + url: Optional[str] = None, api_key: Optional[str] = None, - user: Optional[UserIdentifier] = None, ): - """Initialize HTTPClient. + """Initialize AsyncHTTPClient. Args: - url: OpenViking Server URL - api_key: API key for authentication - user: User name for session management + url: OpenViking Server URL. If not provided, reads from ovcli.conf. + api_key: API key for authentication. If not provided, reads from ovcli.conf. """ + if url is None: + config_path = resolve_config_path(None, OPENVIKING_CLI_CONFIG_ENV, DEFAULT_OVCLI_CONF) + if config_path: + cfg = load_json_config(config_path) + url = cfg.get("url") + api_key = api_key or cfg.get("api_key") + if not url: + raise ValueError( + "url is required. Pass it explicitly or configure in " + "~/.openviking/ovcli.conf (key: \"url\")." + ) self._url = url.rstrip("/") self._api_key = api_key - self._user = user or UserIdentifier.the_default_user() + self._user = UserIdentifier.the_default_user() self._http: Optional[httpx.AsyncClient] = None self._observer: Optional[_HTTPObserver] = None @@ -349,18 +372,20 @@ async def search( self, query: str, target_uri: str = "", + session: Optional[Any] = None, session_id: Optional[str] = None, limit: int = 10, score_threshold: Optional[float] = None, filter: Optional[Dict[str, Any]] = None, ) -> FindResult: """Semantic search with optional session context.""" + sid = session_id or (session.session_id if session else None) response = await self._http.post( "/api/v1/search/search", json={ "query": query, "target_uri": target_uri, - "session_id": session_id, + "session_id": sid, "limit": limit, "score_threshold": score_threshold, "filter": filter, diff --git a/openviking/client/local.py b/openviking/client/local.py index 3a7a541b..650a2d5a 100644 --- a/openviking/client/local.py +++ b/openviking/client/local.py @@ -22,17 +22,15 @@ class LocalClient(BaseClient): def __init__( self, path: Optional[str] = None, - user: Optional[UserIdentifier] = None, ): """Initialize LocalClient. Args: path: Local storage path (overrides ov.conf storage path) - user: User name for session management """ self._service = OpenVikingService( path=path, - user=user or UserIdentifier.the_default_user(), + user=UserIdentifier.the_default_user(), ) self._user = self._service.user diff --git a/openviking/client/session.py b/openviking/client/session.py index 0dc035e2..39f62e32 100644 --- a/openviking/client/session.py +++ b/openviking/client/session.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 """Lightweight Session class for OpenViking client. -Session delegates all operations to the underlying Client (LocalClient or HTTPClient). +Session delegates all operations to the underlying Client (LocalClient or AsyncHTTPClient). """ from typing import TYPE_CHECKING, Any, Dict @@ -24,7 +24,7 @@ def __init__(self, client: "BaseClient", session_id: str, user: UserIdentifier): """Initialize Session. Args: - client: The underlying client (LocalClient or HTTPClient) + client: The underlying client (LocalClient or AsyncHTTPClient) session_id: Session ID user: User name """ diff --git a/openviking/client/sync_http.py b/openviking/client/sync_http.py new file mode 100644 index 00000000..5a69ad62 --- /dev/null +++ b/openviking/client/sync_http.py @@ -0,0 +1,241 @@ +# Copyright (c) 2026 Beijing Volcano Engine Technology Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 +"""Synchronous HTTP Client for OpenViking. + +Wraps AsyncHTTPClient with synchronous methods. +""" + +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union + +if TYPE_CHECKING: + from openviking.client.session import Session + +from openviking.client.http import AsyncHTTPClient +from openviking.utils import run_async + + +class SyncHTTPClient: + """Synchronous HTTP Client for OpenViking Server. + + Wraps AsyncHTTPClient with synchronous methods. + Supports auto-loading url/api_key from ovcli.conf when not provided. + + Examples: + # Explicit url + client = SyncHTTPClient(url="http://localhost:1933", api_key="key") + client.initialize() + + # Auto-load from ~/.openviking/ovcli.conf + client = SyncHTTPClient() + client.initialize() + """ + + def __init__( + self, + url: Optional[str] = None, + api_key: Optional[str] = None, + ): + self._async_client = AsyncHTTPClient(url=url, api_key=api_key) + self._initialized = False + + # ============= Lifecycle ============= + + def initialize(self) -> None: + """Initialize the HTTP client.""" + run_async(self._async_client.initialize()) + self._initialized = True + + def close(self) -> None: + """Close the HTTP client and release resources.""" + run_async(self._async_client.close()) + self._initialized = False + + # ============= Session ============= + + def session(self, session_id: Optional[str] = None) -> "Session": + """Create new session or load existing session.""" + return self._async_client.session(session_id) + + def create_session(self) -> Dict[str, Any]: + """Create a new session.""" + return run_async(self._async_client.create_session()) + + def list_sessions(self) -> List[Any]: + """List all sessions.""" + return run_async(self._async_client.list_sessions()) + + def get_session(self, session_id: str) -> Dict[str, Any]: + """Get session details.""" + return run_async(self._async_client.get_session(session_id)) + + def delete_session(self, session_id: str) -> None: + """Delete a session.""" + run_async(self._async_client.delete_session(session_id)) + + def add_message(self, session_id: str, role: str, content: str) -> Dict[str, Any]: + """Add a message to a session.""" + return run_async(self._async_client.add_message(session_id, role, content)) + + def commit_session(self, session_id: str) -> Dict[str, Any]: + """Commit a session (archive and extract memories).""" + return run_async(self._async_client.commit_session(session_id)) + + # ============= Resource ============= + + def add_resource( + self, + path: str, + target: Optional[str] = None, + reason: str = "", + instruction: str = "", + wait: bool = False, + timeout: Optional[float] = None, + ) -> Dict[str, Any]: + """Add resource to OpenViking.""" + return run_async( + self._async_client.add_resource(path, target, reason, instruction, wait, timeout) + ) + + def add_skill( + self, + data: Any, + wait: bool = False, + timeout: Optional[float] = None, + ) -> Dict[str, Any]: + """Add skill to OpenViking.""" + return run_async(self._async_client.add_skill(data, wait=wait, timeout=timeout)) + + def wait_processed(self, timeout: Optional[float] = None) -> Dict[str, Any]: + """Wait for all processing to complete.""" + return run_async(self._async_client.wait_processed(timeout)) + + # ============= Search ============= + + def search( + self, + query: str, + target_uri: str = "", + session: Optional[Union["Session", Any]] = None, + session_id: Optional[str] = None, + limit: int = 10, + score_threshold: Optional[float] = None, + filter: Optional[Dict] = None, + ): + """Semantic search with optional session context.""" + return run_async( + self._async_client.search( + query=query, + target_uri=target_uri, + session=session, + session_id=session_id, + limit=limit, + score_threshold=score_threshold, + filter=filter, + ) + ) + + def find( + self, + query: str, + target_uri: str = "", + limit: int = 10, + score_threshold: Optional[float] = None, + filter: Optional[Dict] = None, + ): + """Semantic search without session context.""" + return run_async( + self._async_client.find(query, target_uri, limit, score_threshold, filter) + ) + + def grep(self, uri: str, pattern: str, case_insensitive: bool = False) -> Dict: + """Content search with pattern.""" + return run_async(self._async_client.grep(uri, pattern, case_insensitive)) + + def glob(self, pattern: str, uri: str = "viking://") -> Dict: + """File pattern matching.""" + return run_async(self._async_client.glob(pattern, uri)) + + # ============= File System ============= + + def ls(self, uri: str, simple: bool = False, recursive: bool = False) -> List[Any]: + """List directory contents.""" + return run_async(self._async_client.ls(uri, simple=simple, recursive=recursive)) + + def tree(self, uri: str) -> Dict: + """Get directory tree.""" + return run_async(self._async_client.tree(uri)) + + def stat(self, uri: str) -> Dict: + """Get resource status.""" + return run_async(self._async_client.stat(uri)) + + def mkdir(self, uri: str) -> None: + """Create directory.""" + run_async(self._async_client.mkdir(uri)) + + def rm(self, uri: str, recursive: bool = False) -> None: + """Remove resource.""" + run_async(self._async_client.rm(uri, recursive)) + + def mv(self, from_uri: str, to_uri: str) -> None: + """Move resource.""" + run_async(self._async_client.mv(from_uri, to_uri)) + + # ============= Content ============= + + def read(self, uri: str) -> str: + """Read file content.""" + return run_async(self._async_client.read(uri)) + + def abstract(self, uri: str) -> str: + """Read L0 abstract.""" + return run_async(self._async_client.abstract(uri)) + + def overview(self, uri: str) -> str: + """Read L1 overview.""" + return run_async(self._async_client.overview(uri)) + + # ============= Relations ============= + + def relations(self, uri: str) -> List[Dict[str, Any]]: + """Get relations for a resource.""" + return run_async(self._async_client.relations(uri)) + + def link(self, from_uri: str, uris: Union[str, List[str]], reason: str = "") -> None: + """Create link between resources.""" + run_async(self._async_client.link(from_uri, uris, reason)) + + def unlink(self, from_uri: str, uri: str) -> None: + """Remove link between resources.""" + run_async(self._async_client.unlink(from_uri, uri)) + + # ============= Pack ============= + + def export_ovpack(self, uri: str, to: str) -> str: + """Export context as .ovpack file.""" + return run_async(self._async_client.export_ovpack(uri, to)) + + def import_ovpack( + self, file_path: str, target: str, force: bool = False, vectorize: bool = True + ) -> str: + """Import .ovpack file.""" + return run_async(self._async_client.import_ovpack(file_path, target, force, vectorize)) + + # ============= Debug ============= + + def health(self) -> bool: + """Check server health.""" + return run_async(self._async_client.health()) + + def get_status(self) -> Dict[str, Any]: + """Get system status.""" + return self._async_client.get_status() + + def is_healthy(self) -> bool: + """Quick health check.""" + return self._async_client.is_healthy() + + @property + def observer(self): + """Get observer service for component status.""" + return self._async_client.observer diff --git a/openviking/storage/viking_fs.py b/openviking/storage/viking_fs.py index df536f79..e49208c3 100644 --- a/openviking/storage/viking_fs.py +++ b/openviking/storage/viking_fs.py @@ -534,17 +534,10 @@ async def get_relation_table(self, uri: str) -> List[RelationEntry]: def _uri_to_path(self, uri: str) -> str: """viking://user/memories/preferences/test -> /local/user/memories/preferences/test""" - if uri.startswith("viking://"): - path = uri.replace("viking://", "/") - elif uri.startswith("/"): - path = uri - else: - path = f"/{uri}" - - if not path.startswith("/local/"): - path = "/local" + path - - return path.rstrip("/") + remainder = uri[len("viking://"):].strip("/") + if not remainder: + return "/local" + return f"/local/{remainder}" def _path_to_uri(self, path: str) -> str: """/local/user/memories/preferences -> viking://user/memories/preferences""" diff --git a/tests/README.md b/tests/README.md index 6d00d305..f5e18366 100644 --- a/tests/README.md +++ b/tests/README.md @@ -126,7 +126,7 @@ Tests for the OpenViking client API (`AsyncOpenViking` / `SyncOpenViking`). ### server/ -Tests for the OpenViking HTTP server API and HTTPClient SDK. +Tests for the OpenViking HTTP server API and AsyncHTTPClient SDK. | File | Description | Key Test Cases | |------|-------------|----------------| @@ -140,7 +140,7 @@ Tests for the OpenViking HTTP server API and HTTPClient SDK. | `test_api_relations.py` | Relations endpoints | Get relations, link single/multiple targets, unlink | | `test_api_observer.py` | Observer endpoints | Queue, VikingDB, VLM, system observer status | | `test_error_scenarios.py` | Error handling | Invalid JSON, missing fields, not found, wrong content type, invalid URI format | -| `test_http_client_sdk.py` | HTTPClient SDK E2E | Health, add resource, wait, ls, mkdir, tree, session lifecycle, find, full workflow (real HTTP server) | +| `test_http_client_sdk.py` | AsyncHTTPClient SDK E2E | Health, add resource, wait, ls, mkdir, tree, session lifecycle, find, full workflow (real HTTP server) | ### session/ diff --git a/tests/cli/test_cli.py b/tests/cli/test_cli.py index 42c014cc..daa2d2d0 100644 --- a/tests/cli/test_cli.py +++ b/tests/cli/test_cli.py @@ -57,7 +57,11 @@ def _run_cli(args, server_url, env=None, expected_exit_code=0): def test_requires_ovcli_conf(): - result = runner.invoke(app, ["find", "hello"], env={}) + result = runner.invoke( + app, + ["find", "hello"], + env={"OPENVIKING_CLI_CONFIG_FILE": "/tmp/nonexistent/ovcli.conf"}, + ) assert result.exit_code == 2 assert "ovcli.conf" in result.output diff --git a/tests/client/test_lifecycle.py b/tests/client/test_lifecycle.py index 09d6193a..677d4bbd 100644 --- a/tests/client/test_lifecycle.py +++ b/tests/client/test_lifecycle.py @@ -6,7 +6,6 @@ from pathlib import Path from openviking import AsyncOpenViking -from openviking.session.user_id import UserIdentifier class TestClientInitialization: @@ -35,7 +34,7 @@ class TestClientClose: async def test_close_success(self, test_data_dir: Path): """Test normal close""" await AsyncOpenViking.reset() - client = AsyncOpenViking(path=str(test_data_dir), user=UserIdentifier.the_default_user("test")) + client = AsyncOpenViking(path=str(test_data_dir)) await client.initialize() await client.close() @@ -46,7 +45,7 @@ async def test_close_success(self, test_data_dir: Path): async def test_close_idempotent(self, test_data_dir: Path): """Test repeated close is safe""" await AsyncOpenViking.reset() - client = AsyncOpenViking(path=str(test_data_dir), user=UserIdentifier.the_default_user("test")) + client = AsyncOpenViking(path=str(test_data_dir)) await client.initialize() await client.close() @@ -62,12 +61,12 @@ async def test_reset_clears_singleton(self, test_data_dir: Path): """Test reset clears singleton""" await AsyncOpenViking.reset() - client1 = AsyncOpenViking(path=str(test_data_dir), user=UserIdentifier.the_default_user("test")) + client1 = AsyncOpenViking(path=str(test_data_dir)) await client1.initialize() await AsyncOpenViking.reset() - client2 = AsyncOpenViking(path=str(test_data_dir), user=UserIdentifier.the_default_user("test")) + client2 = AsyncOpenViking(path=str(test_data_dir)) # Should be new instance after reset assert client1 is not client2 @@ -81,8 +80,8 @@ async def test_embedded_mode_singleton(self, test_data_dir: Path): """Test embedded mode uses singleton""" await AsyncOpenViking.reset() - client1 = AsyncOpenViking(path=str(test_data_dir), user=UserIdentifier.the_default_user("test")) - client2 = AsyncOpenViking(path=str(test_data_dir), user=UserIdentifier.the_default_user("test")) + client1 = AsyncOpenViking(path=str(test_data_dir)) + client2 = AsyncOpenViking(path=str(test_data_dir)) assert client1 is client2 diff --git a/tests/conftest.py b/tests/conftest.py index 41a88d63..1e5cf17d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -12,7 +12,6 @@ import pytest_asyncio from openviking import AsyncOpenViking -from openviking.session.user_id import UserIdentifier # Test data root directory TEST_ROOT = Path(__file__).parent @@ -150,7 +149,7 @@ async def client(test_data_dir: Path) -> AsyncGenerator[AsyncOpenViking, None]: """Create initialized OpenViking client""" await AsyncOpenViking.reset() - client = AsyncOpenViking(path=str(test_data_dir), user=UserIdentifier.the_default_user("test_user")) + client = AsyncOpenViking(path=str(test_data_dir)) await client.initialize() yield client @@ -164,7 +163,7 @@ async def uninitialized_client(test_data_dir: Path) -> AsyncGenerator[AsyncOpenV """Create uninitialized OpenViking client (for testing initialization flow)""" await AsyncOpenViking.reset() - client = AsyncOpenViking(path=str(test_data_dir), user=UserIdentifier.the_default_user("test_user")) + client = AsyncOpenViking(path=str(test_data_dir)) yield client diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 756bfae8..bebed069 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -4,8 +4,7 @@ """Shared fixtures for integration tests. Automatically starts an OpenViking server in a background thread so that -HTTPClient / AsyncOpenViking integration tests can run without a manually -started server process. +AsyncHTTPClient integration tests can run without a manually started server process. """ import shutil diff --git a/tests/integration/test_full_workflow.py b/tests/integration/test_full_workflow.py index aa8b71a2..ab4aa736 100644 --- a/tests/integration/test_full_workflow.py +++ b/tests/integration/test_full_workflow.py @@ -10,7 +10,6 @@ from openviking import AsyncOpenViking from openviking.message import TextPart -from openviking.session.user_id import UserIdentifier @pytest_asyncio.fixture(scope="function") @@ -22,7 +21,7 @@ async def integration_client(test_data_dir: Path): shutil.rmtree(test_data_dir, ignore_errors=True) test_data_dir.mkdir(parents=True, exist_ok=True) - client = AsyncOpenViking(path=str(test_data_dir), user=UserIdentifier.the_default_user("integration_test_user")) + client = AsyncOpenViking(path=str(test_data_dir)) await client.initialize() yield client diff --git a/tests/integration/test_http_integration.py b/tests/integration/test_http_integration.py index 90f9a2fe..a152f508 100644 --- a/tests/integration/test_http_integration.py +++ b/tests/integration/test_http_integration.py @@ -9,19 +9,17 @@ import pytest import pytest_asyncio -from openviking import AsyncOpenViking -from openviking.client import HTTPClient +from openviking.client.http import AsyncHTTPClient from openviking.exceptions import NotFoundError -from openviking.session.user_id import UserIdentifier class TestHTTPClientIntegration: - """Integration tests for HTTPClient.""" + """Integration tests for AsyncHTTPClient.""" @pytest_asyncio.fixture async def client(self, server_url): - """Create and initialize HTTPClient.""" - client = HTTPClient(url=server_url, user=UserIdentifier.the_default_user("test_user")) + """Create and initialize AsyncHTTPClient.""" + client = AsyncHTTPClient(url=server_url) await client.initialize() yield client await client.close() @@ -83,8 +81,8 @@ class TestSessionIntegration: @pytest_asyncio.fixture async def client(self, server_url): - """Create and initialize HTTPClient.""" - client = HTTPClient(url=server_url, user=UserIdentifier.the_default_user("test_user")) + """Create and initialize AsyncHTTPClient.""" + client = AsyncHTTPClient(url=server_url) await client.initialize() yield client await client.close() @@ -119,43 +117,38 @@ async def test_list_sessions(self, client): assert isinstance(result, list) -class TestAsyncOpenVikingHTTPMode: - """Integration tests for AsyncOpenViking in HTTP mode.""" +class TestAsyncHTTPClientIntegration: + """Integration tests for AsyncHTTPClient as a standalone client.""" @pytest_asyncio.fixture - async def ov(self, server_url): - """Create AsyncOpenViking in HTTP mode.""" - client = AsyncOpenViking(url=server_url, user=UserIdentifier.the_default_user("test_user")) + async def client(self, server_url): + """Create AsyncHTTPClient.""" + client = AsyncHTTPClient(url=server_url) await client.initialize() yield client await client.close() @pytest.mark.asyncio - async def test_http_mode_detection(self, ov): - """Test HTTP mode is correctly detected.""" - assert isinstance(ov._client, HTTPClient) - - @pytest.mark.asyncio - async def test_find_via_ov(self, ov): - """Test find via AsyncOpenViking.""" - result = await ov.find(query="test", limit=5) + async def test_find_via_client(self, client): + """Test find via AsyncHTTPClient.""" + result = await client.find(query="test", limit=5) assert result is not None @pytest.mark.asyncio - async def test_ls_via_ov(self, ov): - """Test ls via AsyncOpenViking.""" - result = await ov.ls("viking://") + async def test_ls_via_client(self, client): + """Test ls via AsyncHTTPClient.""" + result = await client.ls("viking://") assert isinstance(result, list) @pytest.mark.asyncio - async def test_observer_access(self, ov): - """Test observer access in HTTP mode.""" - observer = ov.observer + async def test_observer_access(self, client): + """Test observer access.""" + observer = client.observer assert observer is not None @pytest.mark.asyncio - async def test_session_via_ov(self, ov): - """Test session creation via AsyncOpenViking.""" - session = ov.session() + async def test_session_via_client(self, client): + """Test session creation via AsyncHTTPClient.""" + session = client.session() assert session is not None assert session._client is not None diff --git a/tests/server/conftest.py b/tests/server/conftest.py index 9d749957..5eddf1e2 100644 --- a/tests/server/conftest.py +++ b/tests/server/conftest.py @@ -108,7 +108,7 @@ async def client_with_resource(client, service, sample_markdown_file): # --------------------------------------------------------------------------- -# SDK fixtures: real uvicorn server + HTTPClient (end-to-end tests) +# SDK fixtures: real uvicorn server + AsyncHTTPClient (end-to-end tests) # --------------------------------------------------------------------------- diff --git a/tests/server/test_http_client_sdk.py b/tests/server/test_http_client_sdk.py index d918bed9..a1008058 100644 --- a/tests/server/test_http_client_sdk.py +++ b/tests/server/test_http_client_sdk.py @@ -1,24 +1,22 @@ # Copyright (c) 2026 Beijing Volcano Engine Technology Co., Ltd. # SPDX-License-Identifier: Apache-2.0 -"""SDK tests using HTTPClient against a real uvicorn server.""" +"""SDK tests using AsyncHTTPClient against a real uvicorn server.""" from pathlib import Path import pytest_asyncio -from openviking.client.http import HTTPClient -from openviking.session.user_id import UserIdentifier +from openviking.client.http import AsyncHTTPClient from tests.server.conftest import SAMPLE_MD_CONTENT, TEST_TMP_DIR @pytest_asyncio.fixture() async def http_client(running_server): - """Create an HTTPClient connected to the running server.""" + """Create an AsyncHTTPClient connected to the running server.""" port, svc = running_server - client = HTTPClient( + client = AsyncHTTPClient( url=f"http://127.0.0.1:{port}", - user=UserIdentifier.the_default_user("sdk_test_user"), ) await client.initialize() yield client, svc From 4976ac50ca8d00fa33a715ab530589f1e52d8c30 Mon Sep 17 00:00:00 2001 From: qin-ctx Date: Thu, 12 Feb 2026 12:06:42 +0800 Subject: [PATCH 2/2] fix queue --- openviking/service/core.py | 5 +---- openviking/storage/vikingdb_manager.py | 9 ++------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/openviking/service/core.py b/openviking/service/core.py index 7f5ac143..9c0d48e6 100644 --- a/openviking/service/core.py +++ b/openviking/service/core.py @@ -24,7 +24,7 @@ from openviking.storage.collection_schemas import init_context_collection from openviking.storage.viking_fs import VikingFS, init_viking_fs from openviking.utils import get_logger -from openviking.utils.config import OpenVikingConfig, get_openviking_config +from openviking.utils.config import get_openviking_config from openviking.utils.config.open_viking_config import initialize_openviking_config from openviking.utils.config.storage_config import StorageConfig from openviking.utils.resource_processor import ResourceProcessor @@ -178,9 +178,6 @@ async def initialize(self) -> None: # Create context collection await init_context_collection(self._vikingdb_manager) - # Start queues after collections are ready - self._vikingdb_manager.start_queues() - # Initialize VikingFS self._viking_fs = init_viking_fs( agfs_url=self._agfs_url or "http://localhost:8080", diff --git a/openviking/storage/vikingdb_manager.py b/openviking/storage/vikingdb_manager.py index 9d96105f..59f9b8f3 100644 --- a/openviking/storage/vikingdb_manager.py +++ b/openviking/storage/vikingdb_manager.py @@ -59,11 +59,12 @@ def __init__( self._embedding_handler = None self._semantic_processor = None - # Initialize queue manager (but don't start yet — collections must be created first) + # Initialize queue manager if AGFS URL is provided self._init_queue_manager() if self._queue_manager: self._init_embedding_queue() self._init_semantic_queue() + self._queue_manager.start() def _init_queue_manager(self): """Initialize queue manager for background processing.""" @@ -111,12 +112,6 @@ def _init_semantic_queue(self): ) logger.info("Semantic queue initialized with SemanticProcessor") - def start_queues(self): - """Start the queue manager. Call after collections are created.""" - if self._queue_manager: - self._queue_manager.start() - logger.info("Queue manager started") - async def close(self) -> None: """Close storage connection and release resources, including queue manager.""" try: