pwa-save-article · 调用发文 API 保存文章
把一篇文章通过 PlayWithAI 资源站的 create-article API 保存进去。完整接口规范见项目根目录
CREATE_ARTICLE_API.md;本 skill 只保留执行所需的最小规则。
执行顺序固定为:① 前置检查 → ② 构造参数 → ③ 脚本调用 → ④ 反馈结果。
任何一步遇到本文件标注「必须澄清」的情况,立即停下来用 ask_user_question 向用户提问,不要猜测、不要编造默认值继续执行。
① 前置检查
依次确认,任何一项失败即停下:
- 调用脚本存在:
.agents/skills/pwa-save-article/scripts/save_article.mjs(相对项目根目录)。缺失则报告并停止,不要临时用 curl 代替。 - API 密钥可用(按顺序查找第一处即可):
- 环境变量
PWAI_API_KEY; - 项目
.env中的PWAI_API_KEY=。 - 密钥格式必须为
pwai_+ 64 位十六进制。 - 找不到或格式不对 → 必须澄清:告知用户到管理后台
/admin → API 密钥创建(明文只显示一次),请其提供密钥或确认已写入.env。不要让用户把密钥粘贴到公开场合之外的地方。
- 环境变量
- 接口地址:默认
https://zhjrfpuoiblhbstcpkcz.supabase.co/functions/v1/create-article,可被PWAI_CREATE_ARTICLE_URL(环境变量或.env)覆盖。脚本已内置此逻辑,无需手工拼接。 - 网络可达由脚本执行时验证,前置阶段不单独探测。
② 根据上下文构造参数
从用户消息、会话上下文、或用户指定的文件内容中提取以下字段,组装成一个 JSON 对象(保存为临时文件,如 payload.json)。字段约束(与服务端一致,脚本会本地预校验):
| 字段 | 必填 | 规则 |
|---|---|---|
kind |
✅ | original / open-source / tech / practice |
title |
✅ | 3–160 字符 |
excerpt |
✅ | 12–360 字符(别名 description) |
contentMd |
三选一* | ≤ 30000 字符 Markdown(别名 content) |
githubUrl |
三选一* | http(s) URL,仅 open-source 入库 |
externalUrl |
三选一* | http(s) URL |
coverUrl |
可选 | http(s) URL,留空用默认封面 |
author |
可选 | ≤ 60 字符 |
tags |
可选 | ≤ 8 个 slug,^[a-z0-9-]+$;目录中不存在的标签会被忽略 |
status |
可选 | draft(默认)/ published |
* contentMd、githubUrl、externalUrl 至少一项非空。
构造时的判定规则:
kind:按内容性质推断(原创心得→original;介绍某个开源项目→open-source;技术讲解→tech;实操复盘/案例→practice)。推断没有把握时 → 必须澄清,列出四个栏目让用户选。status:用户明确说"发布/上线/published"才用published;明确说"草稿/draft"用draft;未表态 → 必须澄清(说明:draft 仅后台可见,published 会立即出现在前台)。excerpt:上下文没有现成摘要时,可基于正文提炼一段 12–360 字符的摘要,并在参数摘要中展示给用户。tags:只从用户明确给出的标签生成 slug(中文标签转拼音或询问用户对应 slug);不要自行发明标签。用户给了标签但拿不准 slug 写法 → 必须澄清。- 正文较长时优先读取用户指定的文件作为
contentMd;截断或改写正文前必须征得同意。
调用脚本前,先向用户展示参数摘要(标题、栏目、标签、status、正文字数),确认无误再执行——除非用户已明确表示直接保存。
③ 执行脚本调用 API
node .agents/skills/pwa-save-article/scripts/save_article.mjs --file <payload.json>
- 先用
--dry-run可只做本地校验不发送(调试参数问题时先 dry-run)。 - 其他参数:
--key <pwai_…>(临时密钥)、--url <endpoint>、--stdin(从管道读 JSON)、--timeout <ms>。 - 退出码:
0成功;2前置检查失败(密钥/地址);3本地参数校验失败;4API 4xx;5网络/5xx。 - 脚本输出人类可读摘要 + 原始 JSON,直接引用其输出,不要自己二次解析猜测。
④ 反馈结果
成功(201):向用户报告——
- 标题、栏目
kind、状态status、生成的slug; tagsApplied已生效的标签;若tagsIgnored非空,明确提醒哪些标签因不在标签目录中未生效;status=published时给出前台路径/{kind}/{slug}(如/tech/<slug>);draft则说明需在管理后台查看。
失败:按退出码/HTTP 状态解释原因并给出下一步:
| 状态 | 含义 | 建议动作 |
|---|---|---|
400 |
参数校验失败(响应含 details) |
逐条修正 payload 后重试 |
401 |
密钥无效/已删除 | 回到前置检查,请用户确认或重建密钥 |
413 |
请求体 > 1 MB | 压缩或精简正文 |
429 |
限流(约 30 次/分钟) | 等待约 1 分钟再重试 |
5xx/网络错误 |
服务端或网络问题 | 如实告知,不要自动重试写操作;询问用户是否重试 |
任何失败都不得静默吞掉,也不得在未告知用户的情况下反复重试(接口不做去重,盲目重试会产生重复文章)。
必须澄清的场景汇总
满足任一条件时,停止执行并向用户提问:
- 找不到 API 密钥,或密钥格式不符合
pwai_<64 hex>; kind栏目无法从上下文可靠推断;status未明确(发布 or 草稿)且上下文无暗示;- 标签存在但 slug 写法拿不准;
- 需要截断、改写用户正文,或正文来源有歧义;
- 同一篇内容疑似已提交过,无法确认是否重复保存。