> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zerone.run/llms.txt
> Use this file to discover all available pages before exploring further.

# Files API

> 安全列出和读取 Runtime 工作目录中的文件。

# Files API

Files API 浏览 Runtime 当前工作目录（cwd）中的文件，不是任意主机文件访问接口。它面向运维、调试与控制台展示场景，让外部客户端通过 HTTP 浏览 Agent 的工作区，无需 SSH。API 为只读，不提供上传、写入或删除能力。

<Warning>任何持有有效 API key 的调用方都可以读取 cwd 下的全部内容，包括 `agents.yaml`、`.env`、MCP server 凭证。生产部署前必须配置 `ZERONE_AGENT_HTTP_API_KEY`，并以最小文件权限运行容器，避免把凭据挂载进 Agent 可浏览目录。</Warning>

## 端点一览

| 方法     | 路径                  | 说明                                           |
| ------ | ------------------- | -------------------------------------------- |
| `GET`  | `/v1/files`         | 列出 cwd 下的文件与目录；支持 `path`、`recursive`、`depth` |
| `GET`  | `/v1/files/content` | 单文件流式下载（支持 Range）                            |
| `HEAD` | `/v1/files/content` | 单文件元数据（仅响应头，无 body）                          |

所有端点遵守相同的约束：

* 受 `/v1/*` 的 `x-api-key` 鉴权保护（如已配置）。
* 路径参数 `path` 是相对 cwd 的子路径，禁止 `..` 逃逸、绝对路径和 null byte。
* cwd 内的 symlink 若解析后逃出 cwd，会被拒绝。

## GET /v1/files

### Query 参数

| 参数          | 类型                    | 默认值         | 说明                                                   |
| ----------- | --------------------- | ----------- | ---------------------------------------------------- |
| `path`      | string                | `""`（cwd 根） | 相对 cwd 的子目录路径                                        |
| `recursive` | `"true"` \| `"false"` | `false`     | 是否递归整棵子树                                             |
| `depth`     | number                | 不限          | 限制递归深度（仅 `recursive=true` 时生效）；`depth=N` 表示展开 N 层子目录 |

### 响应（200）

```json theme={null}
{
  "path": "",
  "entries": [
    {
      "name": "agents.yaml",
      "type": "file",
      "size": 482,
      "mtime": "2026-07-07T10:00:00.000Z",
      "mime": "text/yaml"
    },
    {
      "name": "src",
      "type": "directory",
      "size": 0,
      "mtime": "2026-07-07T09:30:00.000Z"
    },
    {
      "name": "outputs-link",
      "type": "symlink",
      "size": 0,
      "mtime": "2026-07-07T09:30:00.000Z",
      "target": "outputs"
    }
  ]
}
```

### Entry 字段

| 字段       | 类型                                                    | 必返回                            | 说明                                 |
| -------- | ----------------------------------------------------- | ------------------------------ | ---------------------------------- |
| `name`   | string                                                | 是                              | 顶层模式为文件名；递归模式为相对 cwd 的路径（用 `/` 分隔） |
| `type`   | `"file"` \| `"directory"` \| `"symlink"` \| `"other"` | 是                              | `other` 用于 FIFO/socket 等非常规类型      |
| `size`   | number                                                | 是                              | 字节数；目录与 broken symlink 为 `0`       |
| `mtime`  | string (ISO 8601)                                     | 是                              | 最后修改时间                             |
| `mime`   | string                                                | 仅 file                         | 由扩展名推断                             |
| `target` | string                                                | 仅 symlink 且 target 解析后仍在 cwd 内 | 链接目标的相对路径                          |

`entries` 数组排序稳定：**directory 优先，再按 name 字典序（区分大小写）**。

### 错误响应

| 状态码   | 触发条件                         | 响应体                                      |
| ----- | ---------------------------- | ---------------------------------------- |
| `400` | 路径非法（绝对路径、`..` 逃逸、null byte） | `{ "error": "Invalid path" }`            |
| `400` | `path` 指向文件而非目录              | `{ "error": "Not a directory" }`         |
| `400` | `depth` 不是非负整数               | `{ "error": "Invalid depth parameter" }` |
| `404` | `path` 不存在                   | `{ "error": "Directory not found" }`     |

### 示例

