Skip to content
Back to skills

1757 Server Cli Design 1ebeb017

ASecurity

OpenViking 目前主要以 Python SDK 形式提供服务,支持两种部署模式: - **Embedded 模式**:自动启动本地 AGFS 子进程和 VikingVectorIndex(单例) - **Service 模式**:连接远程 AGFS 和 VectorDB 服务(非单例)

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 11, 2026
developmentjavascripttypescriptpythongojavashellbashsqlfastapidocker

Works with

  • claude desktop
  • cli
  • api
  • mcp

Security analysis

A92/100
  • mediumUses curl or wget to download content
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 1757-server-cli-design_1ebeb017 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 1757 Server Cli Design 1ebeb017?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 1757 Server Cli Design 1ebeb017
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-1757-server-cli-design-1ebeb017/badge)](https://www.skillsdirectory.com/skills/tools-only-1757-server-cli-design-1ebeb017)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# OpenViking Server/CLI 模式技术方案

## 一、背景与目标

### 1.1 当前架构

OpenViking 目前主要以 Python SDK 形式提供服务,支持两种部署模式:
- **Embedded 模式**:自动启动本地 AGFS 子进程和 VikingVectorIndex(单例)
- **Service 模式**:连接远程 AGFS 和 VectorDB 服务(非单例)

### 1.2 现有问题

| 问题 | 描述 |
|------|------|
| 缺少统一 CLI | 无法通过命令行管理 OpenViking |
| 服务分散 | AGFS 和 VectorDB 需要分别启动 |
| 无 HTTP API | 核心功能没有 HTTP API 暴露 |
| 部署复杂 | 生产环境需要手动协调多个服务 |

### 1.3 目标

1. **CLI 模式**:提供完整的命令行工具
2. **Server 模式**:提供统一的 HTTP API 服务
3. **保持兼容**:现有 SDK 使用方式不变

---

## 二、竞品分析与最佳实践

### 2.1 竞品对比

| 产品 | CLI 设计 | Server 模式 | API 风格 | 部署模式 |
|------|----------|-------------|----------|----------|
| **Chroma** | `chroma run/db/login` | 内置 FastAPI | RESTful | in-memory/persistent/client-server |
| **Qdrant** | 无独立 CLI | 独立服务 | RESTful + gRPC | standalone/distributed |
| **Milvus** | `milvus_cli` 交互式 | 独立服务 | RESTful + gRPC | lite/standalone/distributed |
| **Mem0** | 无 CLI | Platform + OSS | RESTful | managed/self-hosted |
| **LlamaIndex** | 无统一 CLI | 微服务架构 | RESTful | self-hosted |

### 2.2 Chroma 设计参考

Chroma 的 CLI 设计简洁实用:
```bash
chroma run --path <directory>     # 启动服务器
chroma db create <name>           # 创建数据库
chroma login                      # 认证登录
chroma browse                     # 浏览数据
```

**借鉴点**:
- 三种运行模式(in-memory/persistent/client-server)
- 简洁的命令结构
- 环境变量配置支持

### 2.3 Qdrant API 设计参考

Qdrant 的 REST API 采用资源层级结构:
```
POST /collections/{collection_name}/points/search
GET  /collections/{collection_name}/points/{id}
PUT  /collections/{collection_name}/points
```

**借鉴点**:
- 资源层级 URL 设计
- POST 用于复杂查询(请求体包含向量和过滤条件)
- 完善的过滤 DSL
- 一致性级别控制

### 2.4 Milvus CLI 设计参考

Milvus CLI 采用模块化架构:
```
milvus_cli/
├── Connection.py    # 连接管理
├── Collection.py    # 集合操作
├── Database.py      # 数据库管理
├── Index.py         # 索引管理
├── Partition.py     # 分区管理
├── Data.py          # 数据操作
├── Role.py          # 角色管理
└── User.py          # 用户管理
```

**借鉴点**:
- 模块化命令组织
- 交互式 CLI 支持
- 完整的 RBAC 支持

### 2.5 Mem0 架构参考

Mem0 的双部署模式:
- **Platform API**:托管服务,API Key 认证
- **OSS SDK**:自托管,直接调用

**借鉴点**:
- 统一的搜索管道(Platform 和 OSS 共用)
- 复杂的过滤 DSL(AND/OR 逻辑)
- 用户隔离(user_id scoping)

### 2.6 Redis/MySQL 客户端设计参考

Redis 和 MySQL 的客户端设计模式:
- **Server 独立运行**:Server 作为独立进程启动,不依赖 Client
- **Client 仅连接**:Client 只负责连接 Server,不负责启动或管理 Server
- **配置分离**:Server 配置和 Client 配置分开管理

```python
# Redis 示例
import redis
r = redis.Redis(host='localhost', port=6379)  # 仅连接,不启动 Server
r.set('foo', 'bar')

# MySQL 示例
import mysql.connector
conn = mysql.connector.connect(host='localhost', user='root')  # 仅连接
```

**借鉴点**:
- Client 无需 `initialize()` 方法
- 连接参数通过构造函数传入
- Server 生命周期独立于 Client

### 2.7 响应格式与错误处理最佳实践

#### Qdrant 响应格式
```json
{
  "status": "ok",
  "time": 0.123,
  "result": {...},
  "usage": {"cpu": 100, "vector_io_read": 40}
}
```
- 统一的 `status/time/result` 包装
- 可选的 `usage` 字段用于资源监控
- 错误通过 HTTP 状态码 + 消息字符串返回

#### Milvus 错误码
```python
# 数字错误码 + 消息
(code=1, message="UnexpectedError...")
(code=2, message="Connection timeout...")
(code=2200, message="Retry exhausted...")
```
- 基于 gRPC 的数字错误码
- 包含 `code`, `message`, `reason` 三元组

#### gRPC 标准状态码(业界标准)
| 码 | 名称 | HTTP | 说明 |
|----|------|------|------|
| 0 | OK | 200 | 成功 |
| 3 | INVALID_ARGUMENT | 400 | 参数无效 |
| 5 | NOT_FOUND | 404 | 资源不存在 |
| 7 | PERMISSION_DENIED | 403 | 权限不足 |
| 13 | INTERNAL | 500 | 内部错误 |
| 14 | UNAVAILABLE | 503 | 服务不可用 |
| 16 | UNAUTHENTICATED | 401 | 未认证 |

**借鉴点**:
- gRPC 17 种标准状态码覆盖所有常见场景
- 明确的 HTTP 状态码映射
- 可重试 vs 不可重试错误分类

### 2.8 最佳实践总结

| 方面 | 最佳实践 | 来源 |
|------|----------|------|
| **CLI 结构** | 动词-名词命令(`run`, `db create`) | Chroma |
| **API 路由** | 资源层级(`/collections/{name}/points`) | Qdrant |
| **认证** | API Key + 可选 JWT | Qdrant, Mem0 |
| **部署模式** | 三层(embedded/standalone/distributed) | Milvus |
| **过滤系统** | JSON DSL(AND/OR/比较操作符) | Mem0, Qdrant |
| **模块化** | 按资源类型组织命令 | Milvus |
| **Client 设计** | 仅连接,不管理 Server 生命周期 | Redis, MySQL |
| **响应格式** | `{status, time, result}` 统一包装 | Qdrant |
| **错误码** | gRPC 标准状态码(字符串形式) | gRPC, Milvus |
| **HTTP 映射** | 错误码到 HTTP 状态码的标准映射 | gRPC |

### 2.9 参考资料

- [Chroma Documentation](https://docs.trychroma.com/) - CLI 设计参考
- [Qdrant API Reference](https://api.qdrant.tech/) - REST API 设计参考
- [Milvus CLI](https://github.com/zilliztech/milvus_cli) - 模块化 CLI 参考
- [Mem0 Documentation](https://docs.mem0.ai/) - 双部署模式参考
- [LlamaIndex Architecture](https://developers.llamaindex.ai/python/cloud/self_hosting/architecture/) - 微服务架构参考
- [gRPC Status Codes](https://grpc.github.io/grpc/core/md_doc_statuscodes.html) - 标准错误码定义
- [gRPC HTTP Mapping](https://grpc.github.io/grpc/core/md_doc_http-grpc-status-mapping.html) - HTTP 状态码映射
- [Qdrant Common Errors](https://qdrant.tech/documentation/guides/common-errors/) - 错误处理参考
- [Chroma Troubleshooting](https://docs.trychroma.com/troubleshooting) - 异常类设计参考

---

## 三、架构设计

### 3.0 接口定位

OpenViking 提供三种接口,面向不同使用场景:

| 接口 | 使用者 | 场景 | 特点 |
|------|--------|------|------|
| **Python SDK** | Agent 开发者 | Agent 代码中调用 | 对象化 API,支持异步,client 实例维护状态 |
| **Bash CLI** | Agent / 运维人员 | Agent subprocess 调用、运维脚本 | 非交互式,通过环境变量管理状态 |
| **HTTP API** | 任意语言客户端 | 跨语言集成、微服务调用 | RESTful,无状态,每次请求带身份信息 |

**选型建议**:
- **Agent 开发**:优先使用 Python SDK,可以维护 client 实例状态
- **Agent 调用外部工具**:使用 Bash CLI,通过环境变量传递身份信息
- **非 Python 环境**:使用 HTTP API

### 3.1 分层架构

```
┌─────────────────────────────────────────────────────────────┐
│                      CLI Layer                               │
│  openviking <command> [options]                              │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                     Client Layer                             │
│  ┌─────────────────┐  ┌─────────────────┐                   │
│  │ LocalClient     │  │ HTTPClient      │                   │
│  │ (直接调用Service)│  │ (HTTP调用Server)│                   │
│  └─────────────────┘  └─────────────────┘                   │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                     Service Layer                            │
│  ┌─────────────────────────────────────────────────────────┐│
│  │ OpenVikingService                                        ││
│  │ - ResourceService (资源解析、向量化)                      ││
│  │ - SearchService (语义搜索)                               ││
│  │ - SessionService (会话管理)                              ││
│  │ - FSService (文件系统操作)                               ││
│  │ - DebugService (调试服务)                                ││
│  └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                   Infrastructure Layer                       │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐          │
│  │ VikingFS    │  │ VikingDB    │  │ AGFS        │          │
│  └─────────────┘  └─────────────┘  └─────────────┘          │
└─────────────────────────────────────────────────────────────┘
```

### 3.2 部署模式

#### 选型决策

**为什么支持多种部署模式**:

1. **嵌入式模式**:降低入门门槛,开发者无需部署服务即可使用
2. **独立服务模式**:支持团队共享、多 Agent 并发访问
3. **混合模式**:灵活组合,适应不同基础设施环境

**参考业界实践**:
- Chroma:in-memory / persistent / client-server 三种模式
- Milvus:lite / standalone / distributed 三种模式
- SQLite:嵌入式 vs PostgreSQL/MySQL 独立服务

| 模式 | 说明 | 适用场景 |
|------|------|----------|
| **嵌入式** | SDK 自动启动本地 AGFS + VectorDB | 本地开发、单机部署 |
| **独立服务** | 通过 CLI 启动 Server,SDK/CLI 通过 HTTP 连接 | 团队共享、生产环境 |
| **混合模式** | 本地 Server + 远程 AGFS/VectorDB | 分布式部署 |

```
嵌入式模式:
┌─────────────────────────────────────┐
│ Python Process                       │
│  ┌─────────┐  ┌─────────┐           │
│  │ SDK     │──│ Service │           │
│  └─────────┘  └────┬────┘           │
│                    │                 │
│  ┌─────────┐  ┌────┴────┐           │
│  │ AGFS    │  │ VectorDB│           │
│  └─────────┘  └─────────┘           │
└─────────────────────────────────────┘

独立服务模式:
┌─────────────┐      ┌─────────────────────────────────────┐
│ CLI / SDK   │─HTTP─│ OpenViking Server                    │
│ (Client)    │      │  ┌─────────┐  ┌─────────┐           │
└─────────────┘      │  │ Service │──│ AGFS    │           │
                     │  └────┬────┘  └─────────┘           │
                     │       │                              │
                     │  ┌────┴────┐                        │
                     │  │ VectorDB│                        │
                     │  └─────────┘                        │
                     └─────────────────────────────────────┘
```

### 3.3 身份与隔离

支持多租户场景,首先通过 account_id 区分不同的应用租户,然后允许通过 `user` 和 `agent` 实现租户内的身份隔离:

用户或智能体身份标识详见 `from openviking.session.user_id import UserIdentifier`

| 参数 | 说明 | 默认值 |
|------|------|------|
| `account_id` | 租户账号标识,区分不同的租户,租户内 user 和 agent id 空间隔离,也就是保证租户之间数据隔离 | `default` |
| `user_id` | 用户身份标识,用户在租户内的唯一标识符 | `default` |
| `agent_id` | 智能体身份标识,智能体或应用在租户内的唯一标识符 | `default` |

> 举例说明,如果一个团队部署一个 OpenViking 上下文数据库,让团队成员共享一部分上下文资料,但各自保留独立的记忆数据,团队使用统一的 account_id,每个成员使用不同的 user_id 来区分,成员使用不同的应用(如 OpenCode, OpenClaw 等)则使用不同的 agent_id 来区分。
> 一般情况下,`account_id` 不会出现在 viking:// uri 中,因为每个租户的用户数据都是隔离的,不需要在 uri 中指定租户。


### 3.4 配置管理

#### Server 配置

服务端配置统一使用 JSON 配置文件,通过 `--config` 或 `OPENVIKING_CONFIG_FILE` 环境变量指定(与 `OpenVikingConfig` 共用同一个文件):

```json
{
  "server": {
    "host": "0.0.0.0",
    "port": 1933,
    "api_key": "your-api-key"
  },
  "storage": {
    "path": "~/.openviking/data"
  },
  "embedding": {
    "dense": {
      "provider": "openai",
      "model": "text-embedding-3-small"
    }
  },
  "vlm": {
    "provider": "openai",
    "model": "gpt-4o"
  }
}
```

#### Client 配置

客户端 SDK 通过构造函数参数或环境变量配置,不使用配置文件(参考 Weaviate/ChromaDB/Qdrant 等主流产品的设计):

```python
# 方式一:构造函数参数
client = OpenViking(url="http://localhost:1933", api_key="your-api-key")

# 方式二:环境变量(OPENVIKING_URL / OPENVIKING_API_KEY)
client = OpenViking()
```

#### 环境变量

| 环境变量 | 说明 | 示例 |
|----------|------|------|
| `OPENVIKING_URL` | Server URL | `http://localhost:1933` |
| `OPENVIKING_API_KEY` | API Key | `sk-xxx` |
| `OPENVIKING_USER` | 用户标识 | `alice` |
| `OPENVIKING_AGENT` | Agent 标识 | `agent-a1` |
| `OPENVIKING_PATH` | 本地数据路径(嵌入式模式) | `./data` |

**为什么 `user`/`agent` 用环境变量而不是配置文件**:
1. **进程隔离**:环境变量是进程级的,多个 Agent 进程互不干扰
2. **无并发冲突**:不会出现多个进程同时写配置文件的问题
3. **易于设置**:Agent 启动时设置一次,后续调用自动继承

#### 配置优先级

从高到低:
1. 命令行参数 / 构造函数参数(`--url`, `--user` 等)
2. 环境变量(`OPENVIKING_URL`, `OPENVIKING_API_KEY` 等)
3. 配置文件(`OPENVIKING_CONFIG_FILE`,仅服务端)

---

## 四、模块设计

### 4.1 模块职责

| 模块 | 职责 | 依赖 |
|------|------|------|
| **service/** | 核心业务逻辑,与传输层无关 | Infrastructure Layer |
| **server/** | HTTP API 服务,调用 Service 层 | service/ |
| **cli/** | 命令行工具,调用 Client 层 | client/ |
| **client/** | 客户端抽象,支持本地和 HTTP 两种模式 | service/ 或 HTTP |

**设计原则**:
- **Service 层独立**:业务逻辑不依赖传输层(HTTP/CLI),便于测试和复用
- **Client 层抽象**:LocalClient 和 HTTPClient 实现相同接口,上层无感知
- **CLI 薄层**:CLI 只负责参数解析和输出格式化,业务逻辑在 Service 层

### 4.2 目录结构

```
openviking/
├── service/                     # Service 层(业务逻辑)
│   ├── __init__.py
│   ├── core.py                  # OpenVikingService
│   ├── fs_service.py            # 文件系统操作
│   ├── resource_service.py      # 资源导入、技能添加
│   ├── search_service.py        # 语义搜索
│   ├── session_service.py       # 会话管理
│   ├── relation_service.py      # 关联管理
│   ├── pack_service.py          # 导入导出
│   └── debug_service.py         # 调试服务
│
├── server/                      # HTTP Server
│   ├── __init__.py
│   ├── app.py                   # FastAPI 应用
│   ├── bootstrap.py             # 服务启动器
│   ├── config.py                # 服务器配置
│   ├── dependencies.py          # 依赖注入
│   └── routers/
│       ├── resources.py         # /api/v1/resources
│       ├── filesystem.py        # /api/v1/fs
│       ├── content.py           # /api/v1/content
│       ├── search.py            # /api/v1/search
│       ├── relations.py         # /api/v1/relations
│       ├── sessions.py          # /api/v1/sessions
│       └── debug.py             # /api/v1/debug
│
├── cli/                         # CLI 模块
│   ├── __init__.py
│   ├── main.py                  # CLI 入口
│   └── output.py                # 输出格式化
│
├── client/                      # Client 层
│   ├── __init__.py
│   ├── local.py                 # LocalClient
│   └── http.py                  # HTTPClient
│
├── async_client.py              # 兼容层
└── sync_client.py               # 兼容层
```

### 4.3 pyproject.toml

```toml
[project.scripts]
openviking = "openviking.cli.main:app"
```

### 4.4 新增依赖

```toml
dependencies = [
    # ... 现有依赖
    # argparse is used for CLI (part of Python stdlib, no extra dependency needed)
    "rich>=13.0.0",      # CLI 美化输出
]
```

---

## 五、接口设计

### 5.1 核心方法定义

| 方法 | 参数 | 说明 |
|------|------|------|
| `add_resource` | `path, target, wait, timeout` | 导入资源 |
| `add_skill` | `data, wait` | 添加技能 |
| `ls` | `uri, simple, recursive` | 列出目录 |
| `tree` | `uri` | 目录树 |
| `stat` | `uri` | 状态信息 |
| `mkdir` | `uri` | 创建目录 |
| `rm` | `uri, recursive` | 删除 |
| `mv` | `from_uri, to_uri` | 移动 |
| `read` | `uri` | 读取完整内容 (L2) |
| `abstract` | `uri` | 读取摘要 (L0) |
| `overview` | `uri` | 读取概览 (L1) |
| `find` | `query, target_uri, limit, threshold` | 语义搜索 |
| `search` | `query, target_uri, session, limit` | 带上下文搜索 |
| `grep` | `uri, pattern, case_insensitive` | 内容搜索 |
| `glob` | `pattern, uri` | 模式匹配 |
| `link` | `from_uri, uris, reason` | 创建关联 |
| `unlink` | `from_uri, uri` | 删除关联 |
| `relations` | `uri` | 查看关联 |
| `export_ovpack` | `uri, to` | 导出 |
| `import_ovpack` | `file, target, force, vectorize` | 导入 |
| `session` | `user` | 创建/获取 Session 对象 |
| `sessions` | - | 获取所有 Session 对象列表 |
| `wait_processed` | `timeout` | 等待处理完成 |
| `get_status` | - | 获取系统状态(包含 queue/vikingdb/vlm 组件状态) |
| `is_healthy` | - | 快速健康检查 |

**Session 对象方法:**

| 方法 | 参数 | 说明 |
|------|------|------|
| `add_message` | `role, content` | 添加消息 |
| `compress` | - | 压缩会话 |
| `extract` | - | 提取记忆 |
| `delete` | - | 删除会话 |

### 5.2 统一返回值格式

参考 Qdrant 的响应格式设计,采用 `{status, time, result}` 统一包装:

**成功响应**:
```json
{
  "status": "ok",
  "result": {...},
  "time": 0.123,
  "usage": {                    // 可选,用于监控
    "tokens": 100,
    "vectors_scanned": 1000
  }
}
```

**错误响应**:
```json
{
  "status": "error",
  "error": {
    "code": "NOT_FOUND",         // gRPC 风格错误码
    "message": "Resource not found: viking://...",
    "details": {...}            // 可选,额外错误信息
  },
  "time": 0.05
}
```

**Python 数据模型**:
```python
@dataclass
class Response:
    status: str                 # "ok" | "error"
    result: Optional[Any] = None
    error: Optional[ErrorInfo] = None
    time: float = 0.0
    usage: Optional[UsageInfo] = None

@dataclass
class ErrorInfo:
    code: str                   # NOT_FOUND, INVALID_URI, ...
    message: str
    details: Optional[dict] = None

@dataclass
class UsageInfo:
    tokens: Optional[int] = None
    vectors_scanned: Optional[int] = None
```

### 5.3 各方法返回值

**ls / tree**
```json
{
  "status": "ok",
  "result": {
    "entries": [
      {"name": "doc.md", "type": "file", "uri": "viking://resources/doc.md", "size": 1024},
      {"name": "images/", "type": "dir", "uri": "viking://resources/images/", "children_count": 5}
    ]
  },
  "time": 0.05
}
```

**find / search**
```json
{
  "status": "ok",
  "result": {
    "items": [
      {
        "uri": "viking://resources/doc.md",
        "score": 0.92,
        "content": "...",
        "abstract": "...",
        "metadata": {"type": "markdown", "scope": "resources"}
      }
    ],
    "query": "how to use openviking",
    "total": 10
  },
  "time": 0.15,
  "usage": {"vectors_scanned": 1000}
}
```

**read / abstract / overview**
```json
{
  "status": "ok",
  "result": {
    "uri": "viking://resources/doc.md",
    "content": "...",
    "level": "L2"
  },
  "time": 0.02
}
```

**stat**
```json
{
  "status": "ok",
  "result": {
    "uri": "viking://resources/doc.md",
    "type": "file",
    "size": 1024,
    "created_at": "2024-01-01T00:00:00Z",
    "updated_at": "2024-01-02T00:00:00Z",
    "has_abstract": true,
    "has_overview": true,
    "vectorized": true
  },
  "time": 0.01
}
```

**add_resource**
```json
{
  "status": "ok",
  "result": {
    "uri": "viking://resources/my-docs/",
    "files_count": 10,
    "processing_status": "processing",
    "queue": {
      "vectorize": {"processed": 5, "total": 10, "failed": 0}
    }
  },
  "time": 0.5
}
```

**session**(Python CLI 返回 Session 对象,HTTP API 返回 JSON)
```python
# Python CLI
session = client.session(user="alice")
session.id          # "session-abc123"
session.user        # "alice"
session.created_at  # datetime
session.message_count  # 10
session.compressed  # False

# HTTP API 返回
{
  "status": "ok",
  "result": {
    "session_id": "session-abc123",
    "user": "alice",
    "created_at": "2024-01-01T00:00:00Z",
    "message_count": 10,
    "compressed": false
  },
  "time": 0.02
}
```

**错误示例**
```json
{
  "status": "error",
  "error": {
    "code": "NOT_FOUND",
    "message": "Resource not found: viking://resources/nonexistent/"
  },
  "time": 0.01
}
```

```json
{
  "status": "error",
  "error": {
    "code": "INVALID_URI",
    "message": "Invalid URI format: 'invalid-uri'",
    "details": {
      "expected": "viking://<scope>/<path>",
      "received": "invalid-uri"
    }
  },
  "time": 0.001
}
```

**debug/status**
```json
{
  "status": "ok",
  "result": {
    "is_healthy": true,
    "components": {
      "queue": {"name": "queue", "is_healthy": true, "has_errors": false, "details": {...}},
      "vikingdb": {"name": "vikingdb", "is_healthy": true, "has_errors": false, "details": {...}},
      "vlm": {"name": "vlm", "is_healthy": true, "has_errors": false, "details": {...}}
    },
    "errors": []
  },
  "time": 0.05
}
```

**debug/health**
```json
{
  "healthy": true
}
```

### 5.4 错误处理

基于 gRPC 标准状态码,结合 OpenViking 业务场景定制。

#### 通用错误码(基于 gRPC 标准)

| 错误码 | HTTP 状态 | 说明 | 适用场景 |
|--------|-----------|------|----------|
| `OK` | 200 | 成功 | 所有成功操作 |
| `INVALID_ARGUMENT` | 400 | 参数无效 | URI 格式错误、参数缺失、类型错误 |
| `NOT_FOUND` | 404 | 资源不存在 | URI 指向的资源不存在 |
| `ALREADY_EXISTS` | 409 | 资源已存在 | 创建重复资源、重复导入 |
| `PERMISSION_DENIED` | 403 | 权限不足 | API Key 无权限、用户隔离 |
| `UNAUTHENTICATED` | 401 | 未认证 | API Key 缺失或无效 |
| `RESOURCE_EXHAUSTED` | 429 | 资源耗尽 | 配额超限、速率限制 |
| `FAILED_PRECONDITION` | 412 | 前置条件失败 | 资源未就绪、依赖缺失 |
| `ABORTED` | 409 | 操作中止 | 并发冲突、事务失败 |
| `DEADLINE_EXCEEDED` | 504 | 超时 | 处理超时、等待超时 |
| `UNAVAILABLE` | 503 | 服务不可用 | AGFS/VectorDB 不可用 |
| `INTERNAL` | 500 | 内部错误 | 未预期的服务端错误 |
| `UNIMPLEMENTED` | 501 | 未实现 | 功能未实现 |

#### OpenViking 特定错误码

| 错误码 | HTTP 状态 | 说明 | 适用场景 |
|--------|-----------|------|----------|
| `INVALID_URI` | 400 | URI 格式无效 | `viking://` 协议解析失败 |
| `PROCESSING` | 202 | 处理中 | 资源正在处理,尚未就绪 |
| `EMBEDDING_FAILED` | 500 | 向量化失败 | Embedding API 调用失败 |
| `VLM_FAILED` | 500 | VLM 调用失败 | 摘要/概览生成失败 |
| `SESSION_EXPIRED` | 410 | 会话过期 | 会话已被删除或过期 |

#### Python 异常类

参考 Chroma 的特定异常类设计,异常类与错误码一一对应:

```python
# openviking/exceptions.py

class OpenVikingError(Exception):
    """Base exception for all OpenViking errors."""
    def __init__(self, code: str, message: str, details: dict = None):
        self.code = code
        self.message = message
        self.details = details or {}
        super().__init__(f"[{code}] {message}")

# 参数错误
class InvalidArgumentError(OpenVikingError): pass
class InvalidURIError(InvalidArgumentError): pass

# 资源错误
class NotFoundError(OpenVikingError): pass
class AlreadyExistsError(OpenVikingError): pass

# 认证/权限错误
class UnauthenticatedError(OpenVikingError): pass
class PermissionDeniedError(OpenVikingError): pass

# 服务错误
class UnavailableError(OpenVikingError): pass
class InternalError(OpenVikingError): pass
class DeadlineExceededError(OpenVikingError): pass

# 业务错误
class ProcessingError(OpenVikingError): pass
class EmbeddingFailedError(OpenVikingError): pass
class SessionExpiredError(OpenVikingError): pass
```

**错误码到异常的映射**:
```python
ERROR_CODE_TO_EXCEPTION = {
    "INVALID_ARGUMENT": InvalidArgumentError,
    "INVALID_URI": InvalidURIError,
    "NOT_FOUND": NotFoundError,
    "ALREADY_EXISTS": AlreadyExistsError,
    "UNAUTHENTICATED": UnauthenticatedError,
    "PERMISSION_DENIED": PermissionDeniedError,
    "UNAVAILABLE": UnavailableError,
    "INTERNAL": InternalError,
    "DEADLINE_EXCEEDED": DeadlineExceededError,
    "PROCESSING": ProcessingError,
    "EMBEDDING_FAILED": EmbeddingFailedError,
    "SESSION_EXPIRED": SessionExpiredError,
}

def raise_for_error(response: dict):
    """Convert error response to exception."""
    if response.get("status") == "error":
        error = response["error"]
        exc_class = ERROR_CODE_TO_EXCEPTION.get(error["code"], OpenVikingError)
        raise exc_class(error["code"], error["message"], error.get("details", {}))
```

---

## 六、CLI 实现

### 6.1 Bash CLI

#### 模式选型:非交互式 CLI

**选型决策**:采用非交互式 CLI。

**为什么选择非交互式**:

1. **Agent 调用场景**:Agent 通过 subprocess 调用 CLI,非交互式更自然
2. **无状态设计**:每次调用独立,避免状态污染和并发冲突
3. **易于集成**:可以直接在 shell 脚本、CI/CD 中使用
4. **参考业界实践**:kubectl、aws cli、gh cli 都是非交互式设计

#### 多 Agent 场景

OpenViking 支持多 user、多 agent,CLI 需要处理多进程并发场景:

```
┌─────────────────────────────────────────────────────────────┐
│                    OpenViking Server                         │
│                                                              │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐                  │
│  │ user:alice│  │ user:bob │  │ user:carol│                 │
│  │ agent:a1  │  │ agent:b1 │  │ agent:c1  │                 │
│  └──────────┘  └──────────┘  └──────────┘                  │
└─────────────────────────────────────────────────────────────┘
        ▲              ▲              ▲
        │              │              │
   ┌────┴────┐   ┌────┴────┐   ┌────┴────┐
   │ Agent A │   │ Agent B │   │ Agent C │
   │ (进程1) │   │ (进程2) │   │ (进程3) │
   └─────────┘   └─────────┘   └─────────┘
```

多个 Agent 进程可能同时运行,各自有不同的 user/agent 身份。因此 `user`/`agent` 通过环境变量管理(详见 3.4 配置管理)。

#### 使用示例

**Agent 调用场景**:
```bash
# Agent 启动时设置环境变量
export OPENVIKING_URL=http://localhost:1933
export OPENVIKING_API_KEY=sk-xxx
export OPENVIKING_USER=alice
export OPENVIKING_AGENT=agent-a1

# 后续 CLI 调用自动使用环境变量,无需重复指定
openviking find "how to use openviking"
openviking ls viking://resources/
openviking read viking://resources/doc.md
```

**临时覆盖**:
```bash
# 命令行参数覆盖环境变量
openviking --user bob find "query"
```

#### 设计原则

1. **与接口一致**:命令名、参数与接口定义保持一致
2. **体现核心特性**:突出文件系统范式、分层上下文、语义搜索、会话管理
3. **简洁直观**:常用操作简单,复杂操作通过子命令组织

#### 命令列表

```bash
# 服务管理
openviking serve --path <dir> [--port 1933] [--host 0.0.0.0]
openviking serve --port 1933 --agfs-url <url> --vectordb-url <url>
openviking status

# 资源导入
openviking add-resource <path> [--to <uri>] [--wait] [--timeout N]
openviking add-skill <file> [--wait]

# 文件系统操作
openviking ls <uri> [--simple] [--recursive]
openviking tree <uri>
openviking stat <uri>
openviking mkdir <uri>
openviking rm <uri> [--recursive]
openviking mv <from> <to>

# 内容读取
openviking read <uri>
openviking abstract <uri>
openviking overview <uri>

# 搜索
openviking find <query> [<uri>] [--limit N] [--threshold F]
openviking search <query> [<uri>] [--session-id ID] [--limit N]
openviking grep <uri> <pattern> [-i]
openviking glob <pattern> [<uri>]

# 关联管理
openviking link <from> <to>... [--reason TEXT]
openviking unlink <from> <to>
openviking relations <uri>

# 会话管理
openviking session new [--user <name>]
openviking session list
openviking session get <id>
openviking session compress <id>
openviking session extract <id>

# 导入导出
openviking export <uri> <file.ovpack>
openviking import <file.ovpack> <uri> [--force] [--no-vectorize]

# 工具命令
openviking wait [--timeout N]
openviking config show
openviking config init

# 调试命令
openviking status                         # 系统整体状态(包含 queue/vikingdb/vlm 组件状态)
openviking health                         # 快速健康检查
```

#### 命令分组说明

| 命令组 | 体现特性 | 说明 |
|--------|----------|------|
| `add-resource/add-skill` | 自动处理 | 导入后自动解析、分层、向量化 |
| `ls/tree/stat/mkdir/rm/mv` | 文件系统范式 | 像操作文件一样管理上下文 |
| `read/abstract/overview` | 分层上下文 | L0/L1/L2 按需加载 |
| `find/search` | 目录递归检索 | 语义搜索 + 目录定位 |
| `session *` | 会话管理 | 自动压缩、记忆提取 |
| `status/health` | 调试诊断 | 系统状态查询、健康检查 |

#### 实现 (使用 argparse)

```python
# openviking/__main__.py
import argparse
import sys


def main():
    """Main CLI entry point."""
    parser = argparse.ArgumentParser(
        description="OpenViking - An Agent-native context database",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )
    subparsers = parser.add_subparsers(dest="command", help="Available commands")

    # serve command
    serve_parser = subparsers.add_parser("serve", help="Start OpenViking HTTP Server")
    serve_parser.add_argument("--host", type=str, default=None, help="Host to bind to")
    serve_parser.add_argument("--port", type=int, default=None, help="Port to bind to")
    serve_parser.add_argument("--path", type=str, default=None, help="Storage path")
    serve_parser.add_argument("--config", type=str, default=None, help="Config file path")
    serve_parser.add_argument("--api-key", type=str, default=None, help="API key")

    args = parser.parse_args()

    if args.command == "serve":
        from openviking.server.bootstrap import main as serve_main
        serve_main()
    else:
        parser.print_help()
        sys.exit(1)
```

---

### 6.2 Python SDK

#### 使用方式

```python
from openviking import OpenViking

# 嵌入式模式
client = OpenViking(path="./data")

# HTTP 模式
client = OpenViking(url="http://localhost:1933", api_key="xxx")
```

#### 完整示例

```python
from openviking import OpenViking

# 连接
client = OpenViking(url="http://localhost:1933", api_key="xxx")

# 导入资源
result = client.add_resource("./docs/", target="viking://resources/my-docs/", wait=True)
print(f"导入完成: {result.data.uri}, 文件数: {result.data.files_count}")

# 分层读取
abstract = client.abstract("viking://resources/my-docs/")  # L0
overview = client.overview("viking://resources/my-docs/")  # L1
content = client.read("viking://resources/my-docs/README.md")  # L2

# 语义搜索
results = client.find("how to configure", target_uri="viking://resources/my-docs/", limit=10)
for r in results.data.results:
    print(f"{r.uri}: {r.score:.2f}")

# 会话管理(OOP 模式)
session = client.session(user="alice")
session.add_message("user", "What is OpenViking?")
results = client.search("What is OpenViking?", session=session)

# Session 操作
session.compress()
memories = session.extract()

# 获取所有 session
all_sessions = client.sessions()
```

#### 实现方式

```python
class Session:
    """Session 对象,封装会话操作"""
    def __init__(self, client, session_id: str, user: UserIdentifier):
        self._client = client
        self.id = session_id
        self.user = user

    def add_message(self, role: str, content: str):
        """添加消息"""
        ...

    def compress(self):
        """压缩会话"""
        ...

    def extract(self):
        """提取记忆"""
        ...

class OpenViking:
    def __init__(
        self,
        path: Optional[str] = None,
        url: Optional[str] = None,
        api_key: Optional[str] = None,
        user: Optional[UserIdentifier] = None
    ):
        if url:
            self._backend = HTTPBackend(url, api_key)
        else:
            self._backend = LocalBackend(path)
        self._user = user


    def session(self, user: UserIdentifier = None) -> Session:
        """创建或获取 Session 对象"""
        ...

    def sessions(self) -> List[Session]:
        """获取所有 Session 对象"""
        ...
```

### 6.3 使用指南

#### 安装

```bash
pip install openviking
```

#### 环境变量

详见 3.4 配置管理中的环境变量定义。

#### viking:// 目录结构

```
viking://
├── resources/           # 外部资源(文档、代码等)
├── user/
│   └── memories/        # 用户记忆
├── agent/
│   ├── memories/        # Agent 记忆
│   ├── skills/          # Agent 技能
│   └── instructions/    # Agent 指令
└── session/             # 会话数据
```

#### 分层上下文

| 层级 | 方法 | 说明 | 适用场景 |
|------|------|------|----------|
| L0 | `abstract()` | 一句话摘要 | 快速浏览、列表展示 |
| L1 | `overview()` | 核心信息 | 初步了解、决策参考 |
| L2 | `read()` | 完整内容 | 详细阅读、代码执行 |

---

## 七、HTTP API 实现

### 7.1 设计原则

**选型决策**:

1. **RESTful 风格**:资源层级 URL,标准 HTTP 方法
   - 参考 Qdrant API 设计:`/collections/{name}/points`
   - 便于理解和使用,符合开发者习惯

2. **POST 用于复杂查询**:搜索等操作使用 POST,请求体包含查询参数
   - 原因:GET 的 URL 长度有限制,复杂查询参数(如向量、过滤条件)不适合放 URL
   - 参考:Qdrant、Elasticsearch 都采用 POST 进行搜索

3. **统一响应格式**:所有 API 返回 `{status, time, result}` 结构
   - 参考 Qdrant 响应格式
   - 便于客户端统一处理

**为什么不用 GraphQL**:
- OpenViking 的查询模式相对固定,不需要 GraphQL 的灵活性
- RESTful 更简单,学习成本低
- 便于缓存和调试

### 7.2 认证机制

采用 API Key 认证:

```
X-API-Key: your-api-key
# 或
Authorization: Bearer your-api-key
```

**认证策略**:
- `/health` 端点:永远不需要认证(用于负载均衡器健康检查)
- 其他 API 端点:
  - 如果 `config.api_key` 为 `None`(默认)→ 跳过认证(本地开发模式)
  - 如果 `config.api_key` 有值 → 验证请求中的 Key

**配置方式**:
```yaml
# ~/.openviking/server.yaml
server:
  api_key: your-secret-key  # 设置后启用认证,不设置则跳过认证
```

```bash
# 或通过环境变量
export OPENVIKING_API_KEY=your-secret-key
```

### 7.3 API 端点设计

所有 API 响应格式遵循 5.2 统一返回值格式,具体返回值结构见 5.3 各方法返回值。

#### 资源管理 `/api/v1/resources`
```
POST   /api/v1/resources                    # add_resource
       Body: {"path": "...", "target": "...", "wait": false}

POST   /api/v1/skills                       # add_skill
       Body: {"data": {...}}
```

#### 文件系统 `/api/v1/fs`
```
GET    /api/v1/fs/ls?uri=viking://          # ls
GET    /api/v1/fs/tree?uri=viking://        # tree
GET    /api/v1/fs/stat?uri=viking://...     # stat
POST   /api/v1/fs/mkdir                     # mkdir
       Body: {"uri": "viking://..."}

DELETE /api/v1/fs?uri=viking://...&recursive=false  # rm
POST   /api/v1/fs/mv                        # mv
       Body: {"from": "...", "to": "..."}
```

#### 内容读取 `/api/v1/content`
```
GET    /api/v1/content/read?uri=viking://...     # read (L2)
GET    /api/v1/content/abstract?uri=viking://... # abstract (L0)
GET    /api/v1/content/overview?uri=viking://... # overview (L1)
```

#### 搜索 `/api/v1/search`
```
POST   /api/v1/search/find                  # find
       Body: {"query": "...", "uri": "viking://", "limit": 10}

POST   /api/v1/search/search                # search (with session)
       Body: {"query": "...", "uri": "...", "session_id": "..."}

POST   /api/v1/search/grep                  # grep
       Body: {"uri": "...", "pattern": "...", "case_insensitive": false}

POST   /api/v1/search/glob                  # glob
       Body: {"pattern": "**/*.md", "uri": "viking://"}
```

#### 关联 `/api/v1/relations`
```
POST   /api/v1/relations/link               # link
       Body: {"from": "...", "to": "...", "reason": "..."}

DELETE /api/v1/relations/link               # unlink
       Body: {"from": "...", "to": "..."}

GET    /api/v1/relations?uri=viking://...   # relations
```

#### 会话 `/api/v1/sessions`
```
POST   /api/v1/sessions                     # session new
       Body: {"user": "alice"}

GET    /api/v1/sessions                     # session list
GET    /api/v1/sessions/{id}                # session get
DELETE /api/v1/sessions/{id}                # session delete

POST   /api/v1/sessions/{id}/compress       # session compress
POST   /api/v1/sessions/{id}/extract        # session extract
POST   /api/v1/sessions/{id}/messages       # add message
       Body: {"role": "user", "content": "..."}
```

#### 导入导出 `/api/v1/pack`
```
POST   /api/v1/pack/export                  # export
       Body: {"uri": "...", "file": "..."}

POST   /api/v1/pack/import                  # import
       Body: {"file": "...", "uri": "...", "force": false}
```

#### 系统 `/api/v1/system`
```
GET    /health                              # 健康检查
GET    /api/v1/system/status                # 系统状态
POST   /api/v1/system/wait                  # wait_processed
       Body: {"timeout": 60}
```

#### 调试 `/api/v1/debug`
```
GET    /api/v1/debug/status                 # 系统整体状态(包含 queue/vikingdb/vlm 组件状态)
GET    /api/v1/debug/health                 # 快速健康检查(返回 bool)
```

### 7.4 Server 实现

```python
# openviking/server/app.py
from fastapi import FastAPI, Depends
from openviking.server.auth import verify_api_key
from openviking.server.routers import resources, filesystem, content, search, sessions, debug

app = FastAPI(
    title="OpenViking API",
    description="Context Database for AI Agents",
    version="1.0.0"
)

# 注册路由
app.include_router(resources.router, prefix="/api/v1/resources", dependencies=[Depends(verify_api_key)])
app.include_router(filesystem.router, prefix="/api/v1/fs", dependencies=[Depends(verify_api_key)])
app.include_router(content.router, prefix="/api/v1/content", dependencies=[Depends(verify_api_key)])
app.include_router(search.router, prefix="/api/v1/search", dependencies=[Depends(verify_api_key)])
app.include_router(sessions.router, prefix="/api/v1/sessions", dependencies=[Depends(verify_api_key)])
app.include_router(debug.router, prefix="/api/v1/debug", dependencies=[Depends(verify_api_key)])

@app.get("/health")
async def health():
    return {"status": "healthy"}
```

---

## 八、实现任务拆解

### 8.1 任务概览

| 任务 | 描述 | 依赖 | 优先级 | 状态 | 适合社区开发者 |
|------|------|------|--------|------|---------------|
| T1 | Service 层抽取 | - | P0 | Done | |
| T2 | HTTP Server | T1 | P1 | Done | |
| T3 | CLI 基础框架 | T1 | P1 | | |
| T4 | Python SDK | T2 | P2 | Done | |
| T5 | CLI 完整命令 | T3 | P2 | | |
| T6 | 集成测试 | T4, T5 | P3 | | |
| T7 | 文档更新 | T6 | P3 | | |
| T8 | Docker 部署 | T2 | P1 | | ✅ |
| T9 | MCP Server | T1 | P1 | | ✅ |
| T10 | TypeScript SDK | T2 | P2 | | ✅ |
| T11 | Golang SDK | T2 | P2 | | ✅ |

### 8.2 依赖关系

```
T1 (Service层)
    ├── T2 (Server) ──┬── T4 (Python SDK) ──┐
    │                 ├── T8 (Docker)        │
    │                 ├── T10 (TS SDK)       ├── T6 (测试) ── T7 (文档)
    │                 └── T11 (Go SDK)       │
    │                                        │
    ├── T3 (CLI基础) ── T5 (CLI完整) ────────┘
    │
    └── T9 (MCP Server)
```

### 8.3 任务详情

#### T1: Service 层抽取(P0)

**目标**:从 `async_client.py` 抽取业务逻辑到独立的 Service 层

**交付物**:
- `openviking/service/core.py` - OpenVikingService
- `openviking/service/resource_service.py` - 资源导入、技能添加
- `openviking/service/search_service.py` - 语义搜索
- `openviking/service/session_service.py` - 会话管理
- `openviking/service/fs_service.py` - 文件系统操作

**验收标准**:
- 现有单元测试全部通过
- `async_client.py` 作为兼容层,API 不变

---

#### T2: HTTP Server(P1)

**目标**:实现 FastAPI HTTP Server

**交付物**:
- `openviking/server/app.py` - FastAPI 应用
- `openviking/server/bootstrap.py` - 服务启动器
- `openviking/server/auth.py` - API Key 认证
- `openviking/server/routers/*.py` - 所有 API 路由
- `openviking/server/models.py` - 统一响应模型

**验收标准**:
```bash
# 启动服务
openviking serve --path ./data --port 1933

# 验证 API
curl http://localhost:1933/health
curl -X POST http://localhost:1933/api/v1/resources \
  -H "X-API-Key: test" -d '{"path": "./docs"}'
curl http://localhost:1933/api/v1/fs/ls?uri=viking://
```

---

#### T3: CLI 基础框架(P1)

**目标**:实现 CLI 核心命令

**交付物**:
- `openviking/cli/main.py` - CLI 入口
- `openviking/cli/output.py` - 输出格式化
- 核心命令:`serve`, `ls`, `find`, `read`, `abstract`, `overview`, `add-resource`

**验收标准**:
```bash
openviking serve --path ./data --port 1933
openviking add-resource ./docs/ --wait
openviking ls viking://resources/
openviking find "how to use"
```

---

#### T4: Python SDK(P2)

**目标**:支持通过 HTTP 连接远程 Server

**交付物**:
- `openviking/client/http.py` - HTTPClient
- `openviking/client/local.py` - LocalClient(重构)
- 修改 `async_client.py` 支持 `server_url` 参数

**验收标准**:
```python
# HTTP 模式
client = OpenViking(server_url="http://localhost:1933", api_key="test")
client.initialize()
results = client.find("how to use")
```

---

#### T5: CLI 完整命令(P2)

**目标**:补全所有 CLI 命令

**交付物**:
- 会话命令:`session new/list/get/compress/extract`
- 文件系统命令:`tree`, `stat`, `mkdir`, `rm`, `mv`
- 搜索命令:`search`, `grep`, `glob`
- 关联命令:`link`, `unlink`, `relations`
- 导入导出:`export`, `import`
- 配置命令:`config show/init`
- 工具命令:`wait`, `status`

**验收标准**:
```bash
openviking --help  # 显示所有命令
openviking session new --user alice
openviking export viking://resources/docs/ ./backup.ovpack
```

---

#### T6: 集成测试(P3)

**目标**:端到端测试

**交付物**:
- `tests/integration/test_cli.py`
- `tests/integration/test_server.py`
- `tests/integration/test_http_client.py`

**验收标准**:
- 所有集成测试通过
- 覆盖主要使用场景

---

#### T7: 文档更新(P3)

**目标**:更新用户文档

**交付物**:
- README.md 更新(CLI 和 Server 使用说明)
- OpenAPI 文档(自动生成)
- CHANGELOG.md 更新

---

#### T8: Docker 部署(P1)

**目标**:提供 Docker 镜像和 docker-compose 配置

**交付物**:
- `Dockerfile` - 多阶段构建
- `docker-compose.yml` - 本地部署配置
- `.dockerignore` - 忽略文件
- GitHub Actions 自动构建发布

**验收标准**:
```bash
docker build -t openviking .
docker run -p 1933:1933 -e OPENAI_API_KEY=xxx openviking
curl http://localhost:1933/health
```

---

#### T9: MCP Server(P1)

**目标**:实现 Model Context Protocol 服务端,让 Claude 等 AI 可直接调用

**交付物**:
- `openviking/mcp/server.py` - MCP Server 主入口
- `openviking/mcp/tools.py` - Tool 定义(find, read, ls, abstract, overview)
- CLI 命令:`openviking mcp [--path <dir>]`

**验收标准**:
- Claude Desktop 可成功连接并调用 tools
- 支持 stdio 传输

---

#### T10: TypeScript SDK(P2)

**目标**:基于 HTTP API 实现 TypeScript/JavaScript 客户端

**交付物**:
- `openviking-js/` - 独立 npm 包
- 完整类型定义
- 错误处理
- README 和示例

**验收标准**:
```typescript
import { OpenViking } from '@openviking/sdk';
const client = new OpenViking({ url: 'http://localhost:1933', apiKey: 'xxx' });
const results = await client.find('how to configure');
```

---

#### T11: Golang SDK(P2)

**目标**:基于 HTTP API 实现 Golang 客户端

**交付物**:
- `openviking-go/` - 独立 Go 模块
- 完整类型定义
- 错误处理
- README 和示例

**验收标准**:
```go
client := openviking.NewClient(openviking.Config{URL: "http://localhost:1933", APIKey: "xxx"})
results, _ := client.Find("how to configure", nil)
```

### 8.4 关键文件

| 文件 | 操作 | 说明 |
|------|------|------|
| `pyproject.toml` | 修改 | 添加依赖和入口点 |
| `openviking/exceptions.py` | 新增 | 异常类定义 |
| `openviking/cli/main.py` | 新增 | CLI 入口 |
| `openviking/server/app.py` | 新增 | FastAPI 应用入口 |
| `openviking/server/auth.py` | 新增 | API Key 认证 |
| `openviking/server/models.py` | 新增 | 响应模型、错误码定义 |
| `openviking/server/routers/*.py` | 新增 | API 路由 |
| `openviking/client/http.py` | 新增 | HTTP 客户端 |
| `openviking/async_client.py` | 修改 | 支持 HTTP 模式 |

### 8.5 验证方案

#### Bash CLI 验证
```bash
openviking config init
openviking serve --port 1933
openviking add-resource ./docs/ --wait
openviking ls viking://
openviking find "how to use"
```

#### HTTP API 验证
```bash
curl http://localhost:1933/health
curl -X POST http://localhost:1933/api/v1/resources \
  -H "X-API-Key: xxx" -d '{"path": "./docs"}'
curl "http://localhost:1933/api/v1/fs/ls?uri=viking://" \
  -H "X-API-Key: xxx"
```

#### Python CLI 验证
```python
from openviking import OpenViking
client = OpenViking(url="http://localhost:1933", api_key="xxx")
result = client.find("how to use")
print(result)
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.