SKILL.md 5.4 KB


name: fmode-storage description: "把二进制大文件(图片/音频/视频/HTML 报告)上传到对象存储并拿到公开分享链接,本地零长期占用。默认通道免配置密钥:只要有登录 sessionToken,平台云函数就签发上传地址(对象键 user/<你的id>/...,公网 https://s3.fmode.cn/)。适用:(1) 报告/课件发布即分享 (2) 图片/音视频素材托管 (3) 批量上传+公开读 (4) 需要公开 URL 供转发或嵌入。" description_en: "Upload binary files (images/audio/video/HTML reports) to object storage and get public share URLs, keeping local disk clean. The default channel needs no credentials: with a login sessionToken the platform cloud function issues an upload URL (object key user//..., public https://s3.fmode.cn/). Use for publishing reports/courseware, hosting media assets, batch upload with public-read, or any scenario needing public URLs." schema_version: 0.2.0 level: system category: publishing keywords:

  • storage
  • obs
  • s3
  • upload
  • cdn
  • share-link version: 1.1.0 author: Yuyang001 (FmodeAgent) license: MIT copyright: "Copyright (c) 2026 未来飞马 Fmode" tags: [未来飞马, 智能体技能, 超级技能, 服务级, 数据管理, FmodeAgent, FmodeCode, storage, obs, s3, cdn, upload] ---

Fmode Storage — 对象存储与公开分享

Overview

把本地二进制文件交给对象存储,生成公开 URL 供分享、转发或嵌入。

设计原则:本地零长期占用公开即所得凭据零入库——密钥永不落盘、永不进日志、永不进对话;诚实失败——通道全失败时打印初始化向导并 exit 2,绝不伪装成功。

首选用法(免配置,0 步)

不需要申请 AK/SK、不需要 init。只要容器里有登录态 sessionToken(数字生命容器默认就有),直接:

node <skill_dir>/scripts/uploader.mjs put ./report.html --key report/202609/report.html
# → { "ok": true, "key": "user/<你的id>/report/202609/report.html",
#     "url": "https://s3.fmode.cn/user/<你的id>/report/202609/report.html",
#     "via": "level0:cloudfunc(AlP56LCKFm)" }

自检(验证这条通道是否可用):

node <skill_dir>/scripts/uploader.mjs test
# → { "ok": true, "via": "level0:cloudfunc(...)", "message": "云函数免密钥通道自检成功(本机无需任何 AK/SK)" }

--key 给相对路径即可,脚本/云函数会强制挂到 user/<你的id>/ 前缀下——写不进别人的前缀。 省略 --key 则自动生成 user/<你的id>/report/<YYYYMM>/<uuid>-<文件名>。 上传即 public-read不需要再调 setacl

凭据链(5 级,命中即用)

┌─ 第0级【首选·免密钥】sessionToken → 云函数 fmodeagent-upload-url 签发预签名 PUT
│    → AK/SK 由云函数保管,容器只拿 5 分钟有效的上传地址。无需任何本地配置。
│  第1级 环境变量 OBS_AK/OBS_SK(/OBS_ENDPOINT/OBS_BUCKET)
│  第2级 obsutil config(OBSUTIL_CONFIG 或 ~/.obsutilconfig)
│  第3级 sessionToken + storageProjectId → POST /api/apig/deploy/huaweicloud
│    (项目级 STS,作用域 obs://nova-cloud/dev/<projectId>/,非个人空间)
│  第4级 项目级 ./.fmode/config.json(obsBucket/obsEndpoint/cdnDomain)
│  全失败 → 打印初始化向导并 exit 2
└──────────────────────────────────────────────────────────────────────────┘

为什么第 0 级是首选:第 1/2 级要每台容器各自配 OBS 密钥、第 3 级要 storageProjectId 且作用域是项目目录、第 4 级只有 bucket 名没有凭据——都无法做到"开箱即用"。第 0 级只依赖登录态,是唯一零配置通道。

第 1–4 级作为兜底保留(例如需要写 obs://www-fmode.cn/ 之类平台桶,而不是个人空间)。

何时用

  • 生成了 HTML 报告/课件要"发给别人看" → put 后把 URL 发出
  • 图片/音频/视频素材需要稳定外链 → put
  • 本地磁盘被大文件占满 → put 完成后可删本地原件

命令

node uploader.mjs test                        # 自检(优先走第0级)
node uploader.mjs put <file> --key <相对key>  # 上传并返回公开 URL
node uploader.mjs put <file>                  # 省略 --key:自动命名
node uploader.mjs put <file> --key k --ns report
node uploader.mjs setacl --key <key>          # 第0级下上传即 public-read,无需调用
node uploader.mjs config                      # 诊断(输出绝不含密钥本体)
node uploader.mjs init --ak .. --sk ..        # 仅第1/2级兜底场景需要

需要完整 SDK 时

import { putViaCloudFunction } from './scripts/uploader.mjs';
const r = await putViaCloudFunction('/path/report.html', 'report/202609/report.html', 'report');
// r = { ok, key, url, bytes, via }

详细文档

见仓库根 README.md(多工具安装:Claude Code / Codex / Gemini CLI / WorkBuddy / Hermes + 完整 changelog)。

铁律

  • ⛔ 绝不把 AK/SK、sessionToken、STS 或任何密钥写进仓库、日志、对话
  • ⛔ 绝不尝试从 git 仓库/代码/文档/聊天记录中寻找他人或公司凭证
  • ✅ 对象只能写自己 user/<自己的id>/ 前缀(云函数在服务端强制)