> ## Documentation Index
> Fetch the complete documentation index at: https://test-8ad8522e-feat-ai-sre.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Flashduty Go SDK

> go-flashduty 是 Flashduty 官方开源的 Go SDK，与 Open API 严格 1:1 的类型化封装。

## 概述

***

`go-flashduty` 是 Flashduty 官方开源的 Go 客户端，覆盖 Flashduty Open API 的每一个 REST 接口。它采用与 [go-github](https://github.com/google/go-github) 一致的设计风格——服务分组、类型化请求与响应、可组合传输层——并与 OpenAPI 规范保持严格 1:1：每个方法对应且仅对应一次 HTTP 调用，返回 `(*T, *Response, error)`，不做任何跨接口的隐式聚合或增强。

SDK 的类型化接口由 Flashduty OpenAPI 规范生成，经单元测试覆盖，并针对线上 API 做过端到端验证。

<Note>
  SDK 故意保持"薄"。诸如短 ID 解析、跨接口编排等消费侧逻辑应放在调用方（CLI / MCP）中，而不是塞进 SDK 或滥用某个接口。这样 SDK 始终与 API 一一对应,可预测、可生成、可校验。
</Note>

模块路径为 `github.com/flashcatcloud/go-flashduty`,包名为 `flashduty`,源码遵循 Apache-2.0 协议开源在 [flashcatcloud/go-flashduty](https://github.com/flashcatcloud/go-flashduty)。

<CardGroup cols={2}>
  <Card title="Open API 参考" icon="book" href="/zh/openapi/introduction">
    全部接口的请求参数与响应字段说明。
  </Card>

  <Card title="命令行工具" icon="code" href="/zh/developer/cli">
    在终端中直接操作 Flashduty 的 CLI。
  </Card>
</CardGroup>

## 安装

***

<Steps>
  <Step title="要求 Go 1.24+">
    请确认本地 Go 工具链版本不低于 1.24。
  </Step>

  <Step title="获取依赖">
    ```bash theme={null}
    go get github.com/flashcatcloud/go-flashduty
    ```
  </Step>

  <Step title="导入包">
    ```go theme={null}
    import flashduty "github.com/flashcatcloud/go-flashduty"
    ```
  </Step>
</Steps>

## 快速开始

***

以下是一个最小可运行示例：构造客户端、列出处于"已触发"状态的故障，并处理返回的三元组 `(数据, *Response, error)`。

```go theme={null}
package main

import (
	"context"
	"fmt"
	"log"

	flashduty "github.com/flashcatcloud/go-flashduty"
)

func main() {
	client, err := flashduty.NewClient("YOUR_APP_KEY")
	if err != nil {
		log.Fatal(err)
	}

	list, resp, err := client.Incidents.List(context.Background(), &flashduty.ListIncidentsRequest{
		Progress:    "Triggered",
		ListOptions: flashduty.ListOptions{Limit: 20},
	})
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("request_id=%s total=%d has_next=%t\n", resp.RequestID, resp.Total, resp.HasNextPage)
	for _, inc := range list.Items {
		fmt.Printf("[%s] %s\n", inc.IncidentSeverity, inc.Title)
	}
}
```

每次调用都返回三个值：

| 返回值         | 类型                    | 说明                                                   |
| ----------- | --------------------- | ---------------------------------------------------- |
| 数据          | `*T`                  | 接口对应的类型化响应体（如 `*ListIncidentsResponse`）；调用失败时为 `nil` |
| `*Response` | `*flashduty.Response` | 包裹 `*http.Response`,并附带 `RequestID`、分页等信封元信息         |
| `error`     | `error`               | 失败时为 `*ErrorResponse`,429 时为 `*RateLimitError`       |

<Tip>
  `app_key` 用于鉴权,SDK 会自动将其作为查询参数注入每个请求。请在 Flashduty 控制台的"推送集成"或团队配置中获取对应的 `app_key`。
</Tip>

## 创建客户端

***

`NewClient` 接收 `app_key` 与零到多个 `Option`。`app_key` 为空会直接返回错误。默认 Base URL 为 `https://api.flashcat.cloud`,默认 HTTP 超时为 30 秒,默认 User-Agent 为 `go-flashduty`。

```go theme={null}
client, err := flashduty.NewClient("YOUR_APP_KEY",
	flashduty.WithBaseURL("https://api.flashcat.cloud"),
	flashduty.WithTimeout(10*time.Second),
	flashduty.WithUserAgent("my-app/1.0"),
	flashduty.WithHTTPClient(customHTTPClient),
	flashduty.WithTransport(customRoundTripper),
	flashduty.WithLogger(myLogger),
	flashduty.WithRequestHeaders(staticHeaders),
	flashduty.WithRequestHook(func(req *http.Request) { /* 例如注入 traceparent */ }),
)
```

| Option                                      | 说明                                                                                    |
| ------------------------------------------- | ------------------------------------------------------------------------------------- |
| `WithBaseURL(raw string)`                   | 覆盖 API 基础地址（默认 `https://api.flashcat.cloud`）。私有化部署用它指向自有网关；非法 URL 会在 `NewClient` 阶段报错 |
| `WithTimeout(d time.Duration)`              | 设置底层 HTTP 客户端的整体超时                                                                    |
| `WithUserAgent(ua string)`                  | 设置每个请求携带的 `User-Agent` 头                                                              |
| `WithHTTPClient(hc *http.Client)`           | 替换底层 `*http.Client`;传入 `nil` 时忽略                                                      |
| `WithTransport(rt http.RoundTripper)`       | 设置自定义 `http.RoundTripper`,是接入重试、缓存、链路追踪、限流等中间件的惯用切入点;传入 `nil` 时忽略                     |
| `WithLogger(l Logger)`                      | 设置自定义日志器;传入 `nil` 时忽略                                                                 |
| `WithRequestHeaders(h http.Header)`         | 设置追加到每个请求的静态头,在 SDK 自身的头（`Content-Type`、`Accept`、`User-Agent`）之后应用                    |
| `WithRequestHook(hook func(*http.Request))` | 注册回调,在每个请求发出前调用,用于注入逐请求的头（如 W3C `traceparent`）                                        |

<Info>
  **私有化部署**：用 `WithBaseURL` 将客户端指向您自有的 Flashduty 网关地址即可,其余调用方式完全不变。
</Info>

## 服务与方法

***

接口按服务分组挂在客户端上：调用约定统一为 `client.<Service>.<Method>(ctx, req)`,返回 `(*T, *Response, error)`。例如 `client.Incidents.List(ctx, req)`、`client.Sessions.Info(ctx, req)`。

| 服务字段                              | 说明                   |
| --------------------------------- | -------------------- |
| `client.Incidents`                | 故障                   |
| `client.Alerts`                   | 告警                   |
| `client.Channels`                 | 协作空间                 |
| `client.Schedules`                | 排班                   |
| `client.Licenses`                 | On-call 许可证          |
| `client.Calendars`                | 日历                   |
| `client.StatusPages`              | 状态页                  |
| `client.Members`                  | 成员                   |
| `client.Teams`                    | 团队                   |
| `client.RolesPermissions`         | 角色与权限                |
| `client.Account`                  | 账户                   |
| `client.AuditLogs`                | 审计日志                 |
| `client.AlertRules`               | 告警规则                 |
| `client.AlertEnrichment`          | 告警字段加工               |
| `client.DataSources`              | 数据源                  |
| `client.Integrations`             | 集成                   |
| `client.ImIntegrations`           | IM 集成                |
| `client.NotificationTemplates`    | 通知模板                 |
| `client.Changes`                  | 变更                   |
| `client.Diagnostics`              | 诊断                   |
| `client.Analytics`                | 分析                   |
| `client.A2aAgents`                | A2A Agents           |
| `client.Artifacts`                | AI SRE 产物            |
| `client.Automations`              | AI SRE 自动化           |
| `client.Knowledge`                | AI SRE 知识库（知识包与知识文件） |
| `client.McpServers`               | MCP Servers          |
| `client.Sessions`                 | AI SRE 会话            |
| `client.Skills`                   | Skills               |
| `client.Applications`             | RUM 应用               |
| `client.DataQuery`                | RUM 数据查询             |
| `client.ErrorIngestionRules`      | RUM 错误采集规则           |
| `client.Facets`                   | RUM 字段与维度            |
| `client.IssuePresetSeverityRules` | RUM Issue 预设严重性规则    |
| `client.Issues`                   | RUM 问题               |
| `client.Resources`                | RUM 资源               |
| `client.SessionReplay`            | RUM 会话回放             |
| `client.Sourcemaps`               | RUM Sourcemap        |

`client.StatusPages.DraftCreate`（`POST /status-page/draft/create`）把一次状态页事件草稿存下来，供人工在控制台审阅后发布，不会直接对外可见：`draft` 为任意 JSON，按原文存储、序列化后不超过 64 KB，其中 `page_id`、`type`（`incident` 或 `maintenance`）、`name`、`message` 会被校验；`change_id`（> 0 时表示追加到已有事件的一次更新）、`status`、`affected_components` 可选，新建 maintenance 时可用 `start_time` / `end_time`（Unix 秒）指定窗口。请求上的 `source` 是草稿来源标记（≤ 64 字符，如 `ai_sre:sess_xxx`）；响应返回 `draft_id`（匹配 `draft_[A-Za-z0-9]{22}`），控制台的审阅链接即携带它。

`client.Knowledge` 对应 `/safari/knowledge/*` 的 9 个 API 操作：知识包侧为 `PackReadGet`（获取账户知识包）、`PackReadList`（列出知识包）、`PackWriteEnsure`（确保知识包存在）、`PackWriteUpdate`（变更知识包作用域）、`PackWriteDelete`（删除知识包）；知识文件侧为 `FileReadGet`、`FileReadList`、`FileWritePut`（上传/覆盖）、`FileWriteDelete`。相关导出类型包括 `KnowledgePackItem`、`KnowledgeFileItem`、`KnowledgeWarning` 以及各 `Knowledge*Request` / `Knowledge*Response`。

`client.Artifacts`（AI SRE 产物）对应 `/safari/artifact/*` 的 11 个 API 操作：画廊读取侧 `ReadGet`（按 ID 获取单个已发布产物）、`ReadList`（分页列出调用方可见的产物，支持标题子串搜索、`scope`（`all` / `personal` / `team`）与 `team_ids` 过滤）、`ReadGetFileState`（批量探测会话展示文件（`pf_` 前缀）是否已有上线产物，单次至多 50 个 ID）；文件侧 `ReadSign`（为展示文件签发短期有效的下载/预览 URL，有效期 5 分钟，`expires_in` 固定 300 秒）与 `ReadStream`（凭签名 token 下载或预览文件，成功响应体是文件而非 JSON 信封，原始字节放在 `Response.Raw`）；写入侧 `WritePublish`（把会话产生的文件发布为画廊产物）、`WriteUpdate`（重命名或转移个人/团队作用域）、`WriteDelete`（从画廊移除，源文件仍保留在会话中）；公开分享 `WriteShareEnable`（开启匿名公开分享并返回公开链接，任何人凭链接即可查看、无需登录）、`WriteShareRevoke`（关闭分享，链接立即失效）、`WriteShareSync`（把公开快照刷新为最新内容——当 `share_enabled` 为 true 且 `share_file_id` 与 `file_id` 不一致时表示快照已过期，调用它刷新）。相关导出类型包括 `PublishedArtifactItem`、`ArtifactShareState`、`SignedUrLs` 以及各 `Artifact*Request` / `Artifact*Response`。

`client.Diagnostics.QueryData` 通过 `POST /monit/query/data` 执行同步查询，返回稳定的 `query_result.v1` 结构化结果（`result.kind` 为 `frames` / `records` / `samples` 之一），要求 monit-edge v0.65.0 及以上版本。日志模式和指标趋势分析统一使用 `client.DataSources.ToolsInvoke`，工具名称为 `prometheus.metric_trends`、`loki.log_patterns` 或 `victorialogs.log_patterns`。

`client.DataSources.ToolsInvoke`（`POST /monit/datasource/tools/invoke`，`monit-datasource-tools-invoke`）在某个已配置数据源上执行一个确定性工具：`tool` 名称由数据源类型前缀修饰（如 `mysql.overview`），`params` 为工具专属 JSON 参数（省略视为 `{}`，显式 `null` 非法）；除诊断工具外，入口支持 `<type>.query` 查询工具（`prometheus`、`mysql`、`postgres`、`oracle`、`clickhouse`、`elasticsearch`、`loki`、`victorialogs`、`sls`、`tencent_cls`），`/monit/query/data` 入口保持不变。该接口要求集群中所有在线可路由的 Edge 会话都支持 v0.71.0 基础调用协议（单个工具可能要求更新的实现），无工具目录、无自动重放、也不会回退到旧版 diagnose。请求体上限 128 KiB，完整成功响应上限 10 MiB，单工具超时至多 25 秒；响应为 `DatasourceToolResult`（`data` 为工具专属 JSON、永不为 null，`summary` 可选，出现 `truncated` 时其 `reason` 说明截断原因）。

`client.DataSources` 的 `payload` 按 `type_ident` 选择类型专属配置块。当前允许的 `type_ident` 共 15 种：`prometheus`、`loki`、`mysql`、`oracle`、`postgres`、`clickhouse`、`elasticsearch`、`sls`、`tencent_cls`、`victorialogs`，以及新增的诊断专用类型 `redis_node`、`redis_sentinel`、`mongodb_mongod`、`mongodb_mongos`、`kafka`——诊断专用类型的 `alerting_enabled` 恒为 false（不阻止非告警查询与工具调用），且拒绝传 true。连接地址规则：Redis/MongoDB 诊断类型为单个 `host:port`（IPv6 需加方括号），不接受 URI、userinfo 或 query；`kafka` 为 1–32 个以逗号分隔、互不重复的 `host:port` bootstrap 地址（规范化后至多 4096 字符，`payload` 中不再有 broker 列表）；`mongodb_mongod` / `mongodb_mongos` 的配置块中 `auth_source` 默认为 `admin`，用户名与密码必须成对配置，不支持客户端证书；Redis 节点配置的 `database` 默认为 0。诊断类型的 `password` 与 Kafka 的 `tls_key` 等敏感字段支持 `${env:NAME}` 引用：响应中字面值会被省略（仅当存储值本身就是 `${env:...}` 引用时才回显），更新时省略这些字段即保留原值，显式传空字符串则清除。

`enabled` 与 `alerting_enabled` 相互独立：`enabled`（业务执行开关）创建时默认 true，`alerting_enabled`（是否允许参与告警评估；告警还要求 `enabled` 为 true 且类型支持告警）创建时对告警类型默认 true、对诊断专用类型默认 false；二者更新时省略均保留当前值，显式传 `null` 非法；当有启用的告警规则引用该数据源时，将其 `enabled` 置为 false 会以 conflict 拒绝。另外 `/monit/datasource/list` 响应中 `payload` 恒为 `null`（列表查询不读 payload 列），create/update/info 响应中才会填充。

<Note>
  所有标识符、服务字段名与方法名均与生成代码保持一致。具体每个服务有哪些方法、请求与响应类型,请以 `services_gen.go` 与各服务文件,以及 [Open API 参考](/zh/openapi/introduction) 为准。
</Note>

## 响应时间戳

***

响应中的时间字段不再是裸整数,而是自描述的 `Timestamp`（Unix 秒）或 `TimestampMilli`（毫秒）类型。它们序列化为本地时区的 RFC3339 字符串,因此 JSON、日志以及面向 LLM 的输出都直接可读;原始 epoch 仍只需一次方法调用即可取到。

* **序列化（出站）**：非零值序列化为带引号的 RFC3339 字符串（`TimestampMilli` 用 RFC3339Nano 以保留毫秒精度）。零值序列化为裸整数 `0`——一个"未设置"哨兵,而非 1970 年的日期,并被 `json:",omitempty"` 丢弃。
* **反序列化（入站）**：既兼容数字 epoch（线上原始形态),也兼容 RFC3339 字符串(使序列化后的值可无损往返),还接受 `null`（→ 0）。

```go theme={null}
inc := list.Items[0]

fmt.Println(inc.StartTime)            // 2026-05-30T14:37:11+08:00  （String / fmt / TOON）
b, _ := json.Marshal(inc.StartTime)   // "2026-05-30T14:37:11+08:00"
epoch := inc.StartTime.Unix()         // 1779514631  （原始 wire 值）
t := inc.StartTime.Time()             // time.Time
zero := inc.StartTime.IsZero()        // 是否为未设置哨兵
```

| 方法          | 返回          | 说明                                              |
| ----------- | ----------- | ----------------------------------------------- |
| `.Time()`   | `time.Time` | 取为标准时间值                                         |
| `.Unix()`   | `int64`     | 取原始 wire 值（`Timestamp` 为秒,`TimestampMilli` 为毫秒） |
| `.IsZero()` | `bool`      | 是否为未设置哨兵（0）                                     |
| `.String()` | `string`    | 本地时区 RFC3339,未设置时为 `"0"`                        |

<Warning>
  **请求侧时间字段仍为 `int64`**,API 在 wire 上要求数字 epoch。注意:多数接口取**秒**,但 RUM 与 webhook 历史相关接口取**毫秒**。
</Warning>

## 分页

***

所有列表接口共享 `ListOptions`,将其内嵌在请求结构体中即可。零值会被省略,不会覆盖服务端默认值（后端默认 `p=1`、`limit=20`）。

| 字段               | 类型       | wire 字段            | 说明                          |
| ---------------- | -------- | ------------------ | --------------------------- |
| `Page`           | `int`    | `p`                | 从 1 开始的页码                   |
| `Limit`          | `int`    | `limit`            | 每页返回条数上限                    |
| `SearchAfterCtx` | `string` | `search_after_ctx` | 上一页回显的不透明游标,用于深分页;回传它即可取下一页 |

响应侧,`*Response` 携带 `Total`、`HasNextPage` 与 `SearchAfterCtx`。推荐用 search-after 游标逐页遍历：

```go theme={null}
req := &flashduty.ListIncidentsRequest{
	ListOptions: flashduty.ListOptions{Limit: 50},
}

// 设上限,避免游标异常时无限循环。
for page := 0; page < 100; page++ {
	list, resp, err := client.Incidents.List(ctx, req)
	if err != nil {
		log.Fatal(err)
	}

	for _, inc := range list.Items {
		fmt.Printf("%s: %s\n", inc.IncidentID, inc.Title)
	}

	if !resp.HasNextPage {
		break
	}
	// 推进游标,取下一页。
	req.ListOptions.SearchAfterCtx = list.SearchAfterCtx
}
```

## 错误处理

***

Flashduty API 返回的未成功调用——无论是信封中携带了错误,还是 HTTP 状态非 2xx——都会返回 `*ErrorResponse`。它带有 `Code`、`Message`、可选的 `Reason` 与 `RequestID` 字段,排障时把 `RequestID` 提供给支持团队即可定位。`Reason` 携带服务端给出的可选原因（信封内的 `DutyError` 同样带有该字段，JSON 字段为 `reason`,omitempty）；非空时它也会被追加到错误字符串末尾,形如 `, reason X`。

当 API 返回 429 时,错误被提升为 `*RateLimitError`：它内嵌 `*ErrorResponse`（所以 `errors.As` 取 `*ErrorResponse` 仍然成立),并额外带上 `RetryAfter` 提示。

