# 文件系统 OpenViking 提供类 Unix 的文件系统操作来管理上下文。 ## WebDAV(Phase 1) OpenViking Server 也提供了一个面向资源文件的精简 WebDAV 适配层: ```text /webdav/resources ``` Phase 1 有意把范围控制得比较小: - 仅开放 `resources` 命名空间,不暴露 memories、skills、sessions 等其他空间。 - 以文本写入为主,当前 `PUT` 只接受 UTF-8 文本内容。 - 只实现一小部分 WebDAV 方法:`OPTIONS`、`PROPFIND`、`GET`、`HEAD`、`PUT`、`DELETE`、`MKCOL`、`MOVE`。 - 语义侧边文件保持内部可见。`.abstract.md`、`.overview.md`、`.relations.json`、`.path.ovlock` 这些派生文件不会出现在 WebDAV 列表中,也不能被直接访问。 行为说明: - 通过 WebDAV 新建文件时,会对该文件路径触发 OpenViking 的语义生成。 - 通过 WebDAV 覆盖已有文件时,会像 `write()` 一样刷新相关语义和向量。 - 用户自己创建的点目录或点文件仍然可见,只有上面列出的保留内部文件名会被隐藏。 ## API 参考 ### abstract() 读取 L0 摘要(约 100 token 的概要)。 **参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | uri | str | 是 | - | Viking URI(必须是目录) | **Python SDK (Embedded / HTTP)** ```python abstract = client.abstract("viking://resources/docs/") print(f"Abstract: {abstract}") # Output: "Documentation for the project API, covering authentication, endpoints..." ``` **HTTP API** ``` GET /api/v1/content/abstract?uri={uri} ``` ```bash curl -X GET "http://localhost:1933/api/v1/content/abstract?uri=viking://resources/docs/" \ -H "X-API-Key: your-key" ``` **CLI** ```bash openviking abstract viking://resources/docs/ ``` **响应** ```json { "status": "ok", "result": "Documentation for the project API, covering authentication, endpoints...", "time": 0.1 } ``` --- ### overview() 读取 L1 概览,适用于目录。 **参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | uri | str | 是 | - | Viking URI(必须是目录) | **Python SDK (Embedded / HTTP)** ```python overview = client.overview("viking://resources/docs/") print(f"Overview:\n{overview}") ``` **HTTP API** ``` GET /api/v1/content/overview?uri={uri} ``` ```bash curl -X GET "http://localhost:1933/api/v1/content/overview?uri=viking://resources/docs/" \ -H "X-API-Key: your-key" ``` **CLI** ```bash openviking overview viking://resources/docs/ ``` **响应** ```json { "status": "ok", "result": "## docs/\n\nContains API documentation and guides...", "time": 0.1 } ``` --- ### read() 读取 L2 完整内容。 **参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | uri | str | 是 | - | Viking URI | | offset | int | 否 | 0 | 起始行号(0 开始) | | limit | int | 否 | -1 | 读取的行数,`-1` 表示读到结尾 | **说明** - `read()` 只接受文件 URI。传入已存在的目录 URI 时返回 `INVALID_ARGUMENT`(`400`),而不是 `NOT_FOUND`。 - 公开 URI 参数只接受 `resources`、`user`、`agent`、`session` 作用域。`temp`、`queue` 等内部作用域会返回 `INVALID_URI`。 **Python SDK (Embedded / HTTP)** ```python content = client.read("viking://resources/docs/api.md") print(f"Content:\n{content}") ``` **HTTP API** ``` GET /api/v1/content/read?uri={uri} ``` ```bash curl -X GET "http://localhost:1933/api/v1/content/read?uri=viking://resources/docs/api.md" \ -H "X-API-Key: your-key" ``` **CLI** ```bash openviking read viking://resources/docs/api.md ``` **响应** ```json { "status": "ok", "result": "# API Documentation\n\nFull content of the file...", "time": 0.1 } ``` --- ### write() 修改一个已存在的文件,或在 `mode="create"` 时创建新文件,并自动刷新相关语义与向量。 **参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | uri | str | 是 | - | 已存在文件的 URI | | content | str | 是 | - | 要写入的新内容 | | mode | str | 否 | `replace` | `replace`、`append` 或 `create` | | wait | bool | 否 | `false` | 是否等待后台语义/向量刷新完成 | | timeout | float | 否 | `null` | 当 `wait=true` 时的超时时间(秒) | **说明** - `replace` 和 `append` 要求文件已存在;`create` 仅用于创建新文件,目标路径已存在时返回 `409 Conflict`。目录始终会被拒绝。 - `create` 只允许以下文本类扩展名:`.md`、`.txt`、`.json`、`.yaml`、`.yml`、`.toml`、`.py`、`.js`、`.ts`。父目录会自动创建。 - 不允许直接写入派生语义文件:`.abstract.md`、`.overview.md`、`.relations.json`。 - 文件内容会在 API 返回前完成更新;`wait` 只控制是否等待语义/向量刷新完成。 - 公共 API 已不再接受 `regenerate_semantics` 或 `revectorize`;写入后一定会自动刷新相关语义与向量。 **Python SDK (Embedded / HTTP)** ```python result = client.write( "viking://resources/docs/api.md", "# Updated API\n\nFresh content.", mode="replace", wait=True, ) print(result["root_uri"]) ``` **HTTP API** ``` POST /api/v1/content/write ``` ```bash curl -X POST "http://localhost:1933/api/v1/content/write" \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{ "uri": "viking://resources/docs/api.md", "content": "# Updated API\n\nFresh content.", "mode": "replace", "wait": true }' ``` **CLI** ```bash openviking write viking://resources/docs/api.md \ --content "# Updated API\n\nFresh content." \ --wait ``` **响应** ```json { "status": "ok", "result": { "uri": "viking://resources/docs/api.md", "root_uri": "viking://resources/docs", "context_type": "resource", "mode": "replace", "written_bytes": 29, "content_updated": true, "semantic_status": "complete", "vector_status": "complete", "queue_status": { "Semantic": { "processed": 1, "error_count": 0, "errors": [] }, "Embedding": { "processed": 2, "error_count": 0, "errors": [] } } } } ``` --- ### ls() 列出目录内容。 **参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | uri | str | 是 | - | Viking URI | | simple | bool | 否 | False | 仅返回相对路径 | | recursive | bool | 否 | False | 递归列出所有子目录 | | output | str | 否 | `agent` | 输出格式:`agent` 或 `original` | | abs_limit | int | 否 | 256 | `agent` 输出中的摘要长度限制 | | show_all_hidden | bool | 否 | False | 像 `-a` 一样包含隐藏文件 | | node_limit | int | 否 | 1000 | 最大返回节点数 | | limit | int | 否 | None | `node_limit` 的别名 | **条目结构** ```python { "name": "docs", # 文件/目录名称 "size": 4096, # 大小(字节) "mode": 16877, # 文件模式 "modTime": "2024-01-01T00:00:00Z", # ISO 时间戳 "isDir": True, # 如果是目录则为 True "uri": "viking://resources/docs/", # Viking URI "meta": {} # 可选元数据 } ``` **Python SDK (Embedded / HTTP)** ```python entries = client.ls("viking://resources/") for entry in entries: type_str = "dir" if entry['isDir'] else "file" print(f"{entry['name']} - {type_str}") ``` **HTTP API** ``` GET /api/v1/fs/ls?uri={uri}&simple={bool}&recursive={bool} ``` ```bash # 基本列表 curl -X GET "http://localhost:1933/api/v1/fs/ls?uri=viking://resources/" \ -H "X-API-Key: your-key" # 简单路径列表 curl -X GET "http://localhost:1933/api/v1/fs/ls?uri=viking://resources/&simple=true" \ -H "X-API-Key: your-key" # 递归列表 curl -X GET "http://localhost:1933/api/v1/fs/ls?uri=viking://resources/&recursive=true" \ -H "X-API-Key: your-key" ``` **CLI** ```bash openviking ls viking://resources/ [--simple] [--recursive] ``` **响应** ```json { "status": "ok", "result": [ { "name": "docs", "size": 4096, "mode": 16877, "modTime": "2024-01-01T00:00:00Z", "isDir": true, "uri": "viking://resources/docs/" } ], "time": 0.1 } ``` --- ### tree() 获取目录树结构。 **参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | uri | str | 是 | - | Viking URI | | output | str | 否 | `agent` | 输出格式:`agent` 或 `original` | | abs_limit | int | 否 | 256 | `agent` 输出中的摘要长度限制 | | show_all_hidden | bool | 否 | False | 像 `-a` 一样包含隐藏文件 | | node_limit | int | 否 | 1000 | 最大返回节点数 | | limit | int | 否 | None | `node_limit` 的别名 | | level_limit | int | 否 | 3 | 最大目录遍历深度 | **Python SDK (Embedded / HTTP)** ```python entries = client.tree("viking://resources/") for entry in entries: type_str = "dir" if entry['isDir'] else "file" print(f"{entry['rel_path']} - {type_str}") ``` **HTTP API** ``` GET /api/v1/fs/tree?uri={uri} ``` ```bash curl -X GET "http://localhost:1933/api/v1/fs/tree?uri=viking://resources/" \ -H "X-API-Key: your-key" ``` **CLI** ```bash openviking tree viking://resources/my-project/ ``` **响应** ```json { "status": "ok", "result": [ { "name": "docs", "size": 4096, "isDir": true, "rel_path": "docs/", "uri": "viking://resources/docs/" }, { "name": "api.md", "size": 1024, "isDir": false, "rel_path": "docs/api.md", "uri": "viking://resources/docs/api.md" } ], "time": 0.1 } ``` --- ### stat() 获取文件或目录的状态信息。 **参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | uri | str | 是 | - | Viking URI | **Python SDK (Embedded / HTTP)** ```python info = client.stat("viking://resources/docs/api.md") print(f"Size: {info['size']}") print(f"Is directory: {info['isDir']}") ``` **HTTP API** ``` GET /api/v1/fs/stat?uri={uri} ``` ```bash curl -X GET "http://localhost:1933/api/v1/fs/stat?uri=viking://resources/docs/api.md" \ -H "X-API-Key: your-key" ``` **CLI** ```bash openviking stat viking://resources/my-project/docs/api.md ``` **响应** ```json { "status": "ok", "result": { "name": "api.md", "size": 1024, "mode": 33188, "modTime": "2024-01-01T00:00:00Z", "isDir": false, "uri": "viking://resources/docs/api.md" }, "time": 0.1 } ``` --- ### mkdir() 创建目录。 **参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | uri | str | 是 | - | 新目录的 Viking URI | | description | str | 否 | `null` | 目录初始说明。传入后会写入 `.abstract.md`,并进入目录 L0 向量化队列。 | **Python SDK (Embedded / HTTP)** ```python client.mkdir("viking://resources/new-project/") client.mkdir("viking://resources/new-project/", description="接口文档目录") ``` **HTTP API** ``` POST /api/v1/fs/mkdir ``` ```bash curl -X POST http://localhost:1933/api/v1/fs/mkdir \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{ "uri": "viking://resources/new-project/", "description": "接口文档目录" }' ``` **CLI** ```bash openviking mkdir viking://resources/new-project/ openviking mkdir viking://resources/new-project/ --description "接口文档目录" ``` **响应** ```json { "status": "ok", "result": { "uri": "viking://resources/new-project/" }, "time": 0.1 } ``` --- ### rm() 删除文件或目录。 `rm` 是幂等操作:删除一个合法但不存在的 URI 仍会成功。 URI 格式非法、scheme 不支持或使用非公开作用域时返回 `INVALID_URI`。 **参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | uri | str | 是 | - | 要删除的 Viking URI | | recursive | bool | 否 | False | 递归删除目录 | **Python SDK (Embedded / HTTP)** ```python # 删除单个文件 client.rm("viking://resources/docs/old.md") # 递归删除目录 client.rm("viking://resources/old-project/", recursive=True) ``` **HTTP API** ``` DELETE /api/v1/fs?uri={uri}&recursive={bool} ``` ```bash # 删除单个文件 curl -X DELETE "http://localhost:1933/api/v1/fs?uri=viking://resources/docs/old.md" \ -H "X-API-Key: your-key" # 递归删除目录 curl -X DELETE "http://localhost:1933/api/v1/fs?uri=viking://resources/old-project/&recursive=true" \ -H "X-API-Key: your-key" ``` **CLI** ```bash openviking rm viking://resources/old.md [--recursive] ``` **响应** ```json { "status": "ok", "result": { "uri": "viking://resources/docs/old.md" }, "time": 0.1 } ``` --- ### mv() 移动文件或目录。 **参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | from_uri | str | 是 | - | 源 Viking URI | | to_uri | str | 是 | - | 目标 Viking URI | **Python SDK (Embedded / HTTP)** ```python client.mv( "viking://resources/old-name/", "viking://resources/new-name/" ) ``` **HTTP API** ``` POST /api/v1/fs/mv ``` ```bash curl -X POST http://localhost:1933/api/v1/fs/mv \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{ "from_uri": "viking://resources/old-name/", "to_uri": "viking://resources/new-name/" }' ``` **CLI** ```bash openviking mv viking://resources/old-name/ viking://resources/new-name/ ``` **响应** ```json { "status": "ok", "result": { "from": "viking://resources/old-name/", "to": "viking://resources/new-name/" }, "time": 0.1 } ``` --- ### grep() 按模式搜索内容。 **参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | uri | str | 是 | - | 要搜索的 Viking URI | | pattern | str | 是 | - | 搜索模式(正则表达式) | | case_insensitive | bool | 否 | False | 忽略大小写 | | exclude_uri | str | 否 | None | 搜索时要排除的 URI 前缀 | | node_limit | int | 否 | None | 最大搜索节点数 | | level_limit | int | 否 | 5 | 最大目录遍历深度 | **Python SDK (Embedded / HTTP)** ```python results = client.grep( "viking://resources/", "authentication", case_insensitive=True ) print(f"Found {results['count']} matches") for match in results['matches']: print(f" {match['uri']}:{match['line']}") print(f" {match['content']}") ``` **HTTP API** ``` POST /api/v1/search/grep ``` ```bash curl -X POST http://localhost:1933/api/v1/search/grep \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{ "uri": "viking://resources/", "pattern": "authentication", "case_insensitive": true }' ``` **CLI** ```bash openviking grep viking://resources/ "authentication" [--ignore-case] ``` **响应** ```json { "status": "ok", "result": { "matches": [ { "uri": "viking://resources/docs/auth.md", "line": 15, "content": "User authentication is handled by..." } ], "count": 1 }, "time": 0.1 } ``` --- ### glob() 按模式匹配文件。 **参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | pattern | str | 是 | - | Glob 模式(例如 `**/*.md`) | | uri | str | 否 | "viking://" | 起始 URI | | node_limit | int | 否 | None | 最大返回匹配数 | **Python SDK (Embedded / HTTP)** ```python # 查找所有 Markdown 文件 results = client.glob("**/*.md", "viking://resources/") print(f"Found {results['count']} markdown files:") for uri in results['matches']: print(f" {uri}") # 查找所有 Python 文件 results = client.glob("**/*.py", "viking://resources/") print(f"Found {results['count']} Python files") ``` **HTTP API** ``` POST /api/v1/search/glob ``` ```bash curl -X POST http://localhost:1933/api/v1/search/glob \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{ "pattern": "**/*.md", "uri": "viking://resources/" }' ``` **CLI** ```bash openviking glob "**/*.md" [--uri viking://resources/] ``` **响应** ```json { "status": "ok", "result": { "matches": [ "viking://resources/docs/api.md", "viking://resources/docs/guide.md" ], "count": 2 }, "time": 0.1 } ``` --- ### link() 创建资源之间的关联。 **参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | from_uri | str | 是 | - | 源 URI | | to_uris | str 或 List[str] | 是 | - | 目标 URI | | reason | str | 否 | "" | 关联原因 | **Python SDK (Embedded / HTTP)** ```python # 单个关联 client.link( "viking://resources/docs/auth/", "viking://resources/docs/security/", reason="Security best practices for authentication" ) # 多个关联 client.link( "viking://resources/docs/api/", [ "viking://resources/docs/auth/", "viking://resources/docs/errors/" ], reason="Related documentation" ) ``` **HTTP API** ``` POST /api/v1/relations/link ``` ```bash # 单个关联 curl -X POST http://localhost:1933/api/v1/relations/link \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{ "from_uri": "viking://resources/docs/auth/", "to_uris": "viking://resources/docs/security/", "reason": "Security best practices for authentication" }' # 多个关联 curl -X POST http://localhost:1933/api/v1/relations/link \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{ "from_uri": "viking://resources/docs/api/", "to_uris": ["viking://resources/docs/auth/", "viking://resources/docs/errors/"], "reason": "Related documentation" }' ``` **CLI** ```bash openviking link viking://resources/docs/auth/ viking://resources/docs/security/ --reason "Security best practices" ``` **响应** ```json { "status": "ok", "result": { "from": "viking://resources/docs/auth/", "to": "viking://resources/docs/security/" }, "time": 0.1 } ``` --- ### relations() 获取资源的关联关系。 **参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | uri | str | 是 | - | Viking URI | **Python SDK (Embedded / HTTP)** ```python relations = client.relations("viking://resources/docs/auth/") for rel in relations: print(f"Related: {rel['uri']}") print(f" Reason: {rel['reason']}") ``` **HTTP API** ``` GET /api/v1/relations?uri={uri} ``` ```bash curl -X GET "http://localhost:1933/api/v1/relations?uri=viking://resources/docs/auth/" \ -H "X-API-Key: your-key" ``` **CLI** ```bash openviking relations viking://resources/docs/auth/ ``` **响应** ```json { "status": "ok", "result": [ {"uri": "viking://resources/docs/security/", "reason": "Security best practices"}, {"uri": "viking://resources/docs/errors/", "reason": "Error handling"} ], "time": 0.1 } ``` --- ### unlink() 移除关联关系。 **参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | from_uri | str | 是 | - | 源 URI | | to_uri | str | 是 | - | 要取消关联的目标 URI | **Python SDK (Embedded / HTTP)** ```python client.unlink( "viking://resources/docs/auth/", "viking://resources/docs/security/" ) ``` **HTTP API** ``` DELETE /api/v1/relations/link ``` ```bash curl -X DELETE http://localhost:1933/api/v1/relations/link \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{ "from_uri": "viking://resources/docs/auth/", "to_uri": "viking://resources/docs/security/" }' ``` **CLI** ```bash openviking unlink viking://resources/docs/auth/ viking://resources/docs/security/ ``` **响应** ```json { "status": "ok", "result": { "from": "viking://resources/docs/auth/", "to": "viking://resources/docs/security/" }, "time": 0.1 } ``` --- ## 相关文档 - [Viking URI](../concepts/04-viking-uri.md) - URI 规范 - [Context Layers](../concepts/03-context-layers.md) - L0/L1/L2 - [Resources](02-resources.md) - 资源管理