<!-- 文档分类: IMPL-RPT-014 | 阶段: 实现 | 原路径: docs/指南/trae-适配器-官方扫描修复-2026-05-25.md -->
# Trae 适配器官方登录态扫描修复报告

> 日期: 2026-05-25
> 涉及文件: `traeAdapter.js` · `traeOfficialArtifacts.js`
> 状态: 已实施，语法验证通过，功能验证通过

---

## 一、问题背景

Trae adapter 此前存在三个核心缺陷：

1. **无 Nirvana 即盲区** — 没有 Nirvana 换号软件时，`getStatus()` 报告"未检测到 Trae token"，即使用户已在官方 Trae IDE 中登录
2. **加密 blob 误判** — `iCubeAuthInfo://icube.cloudide` 的 base64 解码结果被 fallback 到通用 `base64-binary`，无法区分 Trae 自定义加密、DPAPI、Chromium v10/v11
3. **端点盲选** — `resolveTraeApiBases()` 和 `getRelayProfile()` 会将 `api.trae.ai/v1` 等非 OpenAI 兼容端点盲加到候选列表，导致 `listModels()` / `generate()` 打到 404 或 HTML 页面

---

## 二、Windows 端逆向调查关键发现

通过两轮 Windows 实机调查（storage.json/state.vscdb 读取 + 安装包 main.js 逆向），确认以下事实：

### 2.1 加密方案

| 项目 | 结论 |
|------|------|
| `iCubeAuthInfo://icube.cloudide` | base64 → 二进制，前缀 `74 63 05 10 00 00`（"tc" + 自定义字节） |
| `iCubeAuthInfo://usertag` | 同上，相同前缀 |
| 加密实施者 | Electron 主进程 `EncryptionMainService`，底层调用 `safeStorage.encryptString()` |
| 解密后内容 | JSON 字符串 → `{ token, refreshToken, expiredAt, userId, host, userRegion, account: { username, email, ... } }` |
| 外部可解密 | **否** — safeStorage 密钥绑定 Electron 主进程，外部进程无法调用 |

### 2.2 端点与协议

| 项目 | 结论 |
|------|------|
| `iCubeServerData://icube.cloudide` | 明文 JSON，含 `entitlementInfo`/`commercialActivityInfo`，**无** `apiHost`/`endpoint` 字段 |
| 真实 API 主机（日志） | `grow-normal.trae.ai`、`core-normal.trae.ai` |
| API 鉴权方式 | `x-cloudide-token: <token>`（非 Bearer、非 Cookie） |
| `GetThirdPartyToken` | 返回飞书/Lark token，非 OpenAI 兼容，无用 |
| `get_detail_param` | 配置详情接口，非模型列表 |
| 本地监听端口 | 无常驻端口，仅 SSO 登录时临时随机端口 |

### 2.3 state.vscdb

| 项目 | 结论 |
|------|------|
| 额外明文 token | 无 |
| `secret://` entry | 存在 `secret://{"extensionId":"trae.ai-code-completion","key":"isActivated"}`，值为 `v10` Chromium 加密 |
| 可用 auth 线索 | 无 — 仅 UI 状态和扩展激活标记 |

---

## 三、实施改动

### 3.1 `traeOfficialArtifacts.js`（5 处）

#### 3.1.1 Trae 自定义加密前缀识别

**函数**: `decodeTraeOfficialAuthBlob()`

新增 `74 63 05 10 00 00` 六字节前缀匹配，优先于 DPAPI / v10/v11 判断：

```
schemeHint: 'trae-custom-encrypted'
encryptionService: 'electron-safeStorage'
```

返回结构新增 `encryptionService` 字段（`'electron-safeStorage'` | `null`）。

#### 3.1.2 vscdb Buffer 安全序列化

**新增函数**: `_safeStringify(val)`

vscdb 中 `value` 列可能是 `Buffer`（v10/v11 加密或 Trae 自定义加密），不能直接 `String()` 转换。新函数处理三种情况：

- `v10`/`v11` 前缀 → `<chromium-encrypted:v10:base64...>`
- `tc\x05\x10` 前缀 → `<trae-encrypted:base64...>`
- 其他 → UTF-8 字符串

#### 3.1.3 `secret://` entry 识别

**函数**: `extractTraeOfficialArtifactsFromDb()`

新增 `SECRET_KEY_PATTERN = /^secret:\/\//` 匹配，识别 Electron SecretStorage entry。匹配到的 entry 写入 `result.secretEntries[]`，标记 `encrypted: true/false`。

