Task Plugin API v1 参考
任务插件的 Manifest、上下文、生命周期、原生路由、宿主协议、用量、产物与流式能力。
契约状态与权威来源
当前仓库将 API v1 标记为尚未正式发布的契约。新增能力仍可能沿用 apiVersion: 1,旧宿主会拒绝不认识的字段。以下为中文参考,完整签名与校验结构以
v1.d.ts、v1.schema.json
和原始规范为准。
Manifest:meta
| 字段 | 类型 | 说明 |
|---|---|---|
apiVersion | 1 | 契约版本 |
key | string | 插件标识,最多 30 个字符,与市场目录名一致 |
name | string | 显示名称 |
version | string | 语义化版本,与版本目录一致 |
author | { name, url? } | 作者名称必填,URL 为 HTTP(S) 地址;属于作者自述信息 |
models | string[] | 声明支持的模型 |
fetchMode | per_task / batch | 单任务或批量轮询 |
description | LocalizedText | 插件简介 |
icon | string | LobeHub 图标名或 text / text:<label>,不接受远程 URL 或内联图片 |
website | string | 可选插件官网,非空时为有效 HTTPS URL |
sortPriority | integer | 展示排序,值越大越靠前;不影响路由优先级 |
baseUrl | string | 类型 61 渠道可使用的默认上游地址 |
allowedHosts | string[] | 渠道主机之外允许访问的额外主机,可带端口 |
upstreams | ("vendor" | "new_api")[] | 可选上游类型;默认支持厂商,声明 new_api 才能绑定类型 60 New API 渠道 |
auth | string / object | none、api_key、vertex_oauth 或规范定义的认证对象 |
channelTypes | number[] | 可适配的旧渠道类型;第三方插件通常使用类型 61 的 key 绑定 |
routes | NativeRoute[] | 插件自有原生路由 |
protocols | ProtocolClaim[] | 宿主协议声明 |
usageSchema / usageExamples | object / array | 默认用量字段与示例 |
usageProfiles | array | 按模型提供完整的用量 schema 和示例 |
requiredCapabilities | string[] | 必须由宿主支持的版本化能力 |
submitResponseTypes | array | 上游提交响应类型,默认 ["json"],可声明 "sse" |
baseUrl 不得包含凭据、查询串或片段,必须使用 ASCII 主机名;允许自托管的 HTTP 或私有地址。allowedHosts 使用 host / host:port,不包含协议或路径,端口会参与匹配。默认地址不会隐式扩大允许访问的主机集合。
本地化文本
LocalizedText 可使用字符串或含 en 的语言映射。字符串会规范化为英文映射。匹配顺序为当前语言、主语言、英文:
description: {
en: "Video generation through the vendor API",
zh: "通过厂商接口生成视频",
"zh-TW": "透過廠商介面產生影片",
}插件数据中的文案不应作为管理前端的翻译键使用。模型名、字段 key 和枚举原始值必须保持稳定。
生命周期钩子
| 导出 | 输入 | 主要返回内容 |
|---|---|---|
buildSubmitRequest | DriverContext | HTTP 请求描述符 |
parseSubmitResponse | ctx、{ statusCode, headers, body } | { taskId, taskData?, immediate?, state? } |
buildQueryRequest | TaskQueryContext | 单任务查询描述符,per_task 必需 |
parseTaskResult | 查询上下文、body、{ status, headers } | 标准化状态、可选进度/原因/结果等 |
buildBatchQueryRequest | 批量上下文、任务数组 | 批量查询描述符,batch 必需 |
parseBatchResult | 批量上下文、body、HTTP 信息 | 每项含 taskId 的结果数组,batch 必需 |
所有插件必须导出 meta、buildSubmitRequest、parseSubmitResponse 和 parseTaskResult,包括批量插件。
标准状态包括 NOT_START、SUBMITTED、QUEUED、IN_PROGRESS、SUCCESS、FAILURE、UNKNOWN。未知状态返回 UNKNOWN;不能把未知结果默认视为处理中。
上游响应的 HTTP 状态也参与宿主判定:404/410 导致失败和退款;401/403、429、5xx 和传输异常累计轮询失败。达到 TASK_POLL_MAX_FAILURES(默认 20)后进入失败清理,任务超时机制仍是外层截止条件。
请求与查询上下文
DriverContext 提供规范化的 requestBody、请求头、action、model / upstreamModel、渠道 baseUrl、认证信息、文件引用、公开任务 ID 和可选 originTasks。
TaskQueryContext 从已保存的任务重建:
| 字段 | 含义 |
|---|---|
taskId | 上游任务 ID |
publicTaskId | New API 公开任务 ID |
model / upstreamModel | 用户模型名与渠道映射后的上游模型名 |
action | 已持久化的标准化操作 |
data | 当前 Task.Data 快照 |
state | 插件私有的跨轮询状态 |
baseUrl / 认证字段 | 当前使用的渠道信息 |
查询侧没有 requestBody。保存的字段名是 data,不存在 raw 别名。解析钩子省略 state 时保留原状态;显式返回它才更新。请求和状态输入应视为只读,不依赖模块全局变量保存任务数据。
上游类型与网关互联
meta.upstreams 只允许不重复的 vendor 和 new_api。所有插件默认支持 vendor;声明 new_api 表示驱动也能访问安装了同一插件的上游 New API 网关。类型 60 渠道可通过 setting.task_plugin_key / setting.task_extend_plugin_keys 绑定插件;channelTypes 不能声明 60 或 61,同一旧渠道类型仍只能由一个插件拥有。
宿主在 DriverContext、TaskQueryContext、BatchQueryContext 和 buildContentRequest 上下文中提供 ctx.upstream,值为 { kind: "vendor" } 或 { kind: "new_api" };字段缺失时按 vendor 处理。对于 new_api,驱动使用插件自己的原生路由,例如 /doubao/api/v3/...、/ali/api/v1/...,不能直接照搬厂商路径。已有路径与原生路由相同或只使用宿主协议时,无需添加前缀。
类型 60 渠道的 authHeader 已由宿主设为 Bearer <channel key>,apiKey 为渠道密钥,不执行厂商的 OAuth/JWT 认证流程。提交解析器需要接受上游插件原生呈现器的响应,查询使用上游网关返回的公开任务 ID。upstreams 是 API v1 的增量扩展,旧宿主会拒绝未知字段,安装前应先升级宿主。
HTTP 描述符与文件
构造钩子返回 { url, method?, headers?, body?, ... },由宿主验证和发送。JSON 是默认 body 类型,也可通过 bodyType: "multipart" 与 parts 构造 multipart。
入站 body 由宿主统一解析为以下联合类型:
type RequestBody =
| { kind: 'json'; value: unknown }
| { kind: 'form'; fields: Record<string, readonly string[]> }
| {
kind: 'multipart';
fields: Record<string, readonly string[]>;
files: readonly FileReference[];
}
| { kind: 'none' };文件只以 { ref, field, filename, mimeType, size } 引用进入 JavaScript,插件无法直接读取文件字节。multipart 出站使用 parts[].fileRef;JSON 出站可嵌入占位符,由宿主替换为编码内容:
{ __fileRef: "request_file:input_reference", encoding: "base64" }
{ __fileRef: "request_file:input_reference", encoding: "dataUrl", mimeType: "image/png" }占位符可选 maxBytes,宿主仍会执行文件大小上限和总量检查。不得把引用当作文件路径。
同一字段可以上传多个文件,例如 image[]。每个文件都有独立的 ref:首个为 request_file:<field>,后续为 request_file:<field>#<index>(索引从 0 开始,第二个文件为 #1)。在 parts[].fileRef 或 JSON 占位符中直接使用对应的 files[].ref,不要自行拼接或把同字段的多个文件合并成一个引用。
原生路由与宿主协议
原生路由
meta.routes 定义插件自有 URL,函数名指向 native 对象中的同步函数:
routes: [
{
method: 'POST',
path: '/vendor/jobs',
type: 'submit',
decode: 'create',
render: 'created',
},
{
method: 'GET',
path: '/vendor/jobs/:task_id',
type: 'query',
render: 'status',
},
];submit/dynamic必须指定decode和render;query 只指定render,不能声明 decoder。- query 的任务参数名默认是
task_id,可通过taskIdParam指定。 - 解码器返回
{ kind: "submit", model, action?, requestBody?, originTaskIds? }或 query intent。 routes[].models可限制 submit/dynamic 的顶层模型,不能用于 query;模型嵌套在厂商 body 内时应由 decoder 判断。- 宿主负责认证、所有权和任务持久化,呈现器只处理对外响应。钩子抛出的错误信息可能返回调用者,应使用可读且不含敏感数据的错误文本。
originTaskIds 使用公开任务 ID,宿主检查所有权与渠道一致性后,将包含内部上游 ID 的 originTasks 注入 driver;不会把它交给对外呈现器。
结果保留
routes[].retainResult 是 submit/dynamic 路由可选的布尔字段,默认 true,query 路由禁止声明。只有所有成功提交都会立即完成的接口才应设置 false。即时终态结果不保存 task.data,后续原生查询、Responses/Video 查询及产物列表和内容接口均找不到该任务;任务记录仍保留用于计费与日志。提交呈现器仍能读取完整内存数据,完成用量钩子也在丢弃数据前执行。
若声明 false 的路由实际返回异步任务,宿主仍保留结果并记录警告。Responses 和 Video 协议始终保留结果;Image 协议的即时终态结果直接随创建响应返回,不保留结果数据,通过请求内轮询完成的结果则保留轮询快照。引用已丢弃结果的任务时,originTasks[].data 为 null。旧宿主会拒绝 retainResult 字段。
宿主协议
meta.protocols 声明使用宿主统一管理的协议路径,不应复制这些路径到 meta.routes:
| 协议 | 宿主路径 | 插件导出 |
|---|---|---|
openai_video | POST /v1/videos、GET /v1/videos/{id}、GET / HEAD /v1/videos/{id}/content | protocols.openai_video.decodeRequest 与 render |
openai_responses | POST /v1/responses、GET /v1/responses/{id} | decodeRequest,以及与模式匹配的渲染钩子 |
openai_image | POST /v1/images/generations、POST /v1/images/edits | protocols.openai_image.decodeRequest 与 render |
Responses 必须以对象形式明确声明 supports:stream 要求 renderEvents,sync 或 background 要求 renderFinal。缺少所需钩子,或导出没有任何声明模式使用的钩子,都会被拒绝。
解码器可能在候选筛选和选中渠道后多次执行,应保持确定性。多个插件可共享同协议下的模型,实际插件由所选渠道决定。
Video render 必须返回 JSON 对象;宿主覆盖标准 ID、模型、状态与时间字段,并保留符合规则的厂商扩展。Responses 的成功结果通过宿主注入的 ctx.artifacts[key].url 引用产物。
OpenAI Image 协议
使用 "openai_image" 或 { name: "openai_image", models: [...] } 声明,不设置 supports。它与 openai_video 一样没有请求模式;两者都可使用字符串或带模型范围的对象声明。图片生成接收 JSON,编辑接收 JSON 或 multipart。宿主固定 ctx.model,并提供 ctx.operation: "generate" | "edit"。
插件导出 decodeRequest 和 render。同步上游通过 parseSubmitResponse 返回 immediate 终态;异步上游返回任务 ID,由宿主在当前客户端请求中使用普通查询钩子等待完成。超时由 TASK_PLUGIN_PROTOCOL_TIMEOUT_SECONDS 控制,默认 600 秒,返回 504 task_timeout;客户端断开或等待超时后,已提交任务仍由后台轮询完成并结算。任务终态失败返回 400 和失败原因。
成功时 render(ctx, task) 返回含 data 数组的对象,每项为 { url } 或 { b64_json },可带 revised_prompt。宿主在缺失时补充 created。请求 response_format: "b64_json" 时,宿主下载图片 URL 并补充 Base64,保留原 URL;下载失败时记录警告并保留 URL。此钩子不接收 ctx.artifacts,图片地址来自上游结果。
用量钩子
可选导出 extractUsage、extractUsageOnSubmit 和 extractUsageOnComplete,分别从请求、提交结果或完成结果中提取用量。只返回符合所选 schema 的事实,不返回价格或 quota。
usageProfiles 为所列模型提供完整 schema 和示例,替代默认定义,不合并或继承。运行时先匹配最终上游模型;若上游名称没有 profile(例如被映射为厂商端点 ID),回退到客户端模型的 profile;两者均不匹配时使用插件默认定义。更新 profile 不会自动迁移已保存的计费表达式。配置说明见用量与计费。
数值字段的 description 用“计费对象 + 单价”命名,例如 Image generation unit price / 图片生成单价;实际字段值仍是用量。单位放在 unit,计数显示词放在 unitLabel,枚举显示词放在 enumLabels。动作、布尔和枚举说明分别描述动作、true 对应状态和条件;译文等义,不含数字价格、协议细节或句末标点。
产物与内容请求
产物钩子必须成对导出:
listArtifacts(task):从持久化数据投影稳定的{ key, type, mimeType? }列表,不返回第二份持久化记录或临时下载 URL。buildContentRequest(ctx):根据所选 artifact key、数据、生产版本、上游任务 ID、渠道信息及安全的 Range/条件请求头构造本次读取描述符。
带渠道凭据的内容请求只能访问渠道主机或 allowedHosts。公共动态 CDN 可使用 credentialless: true;这时只允许 GET/HEAD,不能附带插件 headers 或 body,宿主会检查初始地址和重定向。
宿主产物链接使用 TaskPublicAddress,缺省回退到 ServerAddress。多节点需要共享有效 CRYPTO_SECRET;轮换它会使已签发地址失效。
即时完成、SSE 与宿主能力
parseSubmitResponse 可返回 immediate 终态结果,让宿主在提交阶段完成持久化和结算;这些任务不会继续轮询。
上游提交使用 SSE 时,声明 submitResponseTypes: ["json", "sse"],并在描述符中选择 responseType: "sse":
| 模式 | 必要声明与导出 | 数据流 |
|---|---|---|
| 快照 | parseSubmitEvent | 每个事件返回 { state, done },结束后完整 state 作为 parseSubmitResponse 的 body |
| 增量 | requiredCapabilities: ["submit-sse-delta@1"]、parseSubmitEventDelta | 返回 { changes, state, done },宿主应用 set / append / appendText,完成后形成 body |
SSE 模式不会直接透传上游事件给客户端。插件解释事件语义和结束条件,宿主管理连接、帧解析、大小限制及超时;成功接受上游 SSE 后的读取失败不会自动重试提交,避免重复创建计费任务。
json-clone@1 提供同步的 utils.json.clone(value),用于创建可修改的独立 JSON 快照。其他工具包括时间、UUID、Base64、HMAC、JWT 和 Volc 签名工具;完整签名见类型声明。requiredCapabilities 必须声明准确版本,未知或不支持的能力会在加载时拒绝。
管理与诊断接口
Root 管理接口位于 /api/plugin/task,包括上传、版本激活、状态切换、删除、市场源、dry run 和 /runtime/status。这些管理操作与使用 API 密钥访问的 /v1/tasks 不是同一权限体系。
运行时以完整 generation 原子发布。请求固定使用一个 generation,后台轮询可能使用更新后的插件。多节点排查应比较数据库 override revision,不能直接比较各节点自增的 generation 编号。
这篇文档对您有帮助吗?
最后更新于