```bash theme={null}
# 顶层
curl -H "x-api-key: your-runtime-api-key" http://localhost:3000/v1/files

# 子目录
curl -H "x-api-key: your-runtime-api-key" "http://localhost:3000/v1/files?path=src"

# 递归整棵树
curl -H "x-api-key: your-runtime-api-key" "http://localhost:3000/v1/files?recursive=true"

# 限制深度（顶层 + 1 层子目录）
curl -H "x-api-key: your-runtime-api-key" "http://localhost:3000/v1/files?recursive=true&depth=1"
```

## GET /v1/files/content

单文件流式下载，支持 HTTP Range。必填 query 参数 `path` 为相对 cwd 的文件路径。

成功响应（200）的响应头：

```text theme={null}
Content-Type: <由扩展名推断>
Content-Disposition: attachment; filename*=UTF-8''<percent-encoded>
Content-Length: <文件字节数>
Accept-Ranges: bytes
Last-Modified: <RFC 1123 格式>
```

响应不设大小上限——任何大小的文件都会被流式返回。

### Range 请求

支持单段 Range，返回 `206 Partial Content`：

```bash theme={null}
curl -H "x-api-key: your-runtime-api-key" \
     -H "Range: bytes=0-99" \
     "http://localhost:3000/v1/files/content?path=logs/app.log"
```

```text theme={null}
HTTP/1.1 206 Partial Content
Content-Type: text/plain
Content-Length: 100
Content-Range: bytes 0-99/48200
Accept-Ranges: bytes
```

支持的 Range 格式：

| 格式           | 含义            |
| ------------ | ------------- |
| `bytes=0-99` | 第 0 到 99 字节   |
| `bytes=100-` | 第 100 字节到文件末尾 |
| `bytes=-100` | 最后 100 字节     |

多段 Range（如 `bytes=0-99,200-299`）回退为 `200` 全文件返回。

### 错误响应

| 状态码   | 触发条件                            | 响应体                                                                        |
| ----- | ------------------------------- | -------------------------------------------------------------------------- |
| `400` | 路径非法、`path` 指向目录、symlink 逃出 cwd | `{ "error": "Invalid path" }` 或 `{ "error": "Not a file" }`                |
| `404` | 文件不存在                           | `{ "error": "File not found" }`                                            |
| `416` | Range 不可满足（start ≥ size）        | `{ "error": "Range not satisfiable" }`，并携带 `Content-Range: bytes */<size>` |

### 示例

```bash theme={null}
# 全文下载
curl -H "x-api-key: your-runtime-api-key" \
     "http://localhost:3000/v1/files/content?path=outputs/report.json" \
     -o report.json

# Range 下载（前 1KB）
curl -H "x-api-key: your-runtime-api-key" \
     -H "Range: bytes=0-1023" \
     "http://localhost:3000/v1/files/content?path=logs/app.log" \
     -o partial.log
```

## HEAD /v1/files/content

与 `GET` 相同的 query 参数和响应头，但没有响应体。用于下载前预查 `Content-Length` / `Content-Type`，或验证文件是否存在（404 与 200 区分）。

```bash theme={null}
curl -I -H "x-api-key: your-runtime-api-key" \
     "http://localhost:3000/v1/files/content?path=outputs/report.json"
```

```text theme={null}
HTTP/1.1 200 OK
Content-Type: application/json
Content-Disposition: attachment; filename*=UTF-8''report.json
Content-Length: 482
Accept-Ranges: bytes
Last-Modified: Tue, 07 Jul 2026 10:00:00 GMT
```

## 路径安全

所有 `path` 参数都经过统一的 `safeResolve` 检查：

1. **拒绝 null byte**：`path` 含 `\0` 返回 `400`。
2. **拒绝绝对路径**：如 `/etc/passwd` 返回 `400`。
3. **拒绝路径遍历**：如 `../`、`sub/../../` 返回 `400`。
4. **拒绝 symlink 逃逸**：cwd 内的符号链接若解析后指向 cwd 外，下载时返回 `400`；列表时省略 `target` 字段。

这些是底层一致性约束，与是否配置鉴权无关。

## 范围边界

Files API 不提供：

* 文件上传、写入、删除（只读）
* 文件搜索或 glob
* 目录打包（tar/zip）
* 文件变更通知
* 内容脱敏
* 多根目录（cwd 是唯一根）

## 相关

* [Agent 详情 API](/zh/runtime/endpoints/agents)：同类只读接口
