# BT AI 官方知识接口

## 功能

BT AI 官方知识接口向开发工具提供可校验、可缓存的 BT 官方知识。客户端可以先读取知识清单，再按任务需要下载单个模块；首次安装或离线更新也可以下载指定版本的完整包。

接口只返回公开知识，不接收用户问题、项目源码、模型配置或 API Key。所有地址都使用独立的 `/ai/` 前缀。

## 语法

```text
GET https://btlang.org/ai/manifest
GET https://btlang.org/ai/knowledge/{module_id}
GET https://btlang.org/ai/bundle/{knowledge_version}
```

## 参数

### 路径参数

| 字段 | 类型 | 必填 | 默认值 | 有效范围或可选值 | 含义 |
| ------ | ------ | ------ | ------ | ------ | ------ |
| `module_id` | String | 模块接口是 | 无 | 清单 `modules[].id` 中的稳定 ID | 要获取的知识模块。 |
| `knowledge_version` | String | 完整包接口是 | 无 | 清单的 `knowledge_version` | 要获取的完整离线包版本。 |

### 条件请求头

| 字段 | 类型 | 必填 | 默认值 | 有效范围或可选值 | 含义 |
| ------ | ------ | ------ | ------ | ------ | ------ |
| `If-None-Match` | String | 否 | 无 | 上次响应的 `ETag`，支持弱标签和逗号分隔列表 | 内容未变化时返回 `304 Not Modified`。 |
| `If-Modified-Since` | String | 否 | 无 | 上次响应的 `Last-Modified` | 未同时发送 `If-None-Match` 且发布时间一致时返回 `304 Not Modified`。 |

## 返回值

### 知识清单

`GET /ai/manifest` 返回 UTF-8 JSON：

| 字段 | 类型 | 必填 | 默认值 | 有效范围或可选值 | 含义 |
| ------ | ------ | ------ | ------ | ------ | ------ |
| `schema_version` | Int | 是 | 无 | 当前为 `1` | 清单结构版本。 |
| `bt_version` | String | 是 | 无 | 三段式版本 | 知识对应的 BT 版本。 |
| `knowledge_version` | String | 是 | 无 | `YYYY.MM.DD.revision` | 本次知识发布的唯一版本。 |
| `updated_at` | String | 是 | 无 | ISO 8601 | 知识发布时间。 |
| `last_modified` | String | 是 | 无 | RFC 7231 HTTP 日期 | 条件请求使用的最后修改时间。 |
| `min_client_version` | String | 是 | 无 | 三段式版本 | 能读取当前 schema 的最低客户端版本。 |
| `source_sha256` | String | 是 | 无 | 64 位小写十六进制 | 单一知识源规范化后的 SHA-256。 |
| `bundle_format` | String | 是 | 无 | `bt-ai-bundle-json-v1` | 完整包格式。 |
| `bundle_url` | String | 是 | 无 | `/ai/bundle/{knowledge_version}` | 完整包地址。 |
| `bundle_sha256` | String | 是 | 无 | 64 位小写十六进制 | 完整包原始 UTF-8 字节的 SHA-256。 |
| `modules` | Array[Object] | 是 | 无 | 固定模块清单 | 可按需获取的模块元数据。 |

`modules[]` 字段：

| 字段 | 类型 | 必填 | 默认值 | 有效范围或可选值 | 含义 |
| ------ | ------ | ------ | ------ | ------ | ------ |
| `id` | String | 是 | 无 | 稳定模块 ID | 模块唯一标识。 |
| `revision` | Int | 是 | 无 | 大于等于 `1` | 模块正文修订号。 |
| `content_url` | String | 是 | 无 | `/ai/knowledge/{id}` | 模块正文地址。 |
| `sha256` | String | 是 | 无 | 64 位小写十六进制 | 模块原始 UTF-8 字节的 SHA-256。 |
| `approx_tokens` | Int | 是 | 无 | 大于 `0` | 模块的近似 Token 数，用于上下文预算。 |
| `runtimes` | Array[String] | 是 | 无 | `cli/web/desktop/extension/ffi` | 模块适用运行时。 |
| `tags` | Array[String] | 是 | 无 | 稳定检索标签 | 模块选择和本地检索标签。 |
| `depends_on` | Array[String] | 是 | `[]` | 其他模块 ID | 使用本模块前应同时加载的依赖模块。 |
| `block_count` | Int | 是 | 无 | 大于 `0` | 模块中的稳定检索块数量。 |

