yichong-api
v0.4.0
Published
YiChong 公共后端 API:模型、上传、审核、内容、Chat、账户、消费、配置和上报
Readme
yichong-api
独立发布的 TypeScript / ESM npm 包,准备 YiChong 各端通用的后端协议:模型任务、上传、审核、内容提取、Chat、语音合成、消费、账户原语、配置和上报。接口以现有 Canva 工具包为参考,0.4.0 提供 27 个方法,新增模型任务等待 waitForPrediction、输出地址工具 getPredictionOutputUrl、取消判断 isAbortError 和上传保留期 retention,与 yichong-canva2 2.5.1 的 API 对齐。[email protected] 精确依赖 0.4.0,开放全部 27 个方法;yichong-canva2 保持原有独立实现,后续再接入。公共层不依赖 React、Nuxt、Vue 或 Canva SDK,也没有运行时依赖。
公共层只处理请求、校验和返回值。登录缓存、用户状态、余额派生、订阅判断、支付轮询、界面和路由由宿主 SDK 管理。账户方法可供后续接入使用,现有 Canva 登录代码继续保留。
包名为 yichong-api,当前版本为 0.4.0;0.3.0 新增 TTS 与行为统计,保留通用音视频转录 createVtt / getVttStatus。[email protected] 在正式 dependencies 中精确依赖 [email protected],构建后保留 npm 导入,不再内嵌公共代码或使用 file: 依赖。网站执行 npm install yichong-web 时,npm 自动下载对应的 API 包,不需要本地源码目录。Canva 包保持独立实现,暂不依赖本包。
可单独使用完整 API:
npm install [email protected] --save-exact公开安装包只包含 dist、README 和包元数据;构建脚本和测试不会分发。支持 Node.js 22/24 和具备 Fetch API 的浏览器环境。
接入层
- Canva(待接入):公共层保留
requirePlatformUid、预测查询正文和严格响应校验等兼容选项,便于后续按现有 Canva 协议接入。当前没有 Canva 适配层,原包继续使用自己的 API 实现。 - Web:
frontend/web/yichong-web/src/client.ts从现有getContext读取身份,保留platform=web、平台 ID 回退和语言别名。查询仍补user_id,保留 version 创建、取消接口及旧网关的双重 JSON 编码兼容。现有网站登录继续由各网站负责。 - 上传:公共层沿用现有 Canva/Web 的协议,使用
node-nauth申请签名,预签名 PUT 不携带业务身份或凭据。包含对象命名、100 MiB 分片阈值、进度、ETag、合并和账户切换检查。当前由 Web 复用;rejectMultipartFailureFlag保留 Web 原有的success=false检查。
ReplicatePolicy 和上下文兼容开关仅供 SDK 接入层固定使用,应用页面不需要设置。新增后端字段或修复上传协议时修改本包;平台身份和登录差异留在适配层。
完整接口清单
统一入口是 createYichongApi()。常用业务方法保持平铺,账户、Canva 身份验证和远程配置使用命名空间。每个模块也提供独立工厂,Web 0.5.0 通过完整公共客户端开放所有方法,并保留 Web 上传响应的兼容策略。网站仍需显式接入各项业务能力。
| 模块 | 方法 | 鉴权与结果 |
| --- | --- | --- |
| 模型任务 | createPrediction、createSpecifyPrediction、getPrediction、cancelPrediction、waitForPrediction(0.4.0 起) | JWT;code/msg/data,取消兼容原任务对象;等待返回成功的任务快照 |
| 上传 | generatePresignedUrl、initiateUpload、getUploadUrl、completeUpload、uploadFile | 签名控制请求用 node-nauth;PUT 只用签名 URL;0.4.0 起 uploadFile 支持 retention |
| 审核 | textCheck | JWT;保留 allowed/decision/categories,拒绝内容也是正常响应 |
| 内容 | contentExtract | JWT;文档、图片、视频、网页/YouTube 公开 URL;返回 data.content |
| 转录 | createVtt、getVttStatus | JWT;音频/视频共用 /get-vtt/*,自动写入正文 userId,返回原始任务状态 |
| 语音合成(0.3.0 起) | createTextToSpeech、getTextToSpeechResult | 系统 UID 必需,JWT 可选;创建正文 guid 使用当前系统 UID,完成后 result 为音频 URL |
| 大模型 | chat | JWT;同步完整结果 data.result,保留多模态参数 |
| 消费 | reduceFreeCnt、addMonthlyUsage、addFreeUsageCnt | passport + 账户渠道;ok/msg,不重算套餐或自动扣费 |
| 行为统计(0.3.0 起) | reportUsage | 无认证 GET;Promise<boolean>,有限重试、脱敏与 URL 长度限制 |
| 上报 | reportError | 独立上报令牌;脱敏、体积限制、Worker/飞书确认;0.4.0 起 reporting.sdkVersion 写入 sdk_version,robot 参与脱敏 |
| 账户 | account.handleUserLoginByCanvaId、account.getPassport、account.getUserStatusByPassport | 原账户 JSON;不缓存票据或推断已登录 |
| Canva 身份 | canvaIdentity.getUserIds | 调用方传宿主用户 token 和 appId;不导入 Canva 官方 SDK |
| 版本配置 | siteConfig.getAppVersion | /site/get 表单请求,解析配置中的数字版本 |
0.4.0 提供 27 个方法,其中 22 个业务方法、5 个账户/身份/配置原语。后端路径、认证类别、响应类别和默认超时集中记录在 src/contracts.ts。新增方法要求 0.3.0 或更高版本。
packages/login 中的 canUseLimit、getPricingLink、pollUserStatus、refreshUserStatus、历史 use() 等包含宿主状态或流程编排,继续由 Canva Provider 维护。它们的网络能力可逐步使用上述账户/消费原语,当前登录和结账行为保持原样。
适配层使用示例
以下代码可用于直接安装本包的调用方或 SDK 接入层。Web SDK 0.5.0 精确依赖公共 API 0.4.0,完整开放任务等待、TTS 和行为统计等方法。
import { createYichongApi } from 'yichong-api';
declare const account: { id?: string; jwt?: string; passport?: string };
const api = createYichongApi({
getContext: () => ({
uid: account.id,
platformUid: account.id,
jwt: account.jwt,
platform: 'web',
appChannel: 'imgkits',
locale: 'zh-CN',
}),
getAccountCredentials: () => ({
passport: account.passport,
accessChannel: 'imgkit',
}),
services: {
replicate: 'https://api.imgkits.com',
content: 'https://ai.imgkits.com',
chat: 'https://ai.imgkits.com',
account: 'https://usa.imgkits.com',
},
});
await api.chat({ payload: { messages: [{ role: 'user', content: 'Hello' }] } });
await api.account.getUserStatusByPassport();服务地址分别配置,支持反向代理和产品路径前缀。services.accountPassport 可覆盖 passport 的特殊根地址,例如旧 Canva imgkits 的其他账户请求使用产品前缀,但申请 passport 使用根路径。siteConfig 的版本是审核/测试配置版本,独立于 npm 包版本。
appChannel 是请求归属,accessChannel 是账户鉴权渠道,不能互相猜测。消费和状态查询使用 getAccountCredentials() 返回的当前票据,AI 使用上下文 JWT。上报通过 reporting.getToken() 提供专用令牌,公共源码不包含 Canva 的固定上报常量;账户票据、JWT 和额外已知凭据只用于诊断脱敏。
创建客户端不会调用 getter、发送请求或读取存储。调用时读取最新身份;除独立的行为统计采用有限重试外,不自动重试、审核、轮询、消费或上报其他接口的错误。上传的多步流程共用总预算并保留账户切换检查。
音视频转录
新增 createVtt() 和 getVttStatus(),分别对应 POST /get-vtt/create、POST /get-vtt/status。创建正文里的 userId 自动取自 getContext().uid;同时携带当前 JWT、Channel、Accept-Language 和通用查询参数。调用方不需要传用户 ID,也不能通过参数覆盖身份。
// api 是上文 createYichongApi() 返回的客户端;媒体需要先上传为后端可访问的地址。
const created = await api.createVtt({
audio: 'https://media.example.com/speech.mp3',
}, { timeoutMs: 60_000 });
if (created.data.status === -1) {
throw new Error(created.data.remark || 'Transcription failed');
}
// 视频改为 api.createVtt({ video: videoUrl }),返回字段仍是 jobId。
const { data } = await api.getVttStatus({ jobId: created.data.jobId });
if (data.status === 10) {
const segments = JSON.parse(data.result ?? '[]');
console.log(segments); // [{ start_time: '00:00:00.000', end_time: '00:00:01.500', text: '你好' }]
} else if (data.status === -1) {
throw new Error(data.remark || 'Transcription failed');
}
// 0 / 2 表示仍在排队或处理中,由应用安排下一次查询和总时限。data.result 当前是字幕片段数组的 JSON 字符串,SDK 不自动解析,也不转成 WEBVTT/SRT 文件。需要文件时由应用另外转换。
可选创建参数为 ifRender: 0 | 1、email、env,按后端原名传递;省略时由后端取默认值。env: 'pre' 不立即派发任务,普通使用应省略。audio 与 video 建议只传一个,两者都非空时沿用后端视频优先规则;兼容另一字段为空字符串。name 不参与后端处理,因此不作为工具包参数。
单次创建和查询默认超时 60 秒,第二参数支持 { timeoutMs, signal }。SDK 不自动轮询、不自动重试创建、不额外调用消费接口;取消等待不会取消后端任务。任务失败以 data.status === -1 返回,接口业务错误或网络错误才抛出 ApiError。
转录服务默认使用 https://api.imgkits.com,可通过 services.vtt 指定已经部署新路由的服务地址,支持路径前缀。这里是客户端默认配置;实际可用性取决于后端部署和网关转发。这两个方法自 0.2.0 起提供,/get-vtt/* 需先上线;旧转录路由仍由后端保留。
模型任务等待(0.4.0 起)
import { getPredictionOutputUrl, isAbortError } from 'yichong-api';
const controller = new AbortController();
try {
const { data: id } = await api.createSpecifyPrediction({ owner, name, input });
const task = await api.waitForPrediction({ id }, { signal: controller.signal });
const url = getPredictionOutputUrl(task.output);
} catch (error) {
if (!isAbortError(error)) showError(error);
}waitForPrediction 是显式调用的等待流程,只重复调用 getPrediction:默认间隔 3000 毫秒、最多查询 60 次、总预算 180000 毫秒,默认值记录在 apiContracts.replicate.waitForPrediction。默认只在 succeeded 时返回;allowEarlyOutput: true 供已确认支持提前输出的旧模型使用。failed / canceled / aborted 抛 prediction_failed,并保留后端 error_msg 或 error;次数或总预算用完抛 prediction_timeout;调用方取消抛 aborted。只有无 HTTP 状态的网络错误和单次超时会继续查询,连续 3 次失败后保留原错误;鉴权、HTTP 与业务错误直接抛出。停止等待不会调用 cancelPrediction,也不会创建任务或消费额度。
getPredictionOutputUrl 从字符串、嵌套数组或 { url } 中取得第一个合法 HTTP(S) 地址,不接受 blob:、data: 或带用户名密码的地址;没有时返回空字符串。isAbortError 只把 ApiError 的 aborted 和 AbortError 视为主动取消。
uploadFile 自动命名时可传 retention: 'temp' | 'day30',生成 temp_ 或 day30_ 前缀,默认 temp。实际删除取决于目标桶的 R2 生命周期规则;不能与自定义 objectName 同时传入。
语音合成 TTS(0.3.0 起)
createTextToSpeech() 对应 POST /api/text-to-speech/create,getTextToSpeechResult() 对应 POST /api/text-to-speech/result。默认服务为 https://ai.imgkits.com,需要代理或测试环境时通过 services.tts 覆盖,支持路径前缀。
两个方法都要求 getContext().uid 是当前系统用户 ID。创建正文的 guid 自动取此值;调用方不能传入 guid、userId 或 app_id。特别是后端会根据非空 app_id 改变额度校验与扣费分支,因此不能把 Canva App ID 当成普通请求字段透传。现有后端以 guid 关联用户和用量,不能将此描述为 JWT 身份验证;SDK 有有效 JWT 时才附带 Authorization,没有时省略,绝不发送 Bearer null。Channel: ai、通用查询参数和语言沿用公共上下文。
// api 是上文 createYichongApi() 的客户端,且 getContext().uid 已有系统用户 ID。
const controller = new AbortController();
const options = { signal: controller.signal, timeoutMs: 60_000 };
const created = await api.createTextToSpeech({
text: '你好,欢迎使用语音合成。',
voice: 'Arrogant_Miss',
emotion: 'auto',
speed: 1,
}, options);
if (created.data.status === -1) {
throw new Error(created.data.remark || 'Speech generation failed');
}
// 保存 jobId:创建返回 code=0 只说明请求已处理,不说明音频已生成。
const jobId = created.data.jobId;
const { data } = await api.getTextToSpeechResult({ jobId }, options);
if (data.status === 10) {
if (!data.result) throw new Error('The completed task did not return audio');
console.log(data.result); // 音频 URL 字符串,可交给播放器或 Canva 音频导入流程。
} else if (data.status === -1) {
throw new Error(data.remark || 'Speech generation failed');
} else {
console.log('Still waiting or processing', jobId);
// 由应用稍后使用同一个 jobId 查询,并设置总时限;不要重新创建任务。
}必需参数为 text(非空、最多 5000 个 Unicode 字符);可选参数为 voice、emotion、speed、language、refer_audio、refer_audio_text,按后端字段名传递。speed 范围为 0.5–2.0,SDK 不自行舍入;省略时后端使用 1.0。音色与语言未填时由后端取默认值;refer_audio 是后端可访问的 HTTP(S) 参考音频 URL,参考文本最多 5000 个 Unicode 字符,后端仅在参考音频非空时使用。上传文件和选择音色属于应用流程,不由创建接口代办。
返回保留 { code, msg, data } 和 jobId/status/status_str/remark,查询时额外保留 result。任务状态为 0 等待、2 处理中、10 完成、-1 失败;result 是音频 URL 字符串或 null,无需 JSON.parse。code=0 且 status=-1 仍是业务任务失败,SDK保留该响应,由应用展示 remark;接口错误、非法响应、网络失败等才抛出 ApiError。
每次请求默认超时 60 秒,第二参数支持 { timeoutMs, signal }。SDK 不自动重试、轮询或再调用消费接口,后端自身执行 TTS 的字符用量处理。取消或超时只结束本次客户端等待,不能保证后台停止或未记账;尤其创建超时后不要直接重放创建请求。
行为统计(0.3.0 起)
reportUsage 兼容现有 GET https://log.aibabygenerator.io/api/report,与消费 UsageApi、飞书 reportError 分开。不会自动给每次模型请求记“生成成功”;业务结果成功后才由业务/脚手架记录成功事件。
const api = createYichongApi({
getContext: () => ({ uid: account.id, platform: 'web', appChannel: 'imgkits' }),
usageReporting: {
enabled: true, // 默认 true;false 时不发送
appKey: 'imgkits_web', // 省略则为 {appChannel}_{platform}
// endpoint: 'https://your-report-service.example/api/report',
},
getUsageReportingMetadata: () => ({ session_id: sessionId, app_version: '1' }),
});
void api.reportUsage({
sum_key: 'generate_success',
title: '生成成功',
data: { operation_id: operationId, duration_ms: 12800, result_count: 1 },
});上例的 sessionId 和 operationId 由宿主创建:会话 ID 关联一次应用打开,操作 ID 关联一次生成流程。每次 reportUsage 再生成独立事件 UUID,网络重试复用同一个 UUID,配合 Worker 去重。getUsageReportingMetadata 的同名基础属性优先于业务 data;occurred_at 始终是客户端发生时间。Worker 的统计 timestamp 使用服务端接收时间,客户端 query timestamp 仅保留兼容。
上报不要求已登录,不读取 getAccountCredentials(),请求不携带 JWT/passport/cookie;已有 uid、platform_uid、platform、app_channel、timezone 和 Accept-Language 仍按公共上下文补齐。返回 true 表示收到 HTTP 成功确认;关闭、无效参数、上下文异常、取消、序列化或网络错误均返回 false,不会抛到业务或递归上报飞书。
单次请求默认 4 秒,网络/超时/429/5xx 最多重试一次,其他 4xx 不重试。可用第二参数 { signal, timeoutMs } 取消或缩短等待预算(1–4000 毫秒,每次请求)。数据沿用旧客户端的 JSON → encodeURIComponent → URLSearchParams 双重编码。最多 3 层、30 个字段、数组 10 项、字符串 256 字符;完整编码 URL 超过 8192 字符时逐项移除尾部属性,仍超长则返回 false。
仅传事件枚举、模型名、时长、计数、错误码等必要属性。提示词、完整 input/output、文件、URL、token、stack、rawError 等字段会脱敏,非普通对象和 getter 会跳过;脱敏不是任意个人内容检测,不应把用户原文换一个字段名上传。[email protected] 已对接此方法及统计配置,旧 Web 版本需要升级。
开发与验证
API 与 Web 分别构建。公共 API 更新后,在 Web SDK 目录更新正式 npm 依赖,再执行 npm run check。Web 的构建只编译自己的源码,不读取或编译本包的源码目录。后续开发 Web 可以直接 npm ci,不需要旁边存在 API 源码。Canva SDK 继续独立构建与验证。
公共层独立验证:
npm ci
npm run check完成 Web SDK 的构建后,在本目录执行:
npm run check:consumers此检查打包 API 和 Web 的两个真实 tarball,以本机临时 npm registry 提供候选 API 包,在空项目和空缓存中只安装 Web,验证 npm 自动解析并下载 API、原始产物一致、ESM 导入与严格 TypeScript 类型兼容。不会内嵌 API,也没有 React 或 Canva SDK 依赖。不读取、构建或打包 Canva SDK;业务请求使用模拟网络。
发布顺序
本次配套版本为 [email protected] 和 [email protected],Web 精确依赖 API 0.4.0;上一组已发布版本为 API 0.3.0 / Web 0.4.0。npm 版本号发布后不可重复使用。
公共 API 后续升级时,先更新并发布 API 的新版本,确认 registry 可查询后,再更新 Web 的精确依赖及自身版本,完成检查后发布。独立的 Canva SDK 仍需单独维护和发布。已有网站不会自动升级;网站只需安装对应的 Web 包:
npm install [email protected] --save-exactWeb 包安装时由 npm 自动下载其指定的 API 版本,无需单独安装公共 API。
