cd extension pnpm --filter openapi-qoder-webview build # 先确保 webview 产物在(漏了面板会空白) npx vsce package --no-dependencies
从 Torna(toena)接口文档生成高质量 TypeScript 类型 + 请求函数的工具。
两段式流水线:Stage-1 确定性代码生成 → Stage-2 AI 润色(Qoder Agent SDK), AI 的命名决策落盘到命名账本,保证二次运行可复现、增量、不漂移。
产物对标 battery-asset-management-web,但解决其两大痛点:类型冗余、分页类型不可复用。
- Node.js ≥ 18(本仓库用 24 测试)
- 依赖已随仓库声明,安装即可:
npm install| 用途 | 变量 | 说明 |
|---|---|---|
| 拉取 Torna 文档 | TORNA_TOKEN |
Torna 请求头里的 token 值(见 接口/*.ts) |
| Torna 地址(可选) | TORNA_BASE_URL |
默认 https://doc-dev.qijiswap.com |
| Stage-2 AI 润色 | QODER_PERSONAL_ACCESS_TOKEN |
未设置时回退到本地 qodercli login 登录态 |
export TORNA_TOKEN="xxx:eyJhbGci..."
# 可选:export QODER_PERSONAL_ACCESS_TOKEN="qoder_..."# 1) 列出所有空间 / 项目,拿到 projectId
npx tsx src/cli.ts list
# 2) 生成某个项目(Stage-1 确定性 + 复用已有账本 Stage-1.5)
npx tsx src/cli.ts gen <projectId>
# 3) AI 润色(Stage-2:语义命名 + 标量数组元素推断 + tsc 校验闭环)
npx tsx src/polish-run.ts <projectId>
# 4) 把本次 AI 决策记入账本,并纳入 git(下次可复用)
npx tsx src/cli.ts harvest <projectId>
git add .openapi-qoder/naming.lock.json && git commit -m "chore: update naming ledger"或交互式选择空间 → 项目 → 直接生成:
npx tsx src/cli.ts pick产物在 generated/<projectId>/(Stage-1)与 generated/<projectId>-polished/(最终)。
generated/ 已被 gitignore;需要提交的只有账本 .openapi-qoder/naming.lock.json。
| 命令 | 作用 |
|---|---|
list |
列出空间 / 项目 |
pick |
交互式:空间 → 项目 → 生成 |
gen <projectId> |
拉取接口 + Stage-1 生成 + 复用账本(Stage-1.5,无 AI) |
harvest <projectId> |
把 Stage-2 结果反推为决策写入账本 |
status <projectId> |
查看:已入账本 / 结构变更需重润色 / 未解析 unknown[] 数 |
Stage-2 润色单独运行:
npx tsx src/polish-run.ts <projectId>
# 可调参数:
POLISH_BATCH=4 POLISH_MAX_TURNS=60 npx tsx src/polish-run.ts <projectId>npm scripts 快捷方式:npm run qgen -- <命令>、npm run polish -- <projectId>。
每个接口一个文件,自包含类型 + 请求函数:
// AUTO-GENERATED by openapi-qoder (Stage-1 codegen + Stage-2 AI polish).
// Names are pinned in .openapi-qoder/naming.lock.json — edit there, not here.
import request from '@/utils/request';
import type { PageResult } from './common.js';
export interface HostingVehicleQueryParam { /* ... */ }
export interface HostingVehicleVO { /* ... */ }
export type HostingVehiclePageData = PageResult<HostingVehicleVO>;
/** 托管运营车辆分页列表 */
export const getHostingVehiclePage = (data: HostingVehicleQueryParam) =>
request.post<HostingVehiclePageData, HostingVehicleQueryParam>('/v1.0/hostingVehicle/page', data);枚举会被提炼为常量 + 联合类型(common.ts 提供公共 PageResult<T>):
export const USER_TYPE = {
/** 个人 */ PERSONAL: 'CUSTOMER_TYPE_C',
/** 公司 */ COMPANY: 'CUSTOMER_TYPE_B',
} as const;
export type UserType = typeof USER_TYPE[keyof typeof USER_TYPE];要点:
- 响应壳(
code/msg/traceId/...)被剥离,只保留data。 - 分页结构自动识别为公共
PageResult<T>。 - 请求 URL 去掉网关前缀
/2m /2b /2c(代理会自动补)。 @/utils/request为默认请求模块,可在生成选项中替换。
.openapi-qoder/naming.lock.json 以 Torna docId 为稳定 key,记录 AI/人工的命名决策:
再次运行 gen 时:
shape未变 → 纯代码复用旧命名,完全跳过 AI(零成本、零漂移)。- 文档更新导致
shape变化 → 仅新增/变化部分交给 Stage-2 润色。 locked: true的函数名冻结;source: "manual"的条目 harvest 不覆盖。
典型工作流:
gen → polish-run → harvest → 提交 naming.lock.json
# 文档更新后再次 gen:多数接口直接复用账本,只剩少量需要 polish
npm run check:src # 工具源码类型检查
npm run check:out # 校验 generated/ 产物可编译
npm run check:polished # 校验 Stage-2 润色结果可编译Stage-2 内置 tsc 校验门:某文件润色后编译不过,会回滚该文件到 Stage-1 版本, 保证产物「永不比确定性生成更差」。
无需 Torna 网络,用仓库内 mock/*.json 生成到 generated/:
npm run gen # = tsx src/generate.ts更详细的设计说明见 ARCHITECTURE.md。
{ "version": 1, "apis": { "nzDyBg12": { "shape": "ebd35438c83b", // 结构指纹 "fn": "getHostingVehiclePage", "locked": true, "types": { "HostingVehiclePageItem": "HostingVehicleVO" }, "fieldTypes": { "HostingVehiclePageParam.operatorNames": "string[]" }, "source": "ai" // "manual" = 人工命名,AI 永不覆盖 } } }