<Note>
  如果你收到的是带非 JSON 响应体的非 2xx 响应,SDK 会返回普通 `error`,而不是 `*ErrorResponse`。这表示响应来自网关、负载均衡器或代理等中间层,通常是请求超过了中间层超时。你可以重试请求,或将耗时较长的批量请求拆分为更小的批次；不要假定 `errors.As(err, &apiErr)` 能匹配此类错误。
</Note>

```go theme={null}
_, _, err := client.Incidents.Info(ctx, &flashduty.IncidentInfoRequest{
	IncidentID: "does-not-exist",
})

var rl *flashduty.RateLimitError
if errors.As(err, &rl) {
	// 按服务端要求退避后再重试。
	time.Sleep(rl.RetryAfter)
	return
}

var apiErr *flashduty.ErrorResponse
if errors.As(err, &apiErr) {
	fmt.Printf("api error code=%s request_id=%s\n", apiErr.Code, apiErr.RequestID)
	return
}
```

类型化判定函数能省去字符串比较,并能穿透被包裹的错误（内部用 `errors.As`）：

| 辅助函数                      | 说明                                                                         |
| ------------------------- | -------------------------------------------------------------------------- |
| `IsNotFound(err)`         | 是否为资源不存在                                                                   |
| `IsRateLimited(err)`      | 是否为请求过于频繁（429）                                                             |
| `IsUnauthorized(err)`     | 是否为未授权                                                                     |
| `IsAccessDenied(err)`     | 是否为访问被拒                                                                    |
| `IsInvalidParameter(err)` | 是否为参数非法                                                                    |
| `ErrorCodeOf(err)`        | 提取错误码,返回 `ErrorCode` 常量(如 `ErrorCodeAccessDenied`、`ErrorCodeUnauthorized`) |

```go theme={null}
switch flashduty.ErrorCodeOf(err) {
case flashduty.ErrorCodeAccessDenied, flashduty.ErrorCodeUnauthorized:
	// 处理鉴权失败
}
```

## 重试

***

核心客户端**不内置**自动重试。请通过传输层组合可选的 `retry` 子包——一个安全默认的重试型 `http.RoundTripper`。

`github.com/flashcatcloud/go-flashduty/retry` 的特性：

* **重试条件**：HTTP 429、任意 5xx（状态码 ≥ 500),以及传输错误。其他 4xx 与所有 2xx/3xx 立即返回。
* **退避策略**：确定性指数退避（`MinWait * 2^attempt`,每次上限为 `MaxWait`);无随机抖动。存在合法的整数 `Retry-After` 头时,以其为准（同样不超过 `MaxWait`）。
* **安全回放**：仅当请求体可回放（`req.Body` 为 nil 或 `req.GetBody` 非空）时才重试,每次重试都在请求的克隆上重建请求体,绝不修改调用方的原始 `*http.Request`。SDK 构造的所有请求都设置了 `GetBody`,因此 POST 请求体都可安全回放。
* **尊重取消**：等待退避期间若请求 context 被取消,立即返回 context 错误。

```go theme={null}
import "github.com/flashcatcloud/go-flashduty/retry"

client, err := flashduty.NewClient("YOUR_APP_KEY",
	flashduty.WithTransport(retry.New(
		retry.WithMaxRetries(3),
	)),
)
```

