插件精灵脚本开发说明
面向开发者和 AI 的完整脚本契约,涵盖元数据、执行模式、常用配置、任务结果和 MCP Tool。
本文是插件精灵的公开开发契约,面向脚本开发者和协助生成脚本的 AI。为兼容既有脚本,JavaScript 全局对象和元数据前缀继续使用SellerFeeds与@sellerfeeds-*。平台实测差异与故障排查请同时参考《插件精灵脚本开发知识库》。
1. 先理解运行模型
插件精灵是 Chrome MV3 用户脚本运行器。脚本负责业务逻辑,插件负责安装、权限申请、任务调度、常用配置传递、任务历史和可选的 MCP 接入。
- 官方脚本和社区脚本使用同一套运行接口。
- 每个脚本可以声明一个或多个 Tool,但应优先把一个完整业务动作设计成一个 Tool。
- 手动、批量、定时和 MCP 调用最终都会进入同一个
SellerFeeds.onTask处理器。 - 脚本自行决定外部 API 调用、字段映射、追加或覆盖、去重、报告及链接返回方式。
- 插件不会替脚本保存目标网站 Cookie,也不会替脚本实现某个平台的业务写入规则。
2. 最小可运行脚本
// ==UserScript==
// @name 示例商品查询
// @namespace https://example.com/sellerfeeds
// @version 1.0.0
// @description 根据商品编号查询商品信息
// @match https://www.example.com/*
// @run-at document-idle
// @grant none
// @sellerfeeds-execution-mode page
// @sellerfeeds-tool {"name":"example_query_product","title":"查询商品","description":"当用户需要查询 Example 网站中的单个商品信息时使用。读取商品标题与价格,不修改网站数据;需要用户已登录 Example。","inputSchema":{"type":"object","properties":{"productId":{"type":"string","title":"商品编号","description":"Example 网站中的商品编号,不能为空。","minLength":1}},"required":["productId"],"additionalProperties":false},"outputSchema":{"type":"object","properties":{"productId":{"type":"string","description":"商品编号。"},"title":{"type":"string","description":"商品标题。"},"price":{"type":"number","description":"商品价格;网页未返回时省略该字段。"}},"required":["productId","title"]}}
// ==/UserScript==
SellerFeeds.onTask(async ({ taskId, tool, input, variables, source }) => {
if (tool !== 'example_query_product') throw new Error(`不支持的 Tool:${tool}`);
if (!input.productId) throw new Error('请填写商品编号');
return {
message: '查询完成',
data: {
productId: input.productId,
title: '网页返回的真实标题',
},
};
});
@sellerfeeds-tool 和 @sellerfeeds-variable 的 JSON 必须各自写在一行中;文档中的格式化 JSON 只用于讲解。
3. 元数据字段
3.1 标准 UserScript 字段
| 字段 | 要求 |
|---|---|
@name | 必填,脚本显示名称;与 @namespace 一起决定脚本身份。 |
@namespace | 建议使用稳定且属于开发者的命名空间;不要在更新时修改。 |
@version | 建议使用 x.y.z 数字版本;只有更高版本才会被识别为更新。 |
@description | 清楚说明脚本用途,会显示在安装预览和脚本库中。 |
@author | 可选,开发者名称。 |
@match | 必填至少一条,仅支持明确的 HTTP/HTTPS 范围,禁止 <all_urls>。 |
@exclude-match / @include / @exclude | 可选,用于进一步修正注入范围。 |
@run-at | 可选,常用值为 document-idle。 |
@grant | 建议固定为 none,通过 SellerFeeds API 使用运行能力。 |
@noframes | 可选,声明后不注入 iframe。 |
@downloadURL / @updateURL | HTTPS .user.js 地址;通过插件精灵脚本市场发布时由平台生成。 |
@homepageURL / @supportURL | 可选,项目主页和支持地址。 |
3.2 插件精灵扩展字段(@sellerfeeds-*)
| 字段 | 要求 |
|---|---|
@sellerfeeds-execution-mode | page(默认)或 offscreen;旧的 background 已废弃。 |
@sellerfeeds-entry-url | page 模式可选;任务没有现成页面时自动打开的 HTTPS 地址,支持 {input.字段} 占位符。 |
@sellerfeeds-world / @inject-into | content(默认隔离世界)或 main/page(MAIN 世界)。MAIN 世界能访问页面 JS,但网站也能观察和影响脚本。 |
@connect | offscreen 模式可声明额外 API 域,例如 https://api.example.com/*。可写多条。 |
@sellerfeeds-tool | Tool 的单行 JSON 声明,可写多条。 |
@sellerfeeds-variable | “常用配置”的可选表单模板,单行 JSON,可写多条。 |
@sellerfeeds-official | 插件精灵官方分发专用;社区脚本不得声明。 |
脚本源码最大 2MB。安装和更新地址必须使用 HTTPS,并以 .user.js 结尾。
4. 选择执行模式
| 对比项 | page | offscreen |
|---|---|---|
| 适合场景 | 读取或操作目标网页真实 DOM、页面 JS 状态、页面导航 | 纯 HTTP 请求与响应解析,不需要目标页 DOM |
| 执行位置 | 匹配网页的 USER_SCRIPT 或 MAIN 世界 | 插件的隔离 sandbox |
| 没有打开目标页时 | 插件按入口地址静默打开后台标签页 | 不打开标签页,直接在后台沙箱运行 |
| 网络访问 | 页面环境网络能力 | 使用 SellerFeeds.fetch 由扩展代发 |
| Cookie | 使用目标网页当前登录态 | 代发请求使用浏览器当前登录态 |
| DOM | 目标网站真实 DOM | 只有沙箱自身 DOM,可用 DOMParser 解析 HTML 字符串 |
选择原则:必须操作网页就用 page;只做“请求 + 解析”就用 offscreen。
4.1 page 模式入口
// @sellerfeeds-execution-mode page
// @sellerfeeds-entry-url https://www.example.com/product/{input.productId}
占位符只能读取 input 顶层字段。缺少可选字段时,运行器会尝试回退到 @match 可推导出的首页,因此脚本仍需自行检查当前页面和输入。
4.2 offscreen 模式网络域
// @match https://www.example.com/*
// @connect https://api.example.com/*
// @sellerfeeds-execution-mode offscreen
@match 表示目标网站及基础授权范围;@connect 只增加允许请求的 API 域,不会把脚本注入该域。初始 URL 和每一次重定向都必须处于脚本声明且用户已授权的范围内。
5. SellerFeeds 运行时 API
5.1 接收任务
SellerFeeds.onTask(async ({ taskId, tool, input, variables, source }) => {
// source: manual | batch | scheduled | mcp
return { message: '完成', data: {} };
});
| 字段 | 含义 |
|---|---|
taskId | 本次任务的唯一编号。 |
tool | 被调用的 Tool name。一个脚本有多个 Tool 时必须据此分派。 |
input | 已按 inputSchema 生成并校验的任务参数。 |
variables | 用户为本次任务选择的完整“常用配置”,未选择时为 {}。 |
source | manual、batch、scheduled 或 mcp。 |
处理器返回值必须可被 JSON 序列化。抛出 Error 会使任务失败,错误信息会进入任务历史和 MCP 报告。
5.2 后台网络请求
offscreen 脚本通过以下接口请求目标网站或 @connect 域:
const response = await SellerFeeds.fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ keyword: input.keyword }),
});
if (!response.ok) throw new Error(`请求失败:HTTP ${response.status}`);
const result = await response.json();
限制如下:
body只支持字符串,JSON 对象必须先JSON.stringify。headers使用普通对象。- 沙箱内不能直接使用
chrome.*。 - 桥接请求不能真正中止;需要超时提示时可使用
Promise.race,并忽略迟到结果。 - 不要在日志、报告或错误消息中输出 Cookie、Token 或完整常用配置。
5.3 日志与进度
SellerFeeds.log('开始查询', { productId: input.productId });
SellerFeeds.emit('task-progress', { current: 20, total: 100 });
日志只写必要的诊断信息,不要记录凭据和完整响应中的隐私数据。
6. Tool 与输入 Schema
6.1 Tool 声明结构
{
"name": "amazon_collect_search_results",
"title": "采集亚马逊搜索结果",
"description": "当用户需要分析亚马逊关键词搜索结果时使用。读取自然位与广告位,返回商品列表和位置类型;需要浏览器已登录目标站点,只读取数据,不修改店铺。",
"inputSchema": {
"type": "object",
"properties": {},
"required": [],
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"properties": {}
}
}
6.2 MCP 发布硬性要求
脚本能在本地运行,不代表它会自动成为 MCP Tool。安装后默认不发布到 MCP;只有用户开启全局 MCP,并在脚本中心单独打开该脚本的 MCP 开关,AI 才能看到它。
发布前必须满足:
name匹配^[A-Za-z0-9_-]{1,128}$,不能使用保留名get_report。name应稳定且具有业务前缀,推荐“平台_动作_对象”,如amazon_collect_search_results。description明确回答:何时使用、做什么、作用范围、返回什么、需要什么前提、是否有副作用。inputSchema根节点必须是{"type":"object"}。- 每个顶层参数必须有准确的
type和description;数组还必须声明items.type。 required只能引用properties中存在的字段。- 同名 Tool 会冲突,发生冲突的 Tool 都不会发布。
建议为 Tool 和参数提供普通用户能看懂的 title,并声明稳定的 outputSchema。
6.3 Schema 设计要求
支持常用 JSON Schema 约束,包括 type、enum、default、minimum、maximum、minLength、pattern、minItems、required 和 additionalProperties。
- 字段必须对应网页或接口真实存在的输入。
- 枚举只列出真实选项,不虚构“自动”等页面没有的值。
- 数值使用
number或integer,不要让用户填写带单位的字符串。 - 描述中写清单位、格式、示例、范围以及字段间关系。
- Schema 负责基础校验;登录状态、跨字段关系和业务错误仍由脚本检查。
- 没有获取到的数据返回
null或省略,不得使用0或空字符串伪造真实值。
7. 常用配置与配置模板
“常用配置”让普通用户保存一组经常重复填写的名称和值,例如表格地址、授权码、店铺编号或固定筛选条件。它是通用参数库,不绑定某个脚本或平台。
7.1 自动匹配规则
用户为任务选择一项常用配置后:
- 与 Tool
inputSchema同名、同路径的值会自动填入input。 - 用户在任务表单中手动修改的值优先。
- 不在 Schema 中的内容不会混入
input,但脚本仍能从完整的variables中读取。 - 未选择常用配置时,
variables为{}。 - 手动、批量和定时任务都可以选择常用配置;定时任务运行时读取该配置的最新值。
优先级为:用户手动填写 > 常用配置同名值 > Schema 默认值。
7.2 预制录入模板
脚本可声明一个或多个表单模板:
// @sellerfeeds-variable {"title":"飞书多维表格配置","description":"填写表格写入所需信息","schema":{"type":"object","properties":{"baseToken":{"type":"string","title":"多维表格授权码"},"appToken":{"type":"string","title":"App Token"},"tableId":{"type":"string","title":"Table ID"},"baseUrl":{"type":"string","title":"表格链接"}},"required":["baseToken","appToken","tableId"]}}
安装脚本时,用户可以选择模板或“稍后设置”。选中后,安装完成会打开对应表单。模板只改善录入体验,不绑定或过滤常用配置,也不限制开发者增加任意字段。
7.3 在脚本中读取
SellerFeeds.onTask(async ({ input, variables }) => {
const { baseToken, appToken, tableId, baseUrl } = variables;
if (!baseToken || !appToken || !tableId) {
throw new Error('所选常用配置缺少授权码、App Token 或 Table ID');
}
// 追加、覆盖、更新、去重和字段映射均由脚本决定。
return {
message: '多维表格更新成功',
links: baseUrl ? [{ title: '打开多维表格', url: baseUrl }] : [],
};
});
常用配置可以在自动表单和 JSON 模式之间切换。脚本与常用配置分别由用户手动同步;保存或编辑本身不会自动上传。
8. 手动、批量与定时任务
同一个 Tool 不需要为三种任务模式编写三套代码。
- 手动任务:执行一次表单或 JSON 输入。
- 批量任务:选定一个批量字段,多行值会拆成多个任务;其余字段作为每项任务的公共输入。
- 定时任务:保存 Tool、输入、常用配置选择和时间规则,到点后自动调用。
- 运行时可通过
source区分来源,但除非业务确实不同,不建议分叉核心逻辑。
脚本应保证重复执行的行为可预测。是否追加、覆盖、更新或去重必须由脚本根据业务要求明确实现,不要假设插件会代为处理。
9. 任务结果、报告和通知
脚本返回值可以同时包含结构化数据、摘要、链接和文件:
return {
message: '采集和写入完成',
data: { total: records.length, records },
links: [{ title: '打开结果表格', url: tableUrl }],
files: [
{ name: '结果.md', format: 'markdown', content: '# 结果' }
],
};
结果规则:
message用于任务摘要和通知文字。data是结构化结果,会进入任务报告和 MCPpublic_report。links是用户可打开的 HTTPS 链接。files是脚本主动返回的文件;链接和文件可以同时存在。- 有文件就发送文件,有链接就发送链接,两者都有就一起发送。
- 只有链接时,插件不会擅自生成报告文件。
- 没有
files不等于任务失败;报告形式由脚本结果和脚本声明共同决定。
大结果应主动精简。任务历史对超大数据可能只保留截断摘要;不要依赖任务历史保存无限量业务数据。
10. MCP 调用模型
MCP 业务 Tool 使用异步任务模型:
- AI 调用脚本 Tool。
- 服务返回
task_id。 - 浏览器插件领取并执行任务。
- AI 使用系统 Tool
get_report和task_id查询状态及结果。
因此 Tool 的描述和 Schema 必须足够清楚,让 AI 在不阅读源码的情况下判断是否应该调用、怎样填写参数以及会产生什么结果。
控制规则:
- 脚本安装后 MCP 默认关闭。
- 全局 MCP 开关和脚本级 MCP 开关必须同时开启。
- 脚本不能替用户开启 MCP。
- 停用脚本后,它的 Tool 会退出 MCP 清单。
- 脚本更新保留用户原来的 MCP 选择。
- MCP 来源任务不发送普通任务通知,结果由 MCP 客户端通过
get_report获取。
11. 权限和安全边界
@match和@connect应遵循最小范围原则,不要申请无关域名。- 安装或更新增加新域名时,必须由用户确认网站权限。
- 脚本只能读取用户主动为任务选择的那一项常用配置。
- 脚本拿不到插件精灵 License、服务端密钥或其他脚本的数据。
- 不得把 Cookie、Token、授权码或用户业务数据上传到声明用途之外的第三方。
- 不要把完整凭据写入源码、日志、异常信息、任务返回值或报告。
- 使用 MAIN 世界、
eval、new Function、Cookie、本地存储或页面跳转等能力会产生风险提示,应仅在确有必要时使用。 - 未登录、Cookie 失效、验证码、Robot Check、HTTP 401/403/429、超时和平台业务错误都必须真实报告,不得伪造成功。
12. 安装、更新和身份
- 脚本身份由稳定的
@namespace与@name共同确定;修改其中任意一个会被视为新脚本。 - 更新必须提高
@version,并保持脚本身份不变。 - 更新新增网站权限时,用户需要重新授权。
- 本地修改过源码的脚本不会被无提示覆盖。
- 卸载脚本后,运行器会回收不再被其他脚本使用的网站权限。
- 社区脚本安装前应让用户审阅源码、网站范围和风险提示。
13. 开发与测试清单
提交脚本前至少确认:
- 元数据块完整,
@sellerfeeds-tool和@sellerfeeds-variable均为单行 JSON。 @match、@connect和执行模式符合真实需求。- Tool 名称稳定、唯一,描述能让普通用户和 AI 判断使用场景。
- 所有输入字段都有准确类型、标题、说明、单位、范围或示例。
onTask校验必填项、跨字段规则、登录状态和业务响应码。- 正常结果、空结果、未登录、限流、验证码、超时和接口错误均经过测试。
- 批量和定时运行不依赖当前活动页面,或已正确提供
@sellerfeeds-entry-url。 - 没有在源码、日志和结果中泄露 Cookie 或常用配置。
- 返回字段来自真实网页或接口;缺失值不伪造为 0。
- 手动、批量、定时和 MCP 共用同一个稳定业务入口。
仓库开发时运行:
pnpm run verify
14. 如何把文档交给 AI
生成或修改脚本时,建议向 AI 同时提供:
- 本开发说明 Markdown:
https://www.sellerfeeds.com/docs/development.md - 实测知识库 Markdown:
https://www.sellerfeeds.com/docs/knowledge.md - 具体业务需求、目标网站、输入字段、预期输出和是否允许写入外部系统。
可以直接使用以下提示词:
请先完整阅读插件精灵脚本开发说明和知识库,再根据我的需求编写一个可安装的 .user.js。
必须遵守元数据、执行模式、常用配置、Tool Schema、MCP 描述、权限和结果契约。
对知识库没有确认的页面字段或接口行为,不要猜测,请明确列出需要我实测的信息。
我的需求是:……
知识库记录平台的实测事实;开发说明定义运行器契约。两份文档发生表述冲突时,以开发说明的运行器契约为准,以知识库中标注的最新实测结论解释目标平台行为。
