S3 Upload
通过 scripts/s3-cli.js 操作 S3 兼容存储(七牛 Kodo、MinIO、AWS S3 等)。配置来自环境变量,与 src/app-agent/lib/server/s3-storage.ts 及 .env-template 一致。
Agent 工作流
- 先检查配置 — 未配置时不要猜测密钥,提示用户补全
.env:node --env-file-if-exists=.env .cursor/skills/s3-upload/scripts/s3-cli.js config - 选命令 — 上传用
upload;浏览用list;按名称搜用find;取公网链用url。 - 优先
--json— 需要解析结果给后续步骤时用 JSON 输出。 - 从仓库根目录执行 — 依赖根目录
node_modules中的@aws-sdk/client-s3。 - 删除需
--yes— 避免误删;向用户确认后再删。 - 失败时必须给出正确反馈 — 见下方「错误处理」;不要编造 URL 或假装上传成功。
错误处理(Agent 必遵)
CLI 失败时 exit code = 1。加 --json 时 stdout 为结构化 JSON(含 code、error、hint),Agent 必须解析后再回复用户。
回复用户格式
失败时按此结构告知用户(用中文,不要只贴原始 stack):
- 发生了什么 — 引用
error字段 - 可能原因 — 结合
code与上下文 - 下一步 — 引用
hint;若可自动修复(如--no-acl),先尝试再汇报
禁止: 忽略 exit code;把 stderr 当成功;未验证就回复公网 URL;向用户展示完整 Secret Key。
错误码对照
code |
含义 | Agent 动作 |
|---|---|---|
CONFIG_MISSING |
缺环境变量 | 列出 missing,指向 .env-template,请用户补全后重跑 config |
INVALID_CREDENTIALS |
密钥错误 | 请用户核对 AK/SK,不要重复用同一错误密钥盲试 |
ACCESS_DENIED |
无权限 | 说明权限不足;upload 时若 hint 提到 --no-acl,自动重试一次 |
ACL_NOT_SUPPORTED |
不支持 ACL | 用 --no-acl 重试 upload |
BUCKET_NOT_FOUND |
桶不存在 | 检查 S3_BUCKET_NAME 与 S3_ENDPOINT 是否匹配 |
OBJECT_NOT_FOUND |
对象不存在 | 建议 list --prefix / find 查正确 key |
LOCAL_FILE_NOT_FOUND |
本地文件不存在 | 检查路径、cwd 是否在仓库根目录 |
DELETE_REQUIRES_CONFIRM |
未加 --yes |
向用户确认后再加 --yes |
USAGE_ERROR |
参数缺失 | 按 hint 修正命令,不要猜参数 |
NETWORK_ERROR |
网络/端点不可达 | 检查 endpoint、region、代理 |
DEPENDENCY_MISSING |
缺 SDK | 在仓库根目录 bun install 后重试 |
S3_ERROR |
其他 S3 错误 | 汇报 error + details/httpStatus,建议跑 config |
诊断流程
命令失败 (exit 1)
├─ 加 --json 重跑,读取 code
├─ CONFIG_* / INVALID_CREDENTIALS → config
├─ OBJECT_NOT_FOUND → list/find 定位 key
├─ ACCESS_DENIED + upload → 试 --no-acl
└─ 仍失败 → 原样汇报 error/hint/details,不要擅自改密钥
示例:向用户反馈
配置缺失:
S3 未配置完整,缺少
S3_SECRET_ACCESS_KEY。请在项目根目录.env中补全(参考.env-template),保存后我再验证。
上传 ACL 失败(Agent 应先重试):
存储不支持 ACL,已改用
--no-acl重新上传并成功。公网 URL: …
对象不存在:
桶内没有
assets/demo/missing.png。当前assets/demo/下共有 3 个文件:…
快速开始
node --env-file-if-exists=.env .cursor/skills/s3-upload/scripts/s3-cli.js --help
node --env-file-if-exists=.env .cursor/skills/s3-upload/scripts/s3-cli.js config
上传并拿到公网 URL:
node --env-file-if-exists=.env .cursor/skills/s3-upload/scripts/s3-cli.js upload ./local.png --prefix assets/demo/
列出 / 查找:
node --env-file-if-exists=.env .cursor/skills/s3-upload/scripts/s3-cli.js list --prefix uploads/ --max 50
node --env-file-if-exists=.env .cursor/skills/s3-upload/scripts/s3-cli.js find "photo" --prefix assets/
node --env-file-if-exists=.env .cursor/skills/s3-upload/scripts/s3-cli.js find "*.png" --prefix assets/
下载 / 删除 / URL:
node --env-file-if-exists=.env .cursor/skills/s3-upload/scripts/s3-cli.js download assets/demo/photo.png --output ./photo.png
node --env-file-if-exists=.env .cursor/skills/s3-upload/scripts/s3-cli.js url assets/demo/photo.png
node --env-file-if-exists=.env .cursor/skills/s3-upload/scripts/s3-cli.js delete assets/demo/old.png --yes
环境变量
| 变量 | 必填 | 说明 |
|---|---|---|
S3_BUCKET_NAME |
是 | 存储桶 |
S3_ACCESS_KEY_ID |
是 | Access Key |
S3_SECRET_ACCESS_KEY |
是 | Secret Key |
S3_ENDPOINT |
是 | 服务端点(如 https://s3.cn-south-1.qiniucs.com) |
S3_REGION |
否 | 默认 cn-south-1(七牛);阿里云填 cn-hangzhou 等 |
S3_CDN |
否 | CDN 域名;url / 上传结果优先用 CDN 拼公网 URL |
S3_PROVIDER |
否 | 提供商标识(kodo / aliyun / minio 等);aliyun 时 upload 默认不带 ACL |
CLI 会自动读取仓库根目录 .env(不覆盖已有 process.env)。也可显式传 node --env-file-if-exists=.env。
禁止 把密钥写入 skill、脚本或提交到 git。只读 .env 或用户提供的 env。
阿里云 OSS(S3_PROVIDER=aliyun)
S3_BUCKET_NAME=<bucket>
S3_ACCESS_KEY_ID=<RAM AccessKey ID>
S3_SECRET_ACCESS_KEY=<RAM AccessKey Secret>
S3_ENDPOINT=https://<bucket>.s3.oss-<region>.aliyuncs.com
S3_REGION=cn-hangzhou
S3_CDN=https://<your-cdn-domain>
S3_PROVIDER=aliyun
要点:
- Endpoint — 推荐 S3 兼容格式:
https://<bucket>.s3.oss-cn-hangzhou.aliyuncs.com(与S3_BUCKET_NAME一致);亦可用https://s3.oss-cn-hangzhou.aliyuncs.com(path-style)。CLI 会自动识别 endpoint 是否已含 bucket 子域。 - Region — 与 endpoint 中的地域一致(如
cn-hangzhou),不要用占位符<your-region>。 - ACL — 新版 OSS 桶通常禁用 Object ACL;CLI 在
aliyun下 默认不上传 ACL。若仍报 ACL 错,显式加--no-acl。 - 公网 URL — 配置了
S3_CDN时:https://cdn.example.com/<objectKey>;需确保 CDN 已绑定该桶并开启回源。 - RAM 权限 — 密钥需有目标桶的
oss:PutObject、oss:GetObject、oss:ListObjects、oss:DeleteObject等。
命令参考
| 命令 | 用途 |
|---|---|
config |
验证配置,密钥脱敏输出 |
upload <file> |
上传;--key / --prefix / --content-type / --acl / --no-acl |
list |
按 --prefix 列出;--max 限制条数 |
find <pattern> |
key 子串或 * ? 通配;配合 --prefix |
head <key> |
是否存在及元数据 |
download <key> |
下载;--output 指定路径 |
delete <key> --yes |
删除对象 |
url <key> |
输出公网 URL |
全局:--json、-h / --help。
与应用代码的关系
- 服务端上传逻辑见
src/app-agent/lib/server/s3-storage.ts(Presigned POST、CDN URL 解析等)。 - Agent 运维/一次性上传 用本 skill 的 CLI,不要在对话里重写 SDK 逻辑。
- 应用内功能 继续用
s3-storage.ts或现有 OSS 管道,不要混用 CLI。
常见场景
用户要上传截图/构建产物并分享链接
node --env-file-if-exists=.env .cursor/skills/s3-upload/scripts/s3-cli.js upload ./dist/bundle.zip --key releases/v1.2.0/bundle.zip --json
从 JSON 取 publicUrl 回复用户。
用户问某前缀下有哪些文件
node --env-file-if-exists=.env .cursor/skills/s3-upload/scripts/s3-cli.js list --prefix static/_next/ --max 100 --json
用户给了 CDN URL,要确认 key 是否存在
用 objectKeyFromPublicUrl 的逻辑:去掉 CDN 前缀得 key,再 head。
配置报错
缺少必填 env → CLI 返回 CONFIG_MISSING 及 missing 数组 → 对照 .env-template 请用户补全 → 重跑 config 直到 ok: true。
CLI 返回 JSON 错误示例
{
"ok": false,
"code": "ACL_NOT_SUPPORTED",
"error": "当前存储不支持 ACL 字段",
"hint": "重试: upload <file> ... --no-acl",
"details": "…"
}
Agent 应执行 hint 中的重试,成功后再回复用户。
.env 中勿重复定义 S3_*
同一文件内出现多组 S3_BUCKET_NAME 等变量时,后出现的会覆盖先前的(Node --env-file 行为)。只保留一组配置,旧配置注释掉。