Como usar
- Copie o comando e verifique o pacote antes de instalar no seu ambiente de agente.
- Consulte no original as ferramentas, credenciais e ambientes necessários.
- Descreva os dados de entrada e a entrega esperada; confira a saída com as fontes.
npx skills add https://github.com/bilibili/toy --skill toyAntes de começar
- A instalação não inclui assinatura de modelo, franquia API ou acesso aos seus arquivos.
- Estrelas e instalações indicam atividade, não um teste independente de qualidade ou segurança.
Renderizado do repositório de origem, preservando títulos, exemplos, código, tabelas, links e imagens.
toy: Toy 平台创作者 CLI
通过 toy 二进制(cobra CLI,服务端 OAuth 登录)完成 Toy 平台的创作者侧操作:打包发布、更新、预览、查询、视频绑定。本 skill 不写命令矩阵 —— CLI 自描述足够,写死字段名只会与代码漂移。Skill 只承载工作流和铁律。
何时使用
用户提到把本地项目/HTML/zip 发布到 toy、更新已有 Toy、看自己的 Toy 列表或访问统计、把视频与 Toy 绑定或解绑、查发布记录等创作者场景。
不要用于:
- 老的脚本式发布链路 —— 本 skill 取代它,统一走官方
toy二进制。
前置条件
toy已安装。检测command -v toy,没装时引导安装(参见references/installation.md)。- 已登录。任意 API 命令首次跑可能报「登录态已失效,请执行
toy login」,按铁律 4 处理。 - 全局 flag 以
--help-json实际输出为准。
发现机制(关键)
不要凭记忆构造命令。第一次用某个子命令前,跑:
toy --help-json输出是结构化 JSON,包含全部命令树、位置参数、flag、writes 标记、choices 取值。需要单个子树时跑 toy <cmd> --help-json。
JSON 字段语义:
| 字段 | 用途 |
|---|---|
commands[].path | 命令路径数组,如 ["create"]、["history","clear"] |
commands[].args | 位置参数 {min, max, names, variadic} |
commands[].flags | 本层 flag 列表,每条含 type/default/choices/required |
commands[].writes | true 表示业务写操作(如 create/update) |
global_flags | 全局 flag(如 --json) |
缺功能时尝试升级
用户要的能力在 --help-json 里确实找不到(命令/flag 不存在,而非拼错或记错),可能是本地 toy 太旧、新功能还没到。这时可以升一次级(命令见 references/installation.md)再重查 --help-json。升级失败(dev 构建、未配置分发地址、离线)属正常,直接照现有能力回复用户"当前版本不支持",别卡住或反复重试。
铁律
按以下顺序优先级执行:
1. AI 调用一律 --json
不管读还是写,AI 调 toy 都加 --json。读命令(mylist/stats/history)的表格输出会因列宽/超链接渲染变化而崩;写命令的中文成功提示也不如结构化响应好解析。--json 是唯一稳定契约。
2. 发布/更新是「预览 → 确认 → 提交审核」两段式,不是一步到位
create / update(writes:true)带包体时,CLI 先上传打包、生成 preview_url,默认不提交审核。提交审核由 --yes 触发,是真正的确认闸门(client 侧没有 risk 注解,预览即闸门)。
AI 的正确姿势:
- 先不加 `--yes` 跑(带
--json)。CLI 只回{"preview_url": "..."},不提交。 - 把
preview_url原样给用户,让用户在浏览器里检查。 - 主动发起一次显式确认(AskUserQuestion 或等价的明确询问),别只被动说「看完告诉我」。把「即将提交审核」+ 改动摘要(目标 Toy 的
id/title/slug、这次改了什么、slug 保持不变)一起摆出来,请用户明确回「提交 / 不提交」。只有拿到明确肯定答复,才用同样的参数重跑并加 `--yes`。 用户没回、回得含糊(如「嗯」「好」不指向提交动作)或说要再改,都不加--yes。 - 提交成功后
--json会返回{id, status, preview_url},把id/status给用户。
铁律细节:
- 非交互场景(AI 调用)下,
--json不带--yes= 只预览不提交;带--yes= 直接提交。绝不在用户看过预览并明确确认前加 `--yes`。给出预览后要主动问一次「是否提交审核」,而不是被动等用户开口——弱提示(「看完告诉我」)容易让用户以为已经在走审核。 - 纯改元信息(
update不带 path)没有预览链接,是直接提交审核。这种也要先 AskUserQuestion 告知「即将提交审核:<改动摘要>」再加--yes。 --visibility password必须配--access-password(4-32 字符);只传--access-password会按 password 档处理。具体取值/约束以--help-json的choices为准。
3. 带包体发布前先过内容自检
toy 只打包上传,本地不校验包内容(提交时只有少数几条硬限制会拦,如入口 index.html 体积,见下)。toy 页面跑在 /toy/<slug>/ 子路径下,绝对路径资源、根绝对跳转等会让页面白屏 / 404 / 链接错乱——包能传、审核可能也过,但打开是坏的。(注:页内锚点 href="#section" 现已支持,不再是坑,见 references/content-checklist.md §2。)
create / update 带 path 前,按 references/content-checklist.md 对 <path> 做内容预检:优先用清单里提供的自动化预检手段,跑不了再照清单 §1–§6 人肉过一遍高频坑(绝对路径、hash 路由 vs history 路由、构建产物 vs 源码、封面、slug 不可改)。有 ERROR 先给用户、修完再传,别硬传;有 WARN 也要逐条说给用户听(WARN 不改退出码、汇总行照样写 passed,跳过就等于没查)。
HTML 文档体积有两条线,severity 不同,别混(详见清单 §8):
- 入口 index.html 解压后超 1MB → ERROR,发不出去。 create / update / preview 都会拒,报
307000。doctor 报entry index.html is N MB ... over the 1 MB limit就是这条:必须改完再传,硬传只会拿到报错。只管入口那一个文件(包根的index.html,或唯一一级子目录下的那个;单个 HTML 直传时它本身就是入口),算的是解压后体积——压缩得再狠也没用。 - 任何 HTML 文档 ≥12MB → WARN,不拦发布。 doctor 报
HTML document is N MB,是加载体验问题(文档不能被缓存,每次访问都要等整份下完)。照常把 WARN 说给用户,别卡流程。
两条的处方是同一套,都要告诉用户具体怎么操作(上传 Toy 的开发者多半不是专业人员,「改成外部资源」这种说法对他们等于没说)。两条消息里都会说清是哪种形态 —— 「N chunks」是打包器选项选错了(换导出格式),「one inline block」是项目自己的代码(把数据挪成外部文件),两种处方不同,照 §8 对应那一节念步骤。两种都不要自己去剪那几十 MB。
产物文件名不带内容指纹(contenthash)时,toy_doctor.py 会报一条 WARN。这条只是建议:不带指纹照样能发、能访问,只是每次更新都让访客重新下载全部资源。提一句就够,别拿它卡流程,也别替用户改构建配置(多数工具默认已开,Vite 开箱即用)。详见清单 §3.5。
包里用了 云存储 / 排行榜 SDK 能力时,再过一遍清单 §7 的调用节奏。这类和上面几条性质不同:发布时一切正常,玩家一多才爆(按 Toy 共享额度,超限 reject 307044),预览页看不出来。只报 WARN,不阻断发布 —— 给用户提一句即可,别拿它卡流程。阈值不对外公开且线上可调,不要向用户报具体数字,也不要建议写死数字做本地节流。
详见 references/content-checklist.md(§1–§6 已用官方 FAQ 校准或对着 CLI 源码核过,§7 与官方 SDK 文档「频率限制与最佳实践」同源,§8.1 的 1MB 上限是平台提交时的实际限制、有可能调整,§8.2 出自线上加载耗时实测,官方 FAQ 暂未收录)。
4. 登录态失效是「重新 login」
错误信息含「登录态已失效」「请执行 toy login」或 envelope code 为会话失效码时:
toy logintoy login 会走浏览器 OAuth(会自动开浏览器,--no-open 可关)。登录后重试原命令一次。仍失败则停下报告用户,不要循环。详见 references/error-codes.md。
5. 破坏性本地操作要确认
history clear 会删除本机全部发布记录(仅本地流水,不影响线上 Toy)。它带 --yes 跳过确认。AI 要执行时必须先 AskUserQuestion 确认,再加 --yes。其余只读命令(mylist/stats/whoami/history 查看)直接跑。
6. 视频绑定是即时生效,不走预览/审核
video bind / video unbind 改的是绑定关系(绑定后视频页挂上该 Toy 入口),调用即生效:无预览、不产出版本、不进审核、没有 --yes。别套铁律 2 的两段式。
几条 --help-json 里读不出来的约束:
- 一个视频只能绑一个 Toy(反之一个 Toy 可绑多个)。撞上「该视频已绑定其他作品」时讲清冲突、让用户决定,别自己去别的 Toy 上解绑。
- 重复绑定、解绑不存在的绑定都幂等,不报错。不用先查后写。
video mine只返回已过审稿件 —— 找不到某个视频先看它过审了没。bind/unbind的--json只回显你传的那个标识,另一个为空是设计行为。- 解绑非破坏性(可以再绑回来),不必按铁律 5 确认;但解绑用户没点名的绑定关系要先问。
典型工作流
工作流只锚定命令名 + 业务步骤,具体参数 / flag / 取值都用 --help-json 取,避免与 CLI 漂移。
A. 首次发布一个本地项目
- 确认登录态(必要时
toy login)。 - 内容预检:按铁律 3 对
<path>做内容预检(参考references/content-checklist.md),有 ERROR 先修;有 WARN 要逐条说给用户听再往下走 —— WARN 不改退出码(仍是 0),汇总行照样写passed,不说出口就等于没查。 - 跑
create <path>(带--json,不带 `--yes`),<path>可以是目录 / 单个 HTML / 现成 zip。元信息 flag(名称、slug、封面、图标、分类、可见性等)以 `create --help-json` 的当前输出为准,别照记忆列 —— 这几项会随版本增删。不传名称 / slug 时会从路径名推导。 - 拿到
preview_url,原样给用户,请用户在浏览器检查。 - 按铁律 2 主动发起显式确认(摆出改动摘要、请用户明确回「提交」),拿到肯定答复后再 同参数 + `--yes` 重跑,提交审核。
- 解析返回的
id/status给用户。
B. 更新已有 Toy
- 需要先知道 id:跑
mylist(带--json)列出我的 Toy,从中选出目标id。 - 带包体更新:先按铁律 3 对
<path>做内容预检,再update <id> <path>(不带--yes)→ 拿preview_url→ 按铁律 2 主动发起显式确认 → 拿到肯定答复后同参数 +--yes提交。保留原 slug,别为改地址走删除-重建(slug 发布后不可改)。 - 只改元信息(不带 path,无预览链接、直接提交):可改哪些项看
update --help-json,按铁律 2 先告知再加--yes。 - 改密码档:
--visibility password --access-password ...;给现有密码档改密只传--access-password。具体看--help-json。
C. 查看我的 Toy 与统计
mylist(带--json,可--page/--size)看列表与可见性。- 单 Toy 统计
stats <id>,默认近 7 天(截至昨天,当天未结算);区间用--days N或--start/--end(YYYY-MM-DD,最长 90 天),具体看--help-json。脚本/JSON 务必显式传id(不传会进交互选择,AI 环境会失败)。
D. 用发布记录推断「新发布 vs 更新」
用户给一个本地路径说「发布到 toy」时,往往没说清是首发还是更新。先查发布记录消歧,别上来就 create:
- 跑
history <path>(带--json)查这个目录/文件过去有没有发过。记录按登录账号隔离,存的是历次成功create/update的快照(含id/title/源路径等)。 - 判断:
- 查到记录(有对应
id)→ 大概率是更新。用mylist核对该id仍存在,然后走工作流 B(update <id> <path>)。先跟用户确认是更新这条而不是新发。 - 没查到记录 → 可能是首发,也可能是换了机器/换了账号/换了路径发过。别只凭本地记录拍板:可跑
mylist看线上有没有同名/同 slug 的 Toy,再跟用户确认走create(工作流 A)还是update(工作流 B)。
- 旧 `toy.yaml` 只当只读补充线索(老发布链路的遗留物,不是本 skill 维护的文件)。
history查不到、又想再确认时,可以读目录里的toy.yaml,取其中的id/slug/title当作推测线索——但必须用mylist --json核对该id在当前账号下仍存在,别直接拿来当事实。它可能过期、可能指向别人的项目。不要凭里面的owner_mid/uid判断账号。 history和toy.yaml都只是本机线索(不影响线上、可能不全/过期),不是事实源。线上真实状态以mylist为准;拿不准就让用户选。
清空记录用 history clear(破坏性,按铁律 5 确认后 --yes)。
E. 把视频绑定到 Toy
绑定后视频页会挂上这个 Toy 的入口。只能拿自己的视频绑自己的 Toy,归属由服务端校验。
- 定 Toy:用户没指明就跑
mylist让用户确认是哪个。 - 定视频:用户给了视频标识直接用(BV 号或 av 号都收,纯数字按 av 号走);没有就跑
video mine列候选给用户选(只有已过审稿件会出现)。 - 看现状(推荐):
video list看这个 Toy 已绑了什么,顺带发现用户其实想换绑。 - 绑定:
video bind提交,即时生效、无预览无审核。解绑走video unbind。 - 撞上「该视频已绑定其他作品」→ 按铁律 6,讲清冲突让用户决定,别自己去解绑。
脚本/JSON 务必显式传 Toy id(不传会进交互选择,AI 环境会失败);各命令收 id 的入口形态不同,以 --help-json 为准。
错误处理优先级
- 登录态失效(「登录态已失效」/ 会话失效 code)→
toy login,重试一次,不循环。 - 业务错误(envelope
code != 0的 message)→ 直接把 message 给用户,不要二次解释。 - 非交互环境报「需要加 --yes」类提示 → 说明这是预览/提交闸门,按铁律 2 走预览-确认流程,不要无脑加
--yes绕过。 - flag/参数错误(cobra 报
unknown flag/accepts N arg(s))→ 重新跑--help-json对齐参数形态。
不要做的事
- 不要解析人类 help 文本(
toy -h给用户看,AI 用--help-json)。 - 不要凭记忆构造 flag(命令可能升级、也可能因构建渠道而不同,每次都验)。
- 不要在用户看过预览并明确确认前给
create/update加--yes;也不要被动等用户开口,要按铁律 2 主动问一次「是否提交审核」。 - 不要跳过内容预检就发包(绝对路径/根绝对跳转坑会让页面打开是坏的);页内锚点
href="#section"现已支持、不再报错,别再当成坑(见references/content-checklist.md第 2 节)。 - 不要为改 slug 走「删除-重建」,除非用户明确要换地址(slug 发布后不可改,更新时保留)。
- 不要自己去剪 HTML 里的大内联块(几十 MB 逐字节重写不可能保真,坏了还是静默的)。要改的是产出这份 HTML 的那一步 —— 导出选项或构建脚本,具体步骤照清单 §8 给用户念,别只说一句「改成外部资源」。
- 入口 index.html 超 1MB(doctor 报 ERROR)时不要硬传,也不要指望「先出个预览看看」—— preview 同样拦。先按清单 §8 改产出方式,或如实告诉用户这个包当前发不出去。
- 不要默认创建/写入/维护
toy.yaml(本 skill 走官方 CLI 本地记录,toy.yaml只做只读兼容);也别把toy.yaml打进上传包。 - 不要循环重试登录态失效;不要把 session token 写进任何输出。
- 不要对
history clear这类破坏性命令未经确认就加--yes。 - 不要为绑定视频擅自解绑用户其他 Toy 上的绑定。
