工具接入接口文档

工具接入接口文档

适用范围

这份文档面向 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/aifeature 绑定模型和 provider

如果工具要上传资源,去 /zh/admin/storage 检查对象存储和前缀规则

如果工具允许用户个人覆盖配置,到 /zh/dashboard/settings 验证字段是否按预期暴露

如果工具是外部服务,再串联 launch_ticketsession/exchangeruntimeruntime-save

手机号认证(AutoLive 等工具)

平台已支持手机号 + 密码登录;注册与改密使用短信验证码。外部工具不要在客户端直连 TripAI /api/auth/*,应由工具服务端 Relay:

  • 登录POST /v1/auth/platform/exchange body { phone, password, device, licenseKey? }
  • 注册发码POST /v1/auth/phone/send-otp → 平台 phone-number/send-otp
  • 注册POST /v1/auth/phone/register body { phone, code, password, name?, licenseKey?, device } — 无 licenseKey 时仍可完成平台注册并返回 token,响应含 requiresLicenseActivation: true,客户端再调 POST /v1/license/activate
  • 忘记密码POST /v1/auth/phone/password-reset/requestPOST /v1/auth/phone/password-reset/confirm

平台侧对应:sign-in/phone-number/api/platform/auth/phone/registerphone-number/request-password-resetreset-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,
    "status": "active"
  }
}

2. 积分

POST /api/platform/credits/check

{
  "amount": 3
}

POST /api/platform/credits/consume

{
  "amount": 3,
  "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
}

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": 3,
  "serviceName": "autolive:reply",
  "description": "直播回复扣费",
  "metadata": {
    "sessionId": "live_xxx",
    "replyId": "reply_xxx"
  }
}

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:live-reply(直播互动)、script-draft(AI 帮写)
  • TTS feature:live-tts
  • AI provider:geekai
  • 默认模型:gemini-2.5-flash
  • TTS provider:bailian-ttsfishaudio
  • 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_SCRIPT_DRAFT_FEATURE_KEY="script-draft"
$env:TRIPAI_TTS_FEATURE_KEY="live-tts"

TRIPAI_RUNTIME_TOKEN 至少需要:

  • runtime:read
  • runtime:write
  • session:exchange
  • credits:read
  • credits:consume

TRIPAI_AI_API_KEY 建议限制:

  • allowed tools:["autolive"]
  • allowed models:["gemini-2.5-flash"]

密钥保存

明文 runtime token 和 API key 只在生成时可见,不要写入仓库文档、提交记录或前端代码。

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.generate
  • image.understand
  • image.generate
  • image.edit
  • video.understand
  • video.generate
  • audio.understand
  • audio.generate
  • file.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:POST https://dashscope.aliyuncs.com/api/v1/services/audio/tts/SpeechSynthesizer

最小请求:

{
  "tool": "autolive",
  "feature": "live-tts",
  "input": "欢迎来到直播间",
  "model": "cosyvoice-v3-flash",
  "voice": "longxiaochun",
  "format": "mp3",
  "sampleRate": 44100
}

POST /api/platform/ai/voice-enrollment/ensure

幂等确保 CosyVoice 复刻音色已注册(多部署共享 enrollmentKey)。首次调用需 reference.referenceUrl;已存在且上游仍有效时只校验并返回已有 providerVoiceId

{
  "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 声音复刻必须走独立入口,不再复用 /api/platform/ai/chat

{
  "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

平台拿到 ticketlaunchUrl 后跳转到外部工具

外部工具服务端用 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
}

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_ticket
  • runtime token 没有 session:exchange 权限
  • 外部工具扣积分时,runtime token 没有 credits:readcredits:consume 权限
  • 启动票据过期或已被消费
  • toolKey 传错
  • purpose 传错
  • 后台没有对应的工具存储规则

一句话结论

推荐做法

新工具接入时,先导入工具定义,再补管理员配置,再绑定 AI 和存储,最后按是否为外部服务决定是否接 launch_ticket 和运行时接口。不要反过来做。