Fecify Skill 基础功能层
这些功能一般不被 Agent 直接调用,而是作为基础设施被上层业务脚本和 API 模块间接引用。
路径前缀:
fecify_skills/
目录
概述
基础功能层是 skill 的地基,共 14 个文件,分为 4 组:
| 分组 | 文件数 | 职责 |
|---|---|---|
| 配置管理 | 4 | 站点 URL/Token 绑定、init 数据拉取、多会话隔离 |
| API 通信 | 3 | HTTP 请求封装、CLI 代理、Schema 参数查询 |
| 图片上传 | 1 | 本地图片 → Fecify 服务器 |
| AI 生图 | 6 | 文生图引擎(Provider + client + prompt 增强 + CLI) |
所有这些文件都不接受用户的直接指令驱动,而是被以下上层调用:
- Agent CLI 调用:
SKILL.md第 2 节 →api-call.js→api-client.js→site-config.js - 业务脚本:
batch-collection.js、create.js、batch-upload.js等 →api-client.js+image-client.js+upload-local.js - 翻译脚本:
translate-*.js→api-client.js+site-config.js
1. 配置管理
1.1 scripts/base/site-config.js — 配置读写模块
被谁引用:api-client.js、check-config.js、save-config.js、reload-init.js、upload-local.js、image-client.js、config.js
职责:管理多店铺会话配置的持久化存储。不直接给 Agent 调用,作为 Node.js 模块被其他脚本 require()。
存储位置:
%APPDATA%/LobsterAI/data/fecify-shared/sessions/
├── current_<sessionId>.txt # 当前会话绑定的域名(每会话独立)
└── <domain>/
├── config.json # { url, token, updatedAt }
└── init-data.json # { data: { addons[], shop_type, ... }, updatedAt }
导出函数:
| 函数 | 返回 | 说明 |
|---|---|---|
getCurrentConfig() |
{ url, token } |
当前会话的 API 配置 |
isConfigured() |
boolean |
当前会话是否已配置 URL+Token |
getCurrentInitData() |
{ data: { addons[], ... } } |
当前会话的 init 数据 |
hasInitData() |
boolean |
是否已有 init 数据 |
getDomain() |
string |
当前会话绑定的域名 |
setDomain(domain) |
— | 绑定域名到当前会话 |
saveConfig(domain, url, token) |
— | 保存配置 + 绑定 |
saveInitData(domain, data) |
— | 保存 init 数据 |
getConfig(domain) |
— | 跨会话读配置 |
getInitData(domain) |
— | 跨会话读 init |
isDomainConfigured(domain) |
— | 指定域名是否已配置 |
会话隔离原理:
- 通过环境变量
FECIFY_SESSION区分不同店铺 - 未设置 → 用
current_default.txt - 设置了
FECIFY_SESSION=agent-a→ 用current_agent-a.txt - 每个会话文件独立,互不干扰
作为模块引用示例:
const { getCurrentConfig, isConfigured } = require('../base/site-config');
const cfg = getCurrentConfig(); // → { url: 'https://...', token: '...' }
1.2 scripts/base/check-config.js — 配置状态检查
谁调用:Agent 会话启动时通过 SKILL.md 第 1 节间接调用
职责:输出当前会话的配置状态 + skill 版本号,JSON 格式。Agent 根据结果决定是否需要引导用户提交 URL+Token。
node scripts/base/check-config.js
输出:
// 已配置:
{ "version": "2", "configured": true, "domain": "shop.example.com", "url": "https://...", "token": "abc123...", "hasInitData": true }
// 未配置:
{ "version": "2", "configured": false, "domain": null, "message": "站点未配置,需要提示用户提交 URL 和 Token" }
1.3 scripts/base/save-config.js — 配置保存
谁调用:Agent 收到用户 URL+Token 后,通过 SKILL.md 第 1 节间接调用
职责:保存 URL+Token → 自动调 /api/skill/base/init 拉取站点信息 → 存档。一步完成站点绑定和数据初始化。
node scripts/base/save-config.js "<URL>" "<Token>"
内部流程:
- 解析 URL 提取域名
- 调用
site-config.saveConfig()保存 URL+Token - 自动发 GET 请求到
/api/skill/base/init - 成功后调
site-config.saveInitData()存init-data.json - 输出完整结果(店铺名/类型/插件列表/init 字段)
1.4 scripts/base/reload-init.js — Init 数据重载
谁调用:Agent 在插件变更后,通过 SKILL.md 第 1 节间接调用
职责:重新调 /api/skill/base/init 覆盖本地的 init-data.json。用于安装/卸载插件后刷新本地缓存,使插件校验等信息保持同步。
node scripts/base/reload-init.js
无需参数,自动读取当前会话的 URL+Token。
2. API 通信层
2.1 scripts/base/api-client.js — HTTP 客户端
被谁引用:所有业务脚本(api-call.js、batch-collection.js、translate-*.js 等)
职责:封装 HTTP 请求,是 skill 中唯一直接发出网络请求的模块。所有 API 调用必须经过它。
导出函数:
| 函数 | 说明 |
|---|---|
get(path) |
GET 请求 |
post(path, body) |
POST 请求 |
put(path, body) |
PUT 请求 |
del(path) |
DELETE 请求 |
内置能力:
| 能力 | 说明 |
|---|---|
| 自动鉴权 | 从 site-config.js 读取当前会话的 URL+Token,自动添加 skill-access-token header |
| 插件校验 | 路径匹配 /api/apps/{addon}/... 时自动查 init.data.addons 确认插件已安装 |
| 架构拦截 | 10000011(权限)、10000014(插件未安装)、10000025(店铺类型不支持)→ 自动 throw Error |
| 30s 超时 | 请求超时自动 kill |
| 错误识别 | 自动检测 HTML 异常响应(PHP ErrorException),区分 JSON 解析失败 |
作为模块引用示例:
const api = require('../base/api-client');
const r = await api.get('/api/skill/product/list?pageNum=1');
const r2 = await api.post('/api/skill/product-collection/create', { type: 1, title: 'New' });
2.2 scripts/proxy/api-call.js — CLI API 代理
谁调用:Agent 通过 bash exec 直接调用(SKILL.md 第 2 节定义的唯一 API 调用方式)
职责:Agent 与 API 之间的桥梁。接收 CLI 命令 → 解析 body → 调 api-client.js → 输出 JSON。
4 种入参方式:
# 方式 1: GET(无 body)
node scripts/proxy/api-call.js GET /api/skill/product/list
# 方式 2: stdin 管道(短 JSON)
echo '{"page":1}' | node scripts/proxy/api-call.js POST /api/skill/product/list
# 方式 3: --data 文件(长 JSON,推荐)
node scripts/proxy/api-call.js POST /api/skill/product-collection/create --data body.json
# 方式 4: 命令行参数(极短 JSON)
node scripts/proxy/api-call.js POST /api/skill/product/info '{"id":363}'
特点:
- 一次 exec 完成任意 API 调用
- 自动处理 Windows PowerShell 的 JSON 转义问题(
--data文件模式绕过 shell 解析) - 统一 JSON 输出,Agent 直接解析
2.3 scripts/proxy/api-doc.js — Schema 查询
谁调用:Agent 通过 SKILL.md 第 2 节间接调用
职责:读取 docs/schemas/*.json,输出模块列表 / API 列表 / API 参数。Agent 调用 API 前用它确认参数名和类型。
4 种模式:
# 列出所有模块
node scripts/proxy/api-doc.js
# 某模块的所有 API(不含详细参数)
node scripts/proxy/api-doc.js --module=product
# 单个 API 的完整参数(含 params/body_root/product_fields 等)
node scripts/proxy/api-doc.js --api=product/list
# 搜索模块名/API 名
node scripts/proxy/api-doc.js --search=专辑
数据流:
api-doc.js → 读 docs/schemas/*.json → 解析 JSON → 格式化输出
3. 图片上传
3.1 scripts/image/upload-local.js — 本地图片上传
被谁引用:generate.js、batch-collection.js、商品批量上传工作流、模版装修工作流
职责:将本地图片文件直接读文件发 HTTPS 上传到 Fecify 图片服务器。不通过 shell 传 base64,避免命令行长度限制和转义问题。
# 上传目录中所有图片
node scripts/image/upload-local.js "C:\Users\xxx\Desktop\images" product
# 上传单张图片
node scripts/image/upload-local.js "D:\temp\banner.jpg" product
# group_type 可选值: product(默认)/ category / gallery / avatar / editor 等
输出(JSON 数组):
[
{
"fileName": "banner.jpg",
"path": "/product/15/image/2026/06/17/abc123.webp",
"image_base_url": "https://img.example.com",
"url": "https://img.example.com/product/15/image/2026/06/17/abc123.webp",
"sizeBytes": 204800,
"status": "ok"
}
]
4. AI 图片生成引擎
4.1 scripts/image-gen/image-client.js — 通用客户端
被谁引用:batch-collection.js、create.js、generate.js、模版装修脚本
职责:Fecify 文生图核心封装。配置读取 → Provider 路由 → 生成 → PIL 裁切 → WebP 输出。业务脚本只需指定 prompt + 尺寸,无需关心是 duomiapi 还是 doubao。
导出函数:
| 函数 | 说明 |
|---|---|
genImage(opts) |
单张生成:{ prompt, width, height, quality, out } → 返回输出路径 |
genImageBatch(jobs, opts) |
批量生成:[{ prompt, width, height, out }] → 返回结果数组 |
checkConfigReady() |
检查 AI 配置是否就绪 |
getConfig() |
读取当前配置 |
Provider 路由逻辑:
读 image-ai-config.json → 取 defaultProvider → 匹配 Provider:
"gpt-image-2" / 未识别 → duomiapi(异步 + 并发轮询)
"doubao-seedream-5" → doubao(同步 + 串行)
输出处理:
Provider 返回 Buffer → 写临时 PNG → Python PIL cover 裁切 + WebP 编码 → 删除临时 → 返回路径
4.2 scripts/image-gen/config.js — AI 配置管理
谁调用:Agent 初次设置 AI 生图时(SKILL.md 图片模块)
职责:管理 AI 生图的 Provider 配置(API 地址/Token/模型)。多 Provider 架构,切换不丢失已配置项。
配置存储:%APPDATA%/LobsterAI/data/fecify-shared/image-ai-config.json
# 查看
node scripts/image-gen/config.js
# 保存
node scripts/image-gen/config.js save "duomiapi" "https://api.duomiapi.com" "sk-xxx" "gpt-image-2"
# 切换默认 Provider
node scripts/image-gen/config.js use doubao-seedream-5
# 设置单个字段
node scripts/image-gen/config.js set apiKey "sk-new-key"
多 Provider 数据结构:
{
"providers": {
"gpt-image-2": {
"model": "gpt-image-2",
"apiBase": "https://api.duomiapi.com",
"apiKey": "sk-xxx",
"enabled": true
},
"doubao-seedream-5": {
"model": "doubao-seedream-5",
"apiBase": "https://ark.cn-beijing.volces.com",
"apiKey": "sk-yyy",
"enabled": true
}
},
"defaultProvider": "gpt-image-2"
}
4.3 scripts/image-gen/duomiapi-gpt-image-2.js — duomiapi Provider
被谁引用:image-client.js(内部路由,不直接暴露给 Agent)
职责:duomiapi gpt-image-2 异步生图引擎。提供 createTask → queryTask(非阻塞单次)/ pollTask(阻塞轮询)→ downloadImage 三步 API。
导出函数:
| 函数 | 说明 |
|---|---|
generate(apiBase, apiKey, prompt, width, height, quality) |
单张:创建任务→轮询→下载→返回 Buffer |
generateBatch(apiBase, apiKey, jobs, quality) |
批量:全部同时提交→统一轮询(每轮各查一次)→批量下载 |
createTask(...) |
提交任务,返回 taskId |
queryTask(...) |
单次查询任务状态 |
downloadImage(...) |
下载结果图片 |
并发策略:generateBatch 实现了真正的并发——所有任务同时提交,然后集体轮询直到全部完成。大幅减少总耗时(n 张图 ≈ 最慢那张的时间,而非逐个累加)。
4.4 scripts/image-gen/doubao-seedream-5.js — 豆包 Provider
被谁引用:image-client.js(内部路由,不直接暴露给 Agent)
职责:豆包 Seedream 5.0 同步生图引擎。直接发请求 → 同步等待 → 返回结果。自动根据目标尺寸选择最佳预设分辨率(2K/3K/4K/1920/2048)。
导出函数:
| 函数 | 说明 |
|---|---|
generate(apiBase, apiKey, prompt, width, height) |
单张生成,返回 { buffer, width, height } |
generateBatch(apiBase, apiKey, jobs) |
逐张串行生成(豆包不支持真并发) |
尺寸适配:自动匹配最接近的 Seedream 预设分辨率,确保生成质量最佳。
4.5 scripts/image-gen/prompt-enhancer.js — Prompt 增强器
被谁引用:image-client.js(通过 generate.js 间接调用)
职责:为电商生图场景提供 prompt 模板。自动拼接跨境电商锚定词(ABSOLUTELY NO text, no letters, no logos 等)。
导出:
enhancePrompt(userText, imageType, provider)— 核心函数PROMPT_TEMPLATES— 4 种模板(banner/ad/product/carousel)SCENE_KEYWORDS— 中文关键词→英文描述映射(20+ 词)ECOMMERCE_ANCHOR— 锚定词常量
使用:
enhancePrompt('夏季沙滩裙', 'banner')
// → "Professional e-commerce website hero banner..., 夏季沙滩裙, beach scene..., ABSOLUTELY NO text..."
豆包支持中文,enhance 时不强制英文化;非豆包 provider 则拼接英文关键词。
4.6 scripts/image-gen/generate.js — CLI 快捷入口
被谁调用:Agent 需要快速生图时(SKILL.md 图片模块)
职责:用一张标题列表(txt/JSON)或单个 prompt 批量生成图片并输出到 temp/images/。封装了 image-client + prompt-enhancer。
# 单张
node scripts/image-gen/generate.js "Summer Beach Dress" --width=1600 --height=400 --type=banner
# 批量
node scripts/image-gen/generate.js --batch=batch.json
batch.json 格式:
[
{ "prompt": "夏季连衣裙", "width": 1400, "height": 900, "type": "banner" },
{ "prompt": "冬季外套", "width": 1200, "height": 800, "type": "ad" }
]
调用关系图
┌─────────────────────────────────────────────────────────┐
│ 上层(被用户/Agent 直接触发) │
│ SKILL.md → api-call.js | batch-collection.js │
│ create.js | translate-*.js | batch-upload.js │
│ generate.js | theme/*.js | csv-import/*.js │
└────────┬──────────────────────────┬─────────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────────────────────┐
│ API 通信层 │ │ AI 生图引擎 │
│ │ │ │
│ api-call.js ────►│ │ image-client.js │
│ ↓ │ │ ↓ ↓ │
│ api-client.js ◄──│ │ duomiapi doubao │
│ ↓ │ │ ↓ ↓ │
│ site-config.js │ │ prompt-enhancer config.js │
│ │ │ ↓ │
│ api-doc.js ──────┤ │ generate.js (CLI) │
│ ↓ │ │ ↓ │
│ schemas/*.json │ │ upload-local.js │
└─────────────────┘ └──────────────────────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────┐
│ 底层(外部) │
│ fecify-shared/sessions/ domain/config.json │
│ fecify-shared/image-ai-config.json │
│ Fecify API 服务器 AI Provider API │
└─────────────────────────────────────────────────────────┘
核心原则:这 14 个文件构成了 skill 的"操作系统内核"——它们被引用、被依赖,但从未直接接受用户的指令。用户通过 SKILL.md 路由到上层业务脚本/工作流,上层再间接调用它们。