### 单个模块

`GET /ai/knowledge/{module_id}` 返回 UTF-8 Markdown。每个标题前有稳定块标记：

```markdown
<!-- bt-ai:block id="desktop-development/section-7-2" tags="desktop,bt_app,app.json,window.bt,bundle" -->
### 7.2 app.json 字段
```

客户端应以清单中的 `sha256` 校验收到的原始 UTF-8 字节，不要在校验前改变换行、编码或尾部换行。

### 完整离线包

`GET /ai/bundle/{knowledge_version}` 返回 `bt-ai-bundle-json-v1` JSON：

| 字段 | 类型 | 必填 | 默认值 | 有效范围或可选值 | 含义 |
| ------ | ------ | ------ | ------ | ------ | ------ |
| `schema_version` | Int | 是 | 无 | 当前为 `1` | 完整包结构版本。 |
| `bundle_format` | String | 是 | 无 | `bt-ai-bundle-json-v1` | 完整包格式。 |
| `knowledge_version` | String | 是 | 无 | 与请求版本一致 | 包内知识版本。 |
| `manifest` | Object | 是 | 无 | 清单快照 | 包内清单；为避免自引用哈希，`bundle_sha256` 固定为 `null`，外部清单的值才是包校验值。 |
| `block_index` | Object | 是 | 无 | schema 1 | 全部稳定块的模块、行号、标签、Token 估算和 SHA-256 索引。 |
| `modules` | Object[String,String] | 是 | 无 | 键为模块 ID | 9 个模块的完整 Markdown 正文。 |

### 响应头

| 字段 | 类型 | 必填 | 默认值 | 有效范围或可选值 | 含义 |
| ------ | ------ | ------ | ------ | ------ | ------ |
| `Content-Type` | String | 是 | 无 | JSON 或 `text/markdown; charset=utf-8` | 响应格式。 |
| `Cache-Control` | String | 是 | 无 | 清单/模块 5 分钟校验；版本包一年且 immutable | 客户端缓存策略。 |
| `ETag` | String | 是 | 无 | HTTP 实体标签 | `If-None-Match` 条件请求值。 |
| `Last-Modified` | String | 是 | 无 | RFC 7231 HTTP 日期 | `If-Modified-Since` 条件请求值。 |
| `X-BT-Knowledge-Version` | String | 是 | 无 | 当前知识版本 | 响应所属知识版本。 |
| `X-Content-SHA256` | String | 模块和完整包是 | 无 | 64 位小写十六进制 | 当前响应正文的 SHA-256。 |
| `Access-Control-Allow-Origin` | String | 是 | 无 | `*` | 允许公开知识客户端跨域读取。 |

## 代码示例

下面的 BT 脚本按需获取核心契约模块，并用清单中的摘要校验内容：

```bt
manifest_response = reqwest('https://btlang.org/ai/manifest').send()
manifest = manifest_response.body.parse_json()
module_info = manifest.modules.find(fn(item) {
    item.id == 'core-contract'
})

module_response = reqwest('https://btlang.org' + module_info.content_url).send()
verified = crypto(module_response.body).sha256() === module_info.sha256

// 输出：true
print verified
```

## 注意事项

- 同一个开发任务应固定使用一个 `knowledge_version`，不要在任务中途混用两个版本。
- 下载模块或完整包后必须先校验 SHA-256，再写入正式缓存；校验失败时继续使用上一个有效版本。
- 客户端应随安装包内置一个已校验的完整快照。官网不可访问、超时、返回无效 JSON 或哈希不匹配时，回退到内置快照。
- `304` 响应没有正文；客户端应继续使用本地已校验内容。
- 模块接口只接受清单中存在的 ID，未知模块或版本返回 `404`；非 `GET` 请求返回 `405`。
