工具接入接口文档
工具接入接口文档
适用范围
这份文档面向 2026-04-17 已落地的工具插件架构。适合平台管理员、外部工具开发者和站内工具开发者按统一协议接入 tripai / NextDevTpl。
后台导入
先在 /admin/tool-config 导入工具定义,再补管理员默认配置
统一能力
用户、积分、AI、存储、审计统一复用平台能力
外部工具协议
外部服务使用 launch_ticket、runtime token 和 platform API
接入模式
适合只想复用平台账号体系、后台配置和入口管理的工具。
推荐做法:
- 导入工具定义
- 配好字段
- 入口指向外部地址或内部页面
适合主要依赖统一 AI 网关的工具。
推荐做法:
- 导入工具定义
- 配置
features - 在
/admin/ai绑定模型和 provider
适合前后端独立部署的产品。
推荐做法:
authMode = launch_ticket- 平台生成启动票据
- 外部服务端用
runtime token换用户身份并读取配置
适合像 RedInk 这样有专属页面、专属流程和专属适配层的工具。
推荐做法:
- 工具业务逻辑放工具模块
- 用户、AI、积分、存储仍走平台统一能力
接入前提
平台侧
平台已部署,数据库迁移完成,/admin/tool-config、/admin/ai、/admin/storage 可正常访问
工具侧
明确 toolKey、入口类型、是否要用户配置、积分、AI、存储、外部票据
外部工具额外要求
必须有自己的服务端,用来安全保存 runtime token,不能把 token 暴露给浏览器
命名约定
Prop
Type
标准接入流程
管理员进入 /zh/admin/tool-config,导入工具定义 JSON
在 /zh/admin/tool-config 填管理员默认配置、密钥和 JSON 字段
如果工具需要 AI,去 /zh/admin/ai 给 feature 绑定模型和 provider
如果工具要上传资源,去 /zh/admin/storage 检查对象存储和前缀规则
如果工具允许用户个人覆盖配置,到 /zh/dashboard/settings 验证字段是否按预期暴露
如果工具是外部服务,再串联 launch_ticket、session/exchange、runtime、runtime-save
手机号认证(AutoLive 等工具)
平台已支持手机号 + 密码登录;注册与改密使用短信验证码。外部工具不要在客户端直连 TripAI /api/auth/*,应由工具服务端 Relay:
- 登录:
POST /v1/auth/platform/exchangebody{ phone, password, device, licenseKey? } - 注册发码:
POST /v1/auth/phone/send-otp→ 平台phone-number/send-otp - 注册:
POST /v1/auth/phone/registerbody{ phone, code, password, name?, licenseKey?, device }— 无licenseKey时仍可完成平台注册并返回 token,响应含requiresLicenseActivation: true,客户端再调POST /v1/license/activate - 忘记密码:
POST /v1/auth/phone/password-reset/request→POST /v1/auth/phone/password-reset/confirm
平台侧对应:sign-in/phone-number、/api/platform/auth/phone/register、phone-number/request-password-reset、reset-password。
详见 docs/phone-auth-integration-plan-2026-05-22.html(2026-05-23 修订)。
工具定义结构
后台导入和接口导入使用同一结构
你在 /admin/tool-config 页面顶部粘贴的 JSON,和 POST /api/platform/tools/import 接口请求体中的 definition 完全一致。
{
"toolKey": "notes-ai",
"name": "Notes AI",
"description": "会议纪要和知识整理工具",
"entry": {
"type": "external_url",
"url": "https://notes.tripai.icu"
},
"runtimeMode": "platform_api",
"authMode": "launch_ticket",
"billingMode": "ai_gateway",
"storageMode": "platform_storage",
"capabilities": {
"adminConfig": true,
"userConfig": true,
"credits": true,
"ai": true,
"storage": true
},
"enabled": true,
"sortOrder": 60,
"fields": [
{
"fieldKey": "config1",
"label": "notes.defaultTone",
"description": "默认输出风格",
"group": "config",
"type": "select",
"adminOnly": true,
"userOverridable": false,
"defaultValueJson": "formal",
"optionsJson": ["formal", "concise", "friendly"]
},
{
"fieldKey": "secret1",
"label": "notes.webhookSecret",
"description": "外部回调签名密钥",
"group": "secret",
"type": "secret",
"adminOnly": true,
"userOverridable": false
},
{
"fieldKey": "json1",
"label": "notes.templateCatalog",
"description": "模板目录",
"group": "json",
"type": "json",
"adminOnly": true,
"userOverridable": false,
"defaultValueJson": {
"summary": "会议总结",
"todo": "待办提取"
}
}
],
"features": [
{
"featureKey": "meeting_summary",
"name": "会议总结",
"description": "生成会议纪要",
"requestType": "chat",
"defaultOperation": "text.generate",
"requiredCapabilities": ["text"],
"enabled": true,
"sortOrder": 10,
"pricing": {
"billingMode": "token_based",
"minimumCredits": 1,
"inputTokensPerCredit": 1000,
"outputTokensPerCredit": 500
}
}
],
"storage": {
"prefixRules": [
{
"prefix": "notes-ai/attachments/",
"purpose": "attachment",
"retentionClass": "temporary",
"ttlHours": 72,
"enabled": true,
"maxSizeBytes": 10485760,
"contentTypes": ["application/pdf", "image/png", "image/jpeg"]
}
]
}
}关键字段说明
元数据字段
Prop
Type
字段定义
Prop
Type
功能定义
Prop
Type
常用平台接口
1. 会话与账户
GET /api/platform/session
返回当前登录用户、套餐和积分余额。
{
"success": true,
"user": {
"id": "user_xxx",
"name": "Alice",
"email": "alice@example.com",
"phoneNumber": "+8613812345678",
"primaryContact": "+8613812345678",
"primaryContactType": "phone",
"emailIsPlaceholder": false,
"canReceiveEmail": true,
"image": null,
"role": "user"
},
"plan": {
"code": "pro",
"name": "Pro",
"hasActiveSubscription": true
},
"credits": {
"balance": 520.5,
"status": "active"
}
}积分精度(2026-06):
balance与扣费amount均为显示积分(number,最多 2 位小数,最小 0.01)。服务端内部以creditUnits = round(display × 100)记账;工具端请按小数解析,勿再假设整数积分。
2. 积分
POST /api/platform/credits/check
{
"amount": 3.5
}响应示例:
{
"success": true,
"sufficient": true,
"balance": 520.5,
"required": 3.5
}POST /api/platform/credits/consume
{
"amount": 0.06,
"serviceName": "notes_ai_summary",
"description": "生成会议纪要",
"metadata": {
"tool": "notes-ai",
"feature": "meeting_summary"
}
}POST /api/platform/credits/delegated/check
外部工具服务端用 runtime token 代表指定平台用户检查积分。请求头必须带:
Authorization: Bearer <runtime-token>该 token 必须属于请求里的 projectKey + tool,并拥有 credits:read scope。
{
"projectKey": "nextdevtpl",
"tool": "autolive",
"userId": "user_xxx",
"amount": 3.5
}POST /api/platform/credits/delegated/consume
外部工具服务端用 runtime token 代表指定平台用户消费积分。请求头必须带:
Authorization: Bearer <runtime-token>该 token 必须属于请求里的 projectKey + tool,并拥有 credits:consume scope。
{
"projectKey": "nextdevtpl",
"tool": "autolive",
"userId": "user_xxx",
"amount": 0.06,
"serviceName": "autolive:reply",
"description": "直播回复扣费",
"metadata": {
"sessionId": "live_xxx",
"replyId": "reply_xxx"
}
}POST /api/platform/credits/delegated/refund
仅用于补偿已经成功的 delegated consumption(例如音色槽位扣分成功、工具侧 entitlement 落库失败)。使用同一个 credits:consume runtime scope;平台校验原交易属于同一 projectKey / tool / userId,且 orderId 与原消费 metadata 一致。
{
"projectKey": "nextdevtpl",
"tool": "autolive",
"userId": "user_xxx",
"transactionId": "原 delegated consume 返回的 transactionId",
"orderId": "voice_slot_order_xxx",
"reason": "voice slot entitlement allocation failed"
}退款按 delegated_refund:{transactionId} 幂等;并发或重复请求只会增加一次余额。成功返回 refundedAmount、remainingBalance、originalTransactionId 与 idempotent。
POST /api/platform/tools/{toolKey}/entitlement/delegated
外部工具服务端用 runtime token 代表指定平台用户查询 license entitlement。无需用户 runtimeSessionToken。请求头:
Authorization: Bearer <runtime-token>该 token 必须属于请求里的 projectKey + tool,并拥有 runtime:read scope。
{
"projectKey": "nextdevtpl",
"tool": "my-crm",
"userId": "user_xxx",
"deviceId": "optional_device_id"
}响应示例:
{
"success": true,
"toolKey": "my-crm",
"userId": "user_xxx",
"entitled": true,
"summary": {
"activeKeyId": "lk_xxx"
},
"keys": []
}与
POST /api/platform/tools/{toolKey}/entitlement/runtime的区别:runtime 版需要用户runtimeSessionToken(客户端会话);delegated 版仅服务端runtime token+userId,适用于 Frappe 等外部后端。
POST /api/platform/tools/{toolKey}/license/activate/delegated
外部工具服务端用 runtime token 代表指定平台用户激活 license。无需用户 runtimeSessionToken。请求头:
Authorization: Bearer <runtime-token>该 token 必须拥有 runtime:write scope。
{
"projectKey": "nextdevtpl",
"tool": "my-crm",
"userId": "user_xxx",
"licenseKey": "XXXX-XXXX",
"deviceId": "device_fingerprint",
"deviceLabel": "可选设备名称"
}与
POST /api/platform/tools/{toolKey}/license/activate/runtime对称;scope 与 runtime 版一致(runtime:write),不要与credits:consume混用。
2.1 autolive-server 当前配置
autolive-server 是外部 Go 服务,NextDevTpl 侧按数据库工具配置接入。
当前约定:
- project key:
nextdevtpl - tool key:
autolive - 显示名:
autolive-server - 入口类型:
external_url - 本地入口:
http://127.0.0.1:8080 - 认证方式:
launch_ticket - AI feature:按业务动作独立配置:
talent-script-draft、script-image-understand、segment-performance-analysis、knowledge-extract、live-reply、live-reply-batch、segment-variant、segment-variant-batch、segment-rewrite;娱乐模式另增 7 个独立 feature:entertainment-talent-script-draft、entertainment-segment-performance-analysis、entertainment-live-reply、entertainment-live-reply-batch、entertainment-segment-variant、entertainment-segment-variant-batch、entertainment-segment-rewrite(详见docs/autolive-entertainment-mode.md§16.6) - TTS feature:按合成场景独立配置:
live-reply-tts、segment-tts、deep-train-tts、guide-phrase-tts;live-tts仅保留兼容旧调用方 - AI provider:
geekai - 默认模型:
gemini-2.5-flash - TTS provider:
bailian-tts或fishaudio - TTS 默认模型:
cosyvoice-v3-flash或对应 Fish Audio TTS model - 计费方式:固定
1积分 / 次
autolive-server 需要的环境变量:
$env:TRIPAI_BASE_URL="http://127.0.0.1:3000"
$env:TRIPAI_PROJECT_KEY="nextdevtpl"
$env:TRIPAI_TOOL_KEY="autolive"
$env:TRIPAI_RUNTIME_TOKEN="<tool_runtime_token>"
$env:TRIPAI_AI_API_KEY="<api_key>"
$env:TRIPAI_AI_TOOL_KEY="autolive"
$env:TRIPAI_AI_FEATURE_KEY="live-reply"
$env:TRIPAI_TALENT_SCRIPT_DRAFT_FEATURE_KEY="talent-script-draft"
$env:TRIPAI_SEGMENT_PERFORMANCE_ANALYSIS_FEATURE_KEY="segment-performance-analysis"
$env:TRIPAI_KNOWLEDGE_EXTRACT_FEATURE_KEY="knowledge-extract"
$env:TRIPAI_SEGMENT_VARIANT_BATCH_FEATURE_KEY="segment-variant-batch"
$env:TRIPAI_SEGMENT_REWRITE_FEATURE_KEY="segment-rewrite"
$env:TRIPAI_ENTERTAINMENT_TALENT_SCRIPT_DRAFT_FEATURE_KEY="entertainment-talent-script-draft"
$env:TRIPAI_ENTERTAINMENT_LIVE_REPLY_FEATURE_KEY="entertainment-live-reply"
$env:TRIPAI_ENTERTAINMENT_LIVE_REPLY_BATCH_FEATURE_KEY="entertainment-live-reply-batch"
$env:TRIPAI_ENTERTAINMENT_SEGMENT_VARIANT_FEATURE_KEY="entertainment-segment-variant"
$env:TRIPAI_ENTERTAINMENT_SEGMENT_VARIANT_BATCH_FEATURE_KEY="entertainment-segment-variant-batch"
$env:TRIPAI_ENTERTAINMENT_SEGMENT_REWRITE_FEATURE_KEY="entertainment-segment-rewrite"
$env:TRIPAI_ENTERTAINMENT_SEGMENT_PERFORMANCE_ANALYSIS_FEATURE_KEY="entertainment-segment-performance-analysis"
$env:AUTOLIVE_ENTERTAINMENT_MODE_ENABLED="true"
$env:TRIPAI_LIVE_REPLY_TTS_FEATURE_KEY="live-reply-tts"
$env:TRIPAI_SEGMENT_TTS_FEATURE_KEY="segment-tts"
$env:TRIPAI_DEEP_TRAIN_TTS_FEATURE_KEY="deep-train-tts"
$env:TRIPAI_GUIDE_PHRASE_TTS_FEATURE_KEY="guide-phrase-tts"TRIPAI_RUNTIME_TOKEN 至少需要:
runtime:readruntime:writesession:exchangecredits:readcredits:consume
TRIPAI_AI_API_KEY 建议限制:
- allowed tools:
["autolive"] - allowed models:
["gemini-2.5-flash"]
密钥保存
明文 runtime token 和 API key 只在生成时可见,不要写入仓库文档、提交记录或前端代码。
娱乐模式:玩法目录与用户玩法(autolive-server)
autolive-server 侧(非 TripAI 平台 API):
| 方法 | 路径 | 说明 |
|---|---|---|
GET | /v1/settings/live-mode | { "entertainmentEnabled": true };Admin 热开关优先,否则回退 AUTOLIVE_ENTERTAINMENT_MODE_ENABLED |
GET/PATCH | /v1/admin/settings/live-mode | 管理员立刻开关全站娱乐模式,无需重启 |
GET | /v1/live-playbook-catalog | 内置 + 当前用户玩法目录;项含 ref(builtin:* / user:*)、name、instruction、fingerprint |
GET/POST | /v1/live-playbooks | 用户自定义玩法列表 / 创建 |
PATCH/DELETE | /v1/live-playbooks/:id | 更新 / 删除用户玩法 |
GET/POST/PATCH/DELETE | /v1/admin/live-playbooks | 平台管理员维护内置玩法 |
娱乐 AI 请求走独立 TripAI feature(entertainment-*),与卖货 feature 分开计费与路由。完整产品契约见 docs/autolive-entertainment-mode.md。
3. AI 网关
POST /api/platform/ai/chat
{
"tool": "notes-ai",
"feature": "meeting_summary",
"input": "请整理这段会议记录"
}{
"tool": "notes-ai",
"feature": "meeting_summary",
"messages": [
{
"role": "system",
"content": "你是会议纪要助手"
},
{
"role": "user",
"content": "请总结下面内容"
}
],
"model": "gpt-4o-mini",
"operation": "text.generate"
}支持的常见 operation:
text.generateimage.understandimage.generateimage.editvideo.understandvideo.generateaudio.understandaudio.generatefile.understand
GET /api/platform/ai/chat/result?requestId=...
用于查询任务型 AI 结果。
POST /api/platform/ai/tts
用于真正的 TTS/语音合成请求。当前网关会按 provider 分流到真实上游:
- Fish Audio:
POST https://api.fish.audio/v1/tts - 阿里百炼 CosyVoice / Qwen-Audio-TTS:
POST .../api/v1/services/audio/tts/SpeechSynthesizer - VoxCPM2:
POST .../v1/audio/speech(二进制上传对象存储后返回audio.url)
最小请求:
{
"tool": "autolive",
"feature": "segment-tts",
"input": "欢迎来到直播间",
"model": "cosyvoice-v3-flash",
"voice": "longxiaochun",
"format": "mp3",
"sampleRate": 44100
}带引擎无关表演控制(推荐;P1 网关编译 + P2 live_reply* 桥接 + P3 话术/变体/deep_train + P4 开关扩展与管理编辑均已落地):
{
"tool": "autolive",
"feature": "segment-tts",
"input": "今天这款真的很适合日常通勤,先别急,我把区别讲清楚。",
"performance": {
"instruction": "亲切但有说服力,前半句轻快,解释区别时放慢一点",
"language": "zh",
"cues": [{ "after": "先别急", "kind": "pause" }]
}
}performance 字段:
| 字段 | 说明 |
|---|---|
instruction | 可选,引擎无关自然语言表演描述;禁止 SSML / [] 标签 / (style) 前缀 |
language | 可选,受限语言代码(如 zh/en);只影响合成语言提示,不翻译正文 |
cues | 可选,最多 4 个;kind ∈ 平台 canonical 集合(pause/laugh/sigh/cough/gasp/giggle/clear_throat/snort/uhm/shh);after 必须是正文中唯一短语 |
约定:
input必须是纯净展示正文,不得包含 SSML /[laughing]/(style)等供应商语法- 污染正文返回稳定错误码
tts_input_not_clean(HTTP 400,field=input);不计费、不写ai_request_log,但会落event=tts_validation_rejected审计日志 - 网关在选定实际 TTS 引擎后临时编译:CosyVoice →
instruction/SSML;Qwen-Audio →instruction/官方标签;Vox → 文本(prefix)与白名单事件标签 - 顶层
instruction/language/languageHints仍兼容,会规范化到performance - AutoLive
live_reply*由 Server 自动附带performance;talent_script_draft/ 变体深训(deep_train)同样持久化并转发;深训/单段合成受「TTS 语气指令」开关约束;第三方调用方也可直接传同一结构 enableSsml不再由调用方决定;是否启用 SSML 由模型与音色能力自动决定extraBody.input不得覆盖text/instruction/enable_ssml/language_hints/rate/pitch/volume(错误码tts_reserved_extra_input)- 用户计费按纯净
input字符数,不含编译插入的标签、SSML 或 Vox 前缀 - 响应
content/output.text始终为纯净正文,不返回synthesisText - 成功响应可含权威
synthesisFingerprint与synthesisProvenance(routeRevision/engineFamily/modelKey/sourceRevision/renderTargetId/compilerContractVersion/performanceControls.{applied,degraded,dropped});请求明细 attempt meta 同步可查 - 同正文不同情绪请让调用方把规范化
performance纳入externalIdempotencyKey(可用fingerprintTtsPerformance)
端到端产品闭环、表演编译与音色身份进度见 docs/autolive-tts-voice.md。
POST /api/platform/ai/tts/preflight
只读、不计费、不写 ai_request_log。按当前 tool/feature 路由解析引擎能力快照与音色 target 就绪状态,供 AutoLive Server / App 渲染可用标签与深训预检。
{
"tool": "autolive",
"feature": "segment-tts",
"audio": {
"enrollmentKey": "tripai:nextdevtpl:autolive:user:...:voice_..."
}
}成功时返回(脱敏,不含 API key / providerVoiceId / reference URL / 供应商语法):
capabilityRevision/routeRevision(形如segment-tts:42)route:engineFamily/modelKey/displayName/providerKindperformance:instructionMode、supportsInstruction、supportsRichTags、可用cues[](含 label)、instructionPresets[]、maxCues、languagesvoice:可选;identityStatus/targetStatus/strategy/sourceRevision/renderTargetIdfingerprintContext:供调用方计算期望合成指纹的字段子集
Vox 路由下 instructionMode 为 text_prefix 时,supportsInstruction 与 supportsRichTags 均为 true(与编译器一致)。
POST /api/platform/ai/voice-enrollment/ensure
幂等确保 CosyVoice 复刻音色已注册(多部署共享 enrollmentKey)。首次调用需 reference.referenceUrl;已存在且上游仍有效时只校验并返回 primary provider 的 providerVoiceId。
Shadow Clone 响应扩展(2026-06-29;现行语义以分片文档为准):
bindings[]:各 provider 上的 binding 状态(providerKey/providerVoiceId/syncStatus);用户默认仅 owner(RF=1),不再全池复制poolReadiness:full|partial|none(历史字段;新逻辑以 required target ready 为准)primaryProviderKey:HTTP 同步 clone 的主账号凭证
TTS 推荐只传 audio.enrollmentKey,由网关按 owner binding 的配额账号 + 健康凭证 与路由 model 对应的 render target 解析 voice_id。primary_only 不再表示固定全局 bailian-tts。AutoLive Server 对复刻音色已稳定发送 audio.enrollmentKey,普通请求不再附带从音色推断的 Cosy model;系统音色无 enrollment 时可继续只传 voice。
分层身份(2026-07-28)+ 容量分片(2026-07-31):同一 enrollmentKey 可挂多个引擎×模型 render target;binding 挂 renderTargetId,并带 quota_account_id / placement_role。详见 docs/autolive-tts-voice.md 与 docs/autolive-bailian-voice-account-sharding.md。
逻辑 enrollment(2026-07-31;App 新建音色主路径):
POST /api/platform/ai/voice-enrollments:创建(默认 Qwen Flash;容量预留;session 或 API Key)GET /api/platform/ai/voice-enrollments/{enrollmentKey}?tool=...:状态(requiredTargets/ready/failed+脱敏errorCode)DELETE /api/platform/ai/voice-enrollments/{enrollmentKey}?tool=...:tombstone + 上游删除POST /api/platform/ai/voice-commitments?action=commit|release:付费席位 hard commitment(runtime tokencredits:consume;购买前先 commit)POST /api/platform/credits/delegated/refund:工具 entitlement 落库失败时按原消费 transaction + orderId 幂等退款
创建幂等: 同用户同 enrollmentKey 已 ready,或 processing 且仍有活动预留/Shadow job → 返回现状,不再二次预留;createFailed/failed 允许 repair。跨用户冲突 → 409 enrollment_key_conflict。
错误体形状: enrollment 路由多为嵌套 { "error": { "code", "message" } };commitment / legacy voice-clone 410 多为 flat { "error", "message" }。
Commitment orderId(可选): 传入时写入 ai_voice_commitment_event 幂等;重放返回既有 quotaAccountId / hardCommittedSlots / softCommittedSlots / materializedSlots / delta。commit 与 release 须使用不同 orderId。无 orderId 则每次真实变更。失败 voice_capacity_unavailable → 503。
成功创建响应示例(脱敏,不含 quota account / provider key):
{
"success": true,
"status": "processing",
"ready": false,
"errorCode": null,
"enrollmentKey": "tripai:nextdevtpl:autolive:user:u1:voice:v1",
"requiredTargets": [
{
"engine": "qwen_audio_tts",
"model": "qwen-audio-3.0-tts-flash",
"required": true,
"status": "pending"
}
],
"targets": []
}DELETE:全部上游确认清理完成返回 200 { status: "deleted" };仍有 pending binding 返回 202 { status: "deleting", pendingBindings }。
逻辑 enrollment / 音色身份相关错误码:
error | HTTP | 含义 | 调用方建议 |
|---|---|---|---|
tts_voice_not_ready | 409 | 当前 model 对应 target 无 ready binding,或 Vox 缺 reference | 等待物化/补参考音频;不要当「音色已删」 |
voice_model_mismatch | 400 | 遗留 enrollment.targetModel / target 与当前路由 model 不一致 | 修 Admin 场景 model,或改用匹配目标的音色;不要重录 |
voice_target_unsupported | 400 | 如 Qwen 路由尚无独立复刻目标(不可复用 Cosy binding) | 切换到已 ready 的引擎/model,或 Admin 对该 model 执行 materialize |
voice_unavailable | 400 | 上游确认音色失效/不存在 | 重新选择或重新克隆 |
voice_capacity_unavailable | 503 | 无可分配百炼席位(对账过期/账号 full/容量不足) | 稍后重试或联系管理员扩容;勿向用户展示账号配额数字 |
enrollment_key_conflict | 409 | enrollmentKey 已被其他用户占用 | 换 key 或使用本人既有 key |
not_found | 404 | GET/DELETE 时 enrollment 不存在或非本人(不泄露存在性) | 勿向用户展示「无权」细节 |
voice_reference_invalid | 400 | 参考音频不符合要求 | 重新录制清晰连续朗读 |
voice_delete_in_progress | — | GET 状态为 deleting 时的 errorCode(非独立 HTTP 错误) | 用户文案:音色正在删除 |
voice_clone_create_deprecated | 410 | 用户侧遗留 POST /voice-clone action=create 已弃用 | 改调 POST /voice-enrollments;诊断可设 VOICE_CLONE_LEGACY_USER_CREATE=1 |
约定:
ensure禁止把已有 enrollment 的targetModel静默改写为另一模型(返回voice_model_mismatch)- 跨模型 / 控制参数错误不会把健康 enrollment 标为
expired - Vox 无稳定系统音色语义;带
enrollmentKey时必须能解析参考音频 - 上述确定性本地错误发生在预扣前,不会产生扣费流水
- 合成成功时响应与请求明细均可观察
synthesisFingerprint/synthesisProvenance/performanceControls;话术缓存失效以指纹为准 - create 后
query_voice暂未通过时 binding 保持syncing、shadow job 以verify_pending退避重试,不会因一次 miss 立刻终态 failed - Voice Clone / ensure 路径会把
refText写入cloneSpec并进入 source revision(历史空值可在 ensure 时补齐) - 新 Provider 加入 Voice Pool 不会自动 backfill 全部用户音色
- 全池 Shadow 手动 sync 需 Admin 传
confirmFullPool=true(或VOICE_SHADOW_FULL_SYNC_ENABLED=1)
Admin 配置(无需改数据库):
/admin/ai→ 音色资源:创建 quota account、填写quota_scope_key、挂载 Provider(同主账号多 Key 同 scope)、对账(对账超过 15 分钟将拒绝新 placement)/admin/ai→ Provider:百炼 dashscope TTS;同配额账号下标记 primary/secondary 凭证/admin/tool-config→ autolive:场景仍可primary_only;实际发往哪个 Key 由 owner 账号决定/admin/ai→ 模型绑定:TTS 绑定可设置 429/503 重试次数(maxRetries,建议 1–2)- 旧「音色 Shadow」诊断面板仍可用于预设/job 排查;用户音色创建走逻辑 enrollment /
user-qwen-v1
{
"tool": "autolive",
"feature": "voice-clone",
"enrollmentKey": "tripai:nextdevtpl:autolive:preset:zxlive_5262",
"targetModel": "cosyvoice-v3-flash",
"reference": { "referenceUrl": "https://cdn.example.com/ref.wav" },
"prefix": "autolive",
"metadata": { "presetId": "zxlive_5262", "kind": "cloned_preset" }
}POST /api/platform/ai/voice-clone
百炼 CosyVoice 声音复刻的遗留入口。产品新建音色请走 POST /api/platform/ai/voice-enrollments。
用户侧 action=create 默认返回 HTTP 410(voice_clone_create_deprecated),删除版本标签 v2026.08-voice-clone-create。运维诊断可设 VOICE_CLONE_LEGACY_USER_CREATE=1;Admin session 仍可 create。get / list / delete 仍可用至兼容窗口结束。
{
"tool": "autolive",
"feature": "voice-clone",
"action": "create",
"targetModel": "cosyvoice-v3-flash",
"prefix": "autolive",
"reference": {
"referenceUrl": "https://cdn.example.com/autolive/voices/user_1/ref/demo.wav"
},
"languageHints": ["zh"]
}成功响应示例:
{
"success": true,
"requestId": "air_vc_001",
"providerVoiceId": "cosyvoice-v3-flash-autolive-xxx",
"status": "ready",
"demoUrl": null,
"billing": {
"chargedCredits": 10,
"remainingBalance": 90
}
}成功响应会统一返回 output.audio:
- 百炼 / CosyVoice 通常返回
output.audio.url - Fish Audio 通常返回
output.audio.data(Base64)和output.audio.mimeType sampleRate当前仅对百炼 / CosyVoice 生效;传给其他 TTS provider 会直接返回 4xx,而不会再被静默忽略
4. 用户配置
GET /api/platform/tool-config/editor?projectKey=nextdevtpl&tool=notes-ai
读取用户侧可见配置表单。
POST /api/platform/tool-config/user
{
"projectKey": "nextdevtpl",
"tool": "notes-ai",
"values": {
"config2": "friendly"
},
"clearSecrets": []
}5. 对象存储
POST /api/platform/storage/presigned-image
{
"filename": "cover.png",
"contentType": "image/png",
"toolKey": "notes-ai",
"purpose": "attachment",
"retentionClass": "temporary",
"requestId": "req_xxx"
}6. 结果归档
POST /api/platform/results/save
{
"tool": "notes-ai",
"type": "meeting_summary",
"payload": {
"title": "周会纪要",
"content": "..."
},
"requestId": "req_xxx"
}外部工具接入协议
外部工具的核心原则
浏览器不应该直接持有 runtime token。正确做法是:平台前端拿一次性 ticket,外部工具服务端持有 runtime token 去换用户身份和读写配置。
启动时序
平台前端调用 GET /api/platform/tools/{toolKey}/launch
平台拿到 ticket 和 launchUrl 后跳转到外部工具
外部工具服务端用 POST /api/platform/tools/session/exchange 换到当前用户
外部工具服务端再调用 runtime / runtime-save 读取和写回工具配置
GET /api/platform/tools/{toolKey}/launch
成功响应示例:
{
"success": true,
"tool": "notes-ai",
"ticket": "ticket_xxx",
"launchUrl": "https://notes.tripai.icu?ticket=ticket_xxx&projectKey=nextdevtpl",
"expiresAt": "2026-04-17T10:30:00.000Z"
}POST /api/platform/tools/session/exchange
请求头:
Authorization: Bearer <runtime-token>请求体:
{
"projectKey": "nextdevtpl",
"tool": "notes-ai",
"ticket": "ticket_xxx"
}成功响应:
{
"success": true,
"toolKey": "notes-ai",
"user": {
"id": "user_xxx",
"name": "Alice",
"email": "alice@example.com"
},
"expiresAt": "2026-04-17T10:35:00.000Z"
}POST /api/platform/tool-config/runtime
请求头:
Authorization: Bearer <runtime-token>请求体:
{
"projectKey": "nextdevtpl",
"tool": "notes-ai",
"userId": "user_xxx",
"knownRevision": 12
}For the autolive tool, the resolved runtime response also exposes
config.aiResolvedFeatures["voice-clone"].defaultCredits from json2. The
field is optional; a missing value means 0. A configured value of 0 is
valid and means the platform voice-clone operation is free. Consumers must
not infer this value from minimumCredits or maintain a local fallback price.
POST /api/platform/tool-config/runtime-save
请求头:
Authorization: Bearer <runtime-token>请求体:
{
"projectKey": "nextdevtpl",
"tool": "notes-ai",
"userId": "user_xxx",
"values": {
"config2": "friendly"
},
"clearSecrets": []
}GET /api/platform/tool-config/revision?projectKey=nextdevtpl&tool=notes-ai
请求头:
Authorization: Bearer <runtime-token>用途:
- 只读取版本号
- 适合检测配置是否变化
管理后台接口
GET /api/platform/tools
读取工具状态列表、最近导入、最近 AI 请求和运行时访问情况
POST /api/platform/tools/import
导入一份新的工具定义
POST /api/platform/tools/{toolKey}/disable
停用工具但保留历史记录
POST /api/platform/tools/{toolKey}/rollback
回滚最近一次工具定义变更
推荐联调顺序
先完成工具定义导入,不要先写接口调用
先把后台默认配置、密钥和 JSON 字段填完整
再绑定 AI provider 和模型
再验证上传和对象存储前缀
再打通外部票据和运行时配置
最后串联完整业务流:AI、积分、归档、错误处理
常见失败原因
- 只导入了工具定义,没有补后台默认配置
- AI 功能没有在
/admin/ai绑定模型 - 工具被停用
- 字段被设置成
adminOnly = true - 没开
userOverridable = true
authMode不是launch_ticketruntime token没有session:exchange权限- 外部工具扣积分时,
runtime token没有credits:read或credits:consume权限 - 启动票据过期或已被消费
toolKey传错purpose传错- 后台没有对应的工具存储规则
一句话结论
推荐做法
新工具接入时,先导入工具定义,再补管理员配置,再绑定 AI 和存储,最后按是否为外部服务决定是否接 launch_ticket 和运行时接口。不要反过来做。