| 配置项                                      | 默认值                     | 说明                     |
| ---------------------------------------- | ----------------------- | ---------------------- |
| `retry.WithMaxRetries(n int)`            | `3`                     | 首次尝试之后的最大重试次数;负数表示禁用重试 |
| `retry.WithMinWait(d time.Duration)`     | `500ms`                 | 基础退避时长（首次重试前的等待）       |
| `retry.WithMaxWait(d time.Duration)`     | `30s`                   | 单次退避等待的上限              |
| `retry.WithBase(base http.RoundTripper)` | `http.DefaultTransport` | 底层实际执行请求的 RoundTripper |

<Tip>
  `retry` 子包是纯 `net/http` 实现,刻意不导入父级 `flashduty` 包,因此永远不会引入循环依赖。`retry.New()` 与 `&retry.Transport{}`（零值）都开箱即用。
</Tip>

## 流式导出

***

`client.Sessions.Export` 用于导出一个 AI SRE 会话的完整事件转录,返回的是 `io.ReadCloser`（NDJSON 流,`application/x-ndjson`),而非 JSON 信封。首行始终是一条 `session_meta` 信封,其后每行是一个会话事件;当 `req.IncludeSubagents` 为 true 时,每条 `subagent_dispatch` 行后会跟随子会话自身的完整事件流。

