Files
ttstd-infinite-canvas/web/src/pages/plugins/plugin-development-guide.md

6.8 KiB
Raw Blame History

上传请求协议插件

当前上传入口只安装声明式请求协议插件。它把影策统一的文本、图片、视频或音频请求转换为上游 HTTP API,并解析上游响应。素材源、画布节点、工作流、Agent 工具和 UI 扩展仍由应用代码注册,不能通过这里上传 JSON 安装。

1. 准备清单

上传文件必须是 UTF-8 JSON,大小不超过 512 KiB。插件 ID 使用小写 kebab-case;请求路径必须是相对路径;清单不得包含域名、Cookie 或 API Key。

{
  "apiVersion": "v1",
  "metadata": {
    "id": "acme-video",
    "name": "Acme Video API",
    "version": "1.0.0",
    "vendor": "Acme",
    "description": "Acme 视频生成协议适配",
    "categories": ["video"],
    "scopes": [
      "admin.system-channel",
      "user.custom-channel",
      "canvas",
      "creation",
      "agent"
    ],
    "contentType": "application/json",
    "parameters": [
      {
        "name": "model",
        "type": "string",
        "required": true,
        "mapping": "model",
        "description": "上游模型名"
      },
      {
        "name": "prompt",
        "type": "string",
        "required": true,
        "mapping": "input.prompt",
        "description": "视频描述"
      },
      {
        "name": "duration",
        "type": "integer",
        "mapping": "input.seconds",
        "description": "生成时长,单位为秒"
      }
    ],
    "documentation": "# Acme Video API\n\n在这里写完整的 Markdown 接入文档。"
  },
  "create": {
    "method": "POST",
    "path": "/v1/videos",
    "fields": {
      "model": "request.model",
      "input.prompt": "request.prompt",
      "input.seconds": "request.duration"
    }
  },
  "poll": {
    "method": "GET",
    "path": "/v1/videos/{{taskId}}"
  },
  "response": {
    "taskIdPaths": ["id", "task_id"],
    "statusPaths": ["status", "data.status"],
    "messagePaths": ["error.message", "message"],
    "resultUrlPaths": ["url", "video.url", "data.0.url"],
    "resultKind": "video"
  }
}

fields 左侧是上游请求字段路径,右侧是影策请求字段。同步协议只需要 create 和 response;异步协议再声明 poll。清单不会执行 JavaScript,也不能使用 host: 执行器。

同步文本响应

文本模型不一定需要创建任务后轮询。如果上游在创建请求中直接返回正文,可以只声明 create 和 response,例如:

{
  "create": {
    "method": "POST",
    "path": "/v1/chat/completions",
    "fields": {
      "model": "request.model",
      "messages": "request.messages"
    }
  },
  "response": {
    "textPaths": ["choices.0.message.content"],
    "reasoningPaths": ["choices.0.message.reasoning_content"]
  }
}
  • response.textPaths 按顺序尝试读取文本正文,支持对象路径和数组下标。
  • response.reasoningPaths 是可选的,用于读取推理内容;没有该字段时不会影响正文解析。
  • 如果没有声明 statusPaths,但解析到了文本或媒体结果,宿主会将本次响应视为成功。
  • agentResponse 只负责 Agent 工具请求的响应解析,与普通文本请求的 response 相互独立。

2. 编写接入文档

metadata.documentation 是插件详情页展示的 Markdown 正文,不是可选简介。至少写清楚:

  • 接口与鉴权:创建、查询和取消接口的 Method、Path、Header 与 Content-Type。
  • 模型与参数:可用模型名、类型、必填性、默认值、可选值及字段映射。
  • 素材限制:数量、格式、大小、时长,以及 URL 可访问性要求。
  • 请求与响应:提交成功、处理中、完成和失败的真实示例。
  • 轮询与下载:状态值、建议间隔、超时和结果 URL 有效期。
  • 错误处理:HTTP 状态、上游错误字段、内容审核和额度限制。

文档中的路径、模型名和响应字段必须与清单实现一致。详情页支持标题、表格、列表、引用、链接和代码块,并按 GitHub Flavored Markdown 预览。

3. 上传前检查

检查项 要求
标识 apiVersion 为 v1,ID 为 kebab-case,名称和版本不为空
能力 至少声明一个 category 和一个 scope
请求 Method 受支持,Path 为相对路径,字段映射来自 request.*
响应 任务 ID、状态、错误和结果地址路径与真实响应一致
文档 metadata.documentation 完整,并与实现同步
安全 不包含域名、密钥、Cookie、个人数据或 host: 执行器

上传、启用和停用属于管理员写操作。校验失败时插件不会安装;已安装协议停用后,模型配置入口不再提供该协议。

4. Agent 工具请求协议

如果协议同时服务于画布 Agent,请额外声明 agent 和 agentResponse。agent.fields 的右侧可以访问:

  • request.model
  • request.extra.agent.chatCompletion.*
  • request.extra.agent.responses.*

这样同一个插件可以由字段映射决定第三方的消息、工具定义和工具选择,不需要在前端为某个模型写死 URL 或请求格式。示例:

{
  "agent": {
    "method": "POST",
    "path": "/v1/chat/completions",
    "fields": {
      "model": "request.model",
      "messages": "request.extra.agent.chatCompletion.messages",
      "tools": "request.extra.agent.chatCompletion.tools",
      "tool_choice": "request.extra.agent.chatCompletion.tool_choice"
    }
  },
  "agentResponse": {
    "textPaths": ["choices.0.message.content"],
    "reasoningPaths": ["choices.0.message.reasoning_content"],
    "toolCallsPath": "choices.0.message.tool_calls",
    "toolCallIdPaths": ["id"],
    "toolCallNamePaths": ["function.name"],
    "toolCallArgumentsPaths": ["function.arguments"]
  }
}

agentResponse 的路径支持对象和数组下标(例如 choices.0.message.content)。第三方返回的 tool_calls[].function.arguments 可以是 JSON 字符串,也可以是 JSON 对象;宿主会统一转换为 Agent 合同要求的字符串。Agent 请求仍由后端统一负责鉴权、私网/本机上游校验、超时、日志和计费;插件只负责字段映射与结果解析。

5. 运行边界

声明式插件是请求协议运行时:它负责第三方 HTTP 方法、相对路径、请求字段映射、同步/异步响应解析、轮询状态、任务 ID、错误消息和结果地址。系统渠道和用户自建渠道只要选择了明确的协议,都会经过后端协议运行时,不依赖前端为某个模型硬编码请求格式。

宿主负责鉴权、Base URL 版本归一化、私网/本机上游安全校验、出站请求、超时、并发、计费、轮询生命周期、结果下载和任务恢复。内置的 multipart、签名鉴权、特殊媒体下载等协议仍由宿主内置 adapter 承担;上传的第三方插件必须使用声明式字段映射,不能上传可执行代码。