#### 3.1.4 SQL 查询扩展

**函数**: `_readRelevantRowsFromVscdb()`

LIKE 模式从 7 条增加到 8 条，新增 `'secret://%trae%'`。

#### 3.1.5 ServerData URL 深层扫描

**函数**: `_tryParseServerData()` + **新增** `_extractUrlHintsFromObject()`

`iCubeServerData` 实际不含 `apiHost`/`endpoint` 顶层字段。新增递归扫描（3 层深度限制），提取嵌套对象中形如 `https://*.trae.ai` 或 `https://*.trae.cn` 的 URL 到 `endpointHints`。

### 3.2 `traeAdapter.js`（6 处）

#### 3.2.1 原生端点列表扩展

**函数**: `resolveTraeApiBases()`

`TRAE_NATIVE_HOSTS` 数组新增 `grow-normal.trae.ai`、`core-normal.trae.ai`，这些主机使用 Trae 原生协议（`x-cloudide-token` + 非 OpenAI 格式），不进入 OpenAI 兼容端点候选列表。

#### 3.2.2 CW 端点候选扩展

**函数**: `_resolveTraeCWEndpoints()`

CN 用户和国际用户的候选列表均增加 `grow-normal.trae.ai`、`core-normal.trae.ai`，排在 `adaptive-api` 之后。

#### 3.2.3 NativeAPI 多端点级联

**函数**: `fetchModelsFromNativeApi()`

改为遍历 `_resolveTraeCWEndpoints()` 返回的前 4 个端点（而非只试单个 `_resolveTraeCWEndpoint()`），并增加 HTML 响应检测 + 探活缓存写入。

#### 3.2.4 NativeAPI 移除 Cookie 前置条件

**函数**: `listModels()`

原来仅在 `_token.sessionCookies && !isCookieExpired()` 时才尝试 `fetchModelsFromNativeApi`。现在改为有 `accessToken` 即可尝试（Cookie 增强成功率但非必须）。

#### 3.2.5 Relay fallback 修复

**函数**: `getRelayProfile()`

移除 `|| 'https://api.trae.ai/v1'` 盲 fallback。无可用 OpenAI 兼容端点时抛出明确错误。

#### 3.2.6 加密态状态描述增强

**函数**: `getStatus()`

`statusLevel='encrypted'` 时，从 `authBlobAnalysis.schemeHint` 推导中文描述：

| schemeHint | 显示 |
|------------|------|
| `trae-custom-encrypted` | Electron safeStorage 加密 |
| `dpapi` | Windows DPAPI 加密 |
| `chromium-safe-storage-v10` | Chromium v10 加密 |
| 其他 | 加密格式未知 |

---

## 四、状态模型（修复后）

`getStatus()` 现在返回分层结构化状态：

```
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ 字段                 │ 说明                                                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ installDetected     │ 磁盘上有 Trae/Nirvana 目录                             │
│ officialArtifacts   │ 找到 iCube 登录痕迹（即使加密）                          │
│   .detected         │ boolean                                                │
│   .sources          │ 发现 artifact 的路径列表                                │
│   .authBlobPresent  │ iCubeAuthInfo://icube.cloudide 存在                    │
│   .userTagBlobPresent│ iCubeAuthInfo://usertag 存在                          │
│   .serverDataPresent│ iCubeServerData://icube.cloudide 存在                  │
│   .credentialMode   │ 'none' | 'encrypted' | 'plaintext'                    │
│   .authBlobAnalysis │ 加密方案分析（schemeHint / encryptionService）           │
│ credentialMode      │ 全局凭据模式                                            │
│ sessionVerified     │ token 成功调用过 API                                    │
│ available           │ 派生：sessionVerified 或有可用明文 token/cookie          │
│ statusLevel         │ 'verified' | 'pending' | 'encrypted' | 'installed' | 'missing' │
│ endpoints           │ 各端点探活状态 [{endpoint, status: 'ok'|'fail'|'untested'}] │
└─────────────────────┴────────────────────────────────────────────────────────┘
```

五种状态级别的含义：

| statusLevel | 条件 | 用户可见描述 |
|-------------|------|-------------|
| `verified` | available + sessionVerified | Token 有效，已验证 + Cookie (N 个模型) |
| `pending` | available + !sessionVerified | Token 检测到，待验证 (N 个模型) |
| `encrypted` | officialArtifactsDetected + credentialMode=encrypted | Trae 已登录，检测到加密登录态（Electron safeStorage 加密，外部无法解密） |
| `installed` | installDetected + 无 artifacts | Trae 已安装，未检测到登录态 — 请先登录 Trae IDE |
| `missing` | 其他 | 未检测到 Trae 安装 |

---

## 五、凭据优先级（修复后）

```
1. 官方 Trae 可验证会话  (officialCred.token + sessionVerified)
2. Nirvana 明文 token      (storage.json 中 traeAuth.accessToken 等)
3. Nirvana session cookie  (trae_local_cache.json 60天有效)
4. 账号池 token            (pool:trae)
5. 官方加密态 artifacts    (不可用于调用，但在 getStatus 中体现)
```

---

## 六、已知限制

| 限制 | 原因 | 后续方向 |
|------|------|---------|
| 无法从 safeStorage 解密 iCubeAuthInfo | Electron safeStorage 密钥绑定主进程 | 等第三轮调查确认 sandbox IPC token 落盘位置 |
| 解密后 token 使用 `x-cloudide-token` 头 | Trae 原生协议，非 Bearer | 需适配专属请求头格式 |
| 真实 API 端点动态拼接 | `getApi(Kc.ugApi, path)` 运行时决定 | 需确认 `host` 字段典型值 |
| Trae 无本地代理端口 | 仅 SSO 登录时临时端口 | 不可行路径 |

---

## 七、验证

### 语法检查

```bash
node -c backend/src/services/gateway/adapters/traeOfficialArtifacts.js  # OK
node -c backend/src/services/gateway/adapters/traeAdapter.js            # OK
```

### 功能验证

```bash
# Trae 自定义加密 blob 识别
node -e "
const a = require('./backend/src/services/gateway/adapters/traeOfficialArtifacts');
const b = Buffer.alloc(200); b[0]=0x74;b[1]=0x63;b[2]=0x05;b[3]=0x10;b[4]=0;b[5]=0;
const r = a.decodeTraeOfficialAuthBlob(b.toString('base64'));
console.log(r.schemeHint);           // trae-custom-encrypted
console.log(r.encryptionService);    // electron-safeStorage
console.log(r.decryptable);          // false
"

# 端到端: 模拟含加密 blob 的 storage.json → credentialMode=encrypted
node -e "
const a = require('./backend/src/services/gateway/adapters/traeOfficialArtifacts');
const b = Buffer.alloc(200); b[0]=0x74;b[1]=0x63;b[2]=0x05;b[3]=0x10;b[4]=0;b[5]=0;
const mock = {
  'iCubeAuthInfo://icube.cloudide': b.toString('base64'),
  'iCubeServerData://icube.cloudide': JSON.stringify({region:'cn-east',userId:'u123'}),
};
const r = a.extractTraeOfficialArtifactsFromStorage(mock, '/mock');
console.log(r.officialArtifactsDetected);  // true
console.log(r.credentialMode);             // encrypted
const c = a.resolveTraeOfficialCredential({artifacts: r});
console.log(c.credentialMode);             // encrypted
console.log(c.authBlobAnalysis.schemeHint); // trae-custom-encrypted
"
```

### 验证结果

| 测试项 | 结果 |
|--------|------|
| `tc 05 10` 前缀识别 | `trae-custom-encrypted` + `electron-safeStorage` |
| DPAPI 前缀识别 | `dpapi` |
| v10/v11 前缀识别 | `chromium-safe-storage-v10`/`v11` |
| 无 Nirvana 时 officialArtifactsDetected | `true` |
| 加密态 credentialMode | `encrypted`（不再是 `none`） |
| 端点不再盲选 | `resolveTraeApiBases()` 空列表时不会 fallback 到 `api.trae.ai/v1` |
| getRelayProfile 无端点时 | 抛出明确错误而非返回无效 URL |

---

## 八、待第三轮调查后实施

| 方向 | 触发条件 | 实施内容 |
|------|---------|---------|
| sandbox token 直读 | 确认 sandbox 将 token 写入可读文件/DB | 新增读取路径到 `readTraeToken()` |
| `x-cloudide-token` 协议适配 | 确认 `host` 字段典型值 | `callTraeByHttp` 新增 Trae 原生协议分支 |
| 扩展 API token 导出 | 确认 AuthenticationProvider 可用 | 提供用户安装的轻量 Trae 扩展 |