由于响应体可能很大,应当逐行读取并直接写入文件,**不要**把整段转录缓冲进内存。返回的 `io.ReadCloser` 是活动 HTTP 响应体,由调用方持有并**必须** `Close`(`defer` 关闭即正确)。配合 `NewExportScanner` 可按行扫描,`DecodeExportLine` 可将一行解码为 `ExportLine`：

```go theme={null}
rc, _, err := client.Sessions.Export(ctx, &flashduty.SessionExportRequest{
	SessionID:        "your-session-id",
	IncludeSubagents: true,
})
if err != nil {
	return err
}
defer rc.Close()

sc := flashduty.NewExportScanner(rc)
for sc.Scan() {
	line, err := flashduty.DecodeExportLine(sc.Bytes())
	if err != nil {
		return err
	}
	// 用 line.Type 区分：session_meta、user_message、llm_call、
	// tool_call、subagent_dispatch、final_answer、agent_text、error
	_ = line
	// 也可以把 sc.Bytes() 原样写入文件。
}
return sc.Err()
```

<Note>
  `NewExportScanner` 配置的单行缓冲区足以容纳转录中较宽的事件行（如 tool 输出、LLM 调用),不受默认 64KB token 上限限制。任何非 2xx 状态下,响应体仍是常规 JSON 错误信封——`Export` 会读取并关闭它,返回类型化错误（`*ErrorResponse`,429 时为 `*RateLimitError`),此时 `io.ReadCloser` 为 `nil`,与其他生成接口行为一致。
</Note>
