// 把 API 协议参考渲染为独立的 HTML 文档(不引用任何外部资源):后台页面内嵌显示,也用于生成 PDF import { API_ERRORS, API_EVENTS, API_GROUPS, API_OVERVIEW, API_TYPES, type Endpoint, type Field } from './reference' export interface RenderOptions { /** 文档中示例使用的服务地址 */ baseUrl: string theme: 'light' | 'dark' version: string generatedAt: Date } const esc = (s: string) => s.replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]!)) /** 行内代码:`xxx` → */ const inline = (s: string) => esc(s).replace(/`([^`]+)`/g, '$1') /** 概述条目:`代码`、**加粗**,$BASE 替换为服务地址 */ const marked = (s: string, base: string) => inline(s.replaceAll('$BASE', base)).replace(/\*\*([^*]+)\*\*/g, '$1') /** "409 session_busy:说明" → 状态码加粗、错误码为代码样式 */ const errorItem = (x: string) => { const m = /^(\d{3}) ([a-z_]+)(.*)$/.exec(x) return m ? `
  • ${m[1]} ${m[2]}${inline(m[3]!)}
  • ` : `
  • ${inline(x)}
  • ` } const anchor = (e: Endpoint) => `${e.method}-${e.path}`.toLowerCase().replace(/[^a-z0-9]+/g, '-') function fieldTable(fields: Field[], withRequired = true) { return `${withRequired ? '' : ''}${ fields.map(f => `${withRequired ? `` : ''}`).join('') }
    字段类型必填说明
    ${esc(f.name)}${esc(f.type)}${f.required ? '是' : ''}${inline(f.desc)}
    ` } function endpoint(e: Endpoint, base: string) { return `

    ${e.method}${esc(e.path)}${esc(e.summary)}

    ${e.desc ? `

    ${inline(e.desc)}

    ` : ''} ${e.query?.length ? `

    查询参数

    ${fieldTable(e.query)}` : ''} ${e.body?.length ? `

    请求体(JSON)

    ${fieldTable(e.body)}` : ''} ${e.bodyNote ? `

    请求体

    ${inline(e.bodyNote)}

    ` : ''}

    响应

    ${e.response.status} ${esc(e.response.type)}${e.response.desc ? ` — ${inline(e.response.desc)}` : ''}

    ${e.errors?.length ? `

    常见错误

    ` : ''} ${e.example ? `

    示例

    ${esc(e.example.replaceAll('$BASE', base))}
    ` : ''}
    ` } export function renderApiReferenceHtml(o: RenderOptions): string { const base = o.baseUrl.replace(/\/+$/, '') const date = o.generatedAt.toISOString().slice(0, 10) const toc = [ ['overview', '1. 概述'], ...API_GROUPS.map((g, i) => [g.id, `${i + 2}. ${g.title}`]), ['event-types', `${API_GROUPS.length + 2}. 事件类型`], ['types', `${API_GROUPS.length + 3}. 数据结构`], ['errors', `${API_GROUPS.length + 4}. 错误码`], ] return ` AgentServer API 协议 ${esc(o.version)}

    AgentServer 对外 API 协议

    版本 ${esc(o.version)} · 服务地址 ${esc(base)} · 生成于 ${date}

    目录

      ${toc.map(([id, t]) => `
    1. ${esc(t!.replace(/^\d+\. /, ''))}
    2. `).join('')}

    1. 概述

    典型流程

      ${API_OVERVIEW.flow.map(x => `
    1. ${marked(x, base)}
    2. `).join('')}
    ${API_GROUPS.map((g, i) => `

    ${i + 2}. ${esc(g.title)}

    ${g.desc ? `

    ${inline(g.desc)}

    ` : ''} ${g.endpoints.map(e => endpoint(e, base)).join('\n')}`).join('\n')}

    ${API_GROUPS.length + 2}. 事件类型

    事件信封见"数据结构 › AgentEvent"。"落库"为否的事件只在实时事件流中推送,历史事件中只保留对应的 completed 事件。

    ${API_EVENTS.map(e => ``).join('\n')}
    typepayload说明落库
    ${esc(e.type)}${esc(e.payload)}${inline(e.desc)}${e.persisted ? '是' : '否'}

    ${API_GROUPS.length + 3}. 数据结构

    ${API_TYPES.map(t => `

    ${esc(t.name)}

    ${t.desc ? `

    ${inline(t.desc)}

    ` : ''}${fieldTable(t.fields, false)}`).join('\n')}

    ${API_GROUPS.length + 4}. 错误码

    ${API_ERRORS.map(e => ``).join('\n')}
    HTTPcode说明
    ${e.status}${esc(e.code)}${inline(e.desc)}
    ` }