|
@@ -1,209 +0,0 @@
|
|
|
-#!/usr/bin/env python3
|
|
|
|
|
-"""批量生成 fmode-skills 服务层子技能 ESM 结构(统一规范)"""
|
|
|
|
|
-import os, textwrap
|
|
|
|
|
-
|
|
|
|
|
-BASE = '/opt/data/projects/fmode-skills/skills'
|
|
|
|
|
-
|
|
|
|
|
-skills = [
|
|
|
|
|
- {
|
|
|
|
|
- "dir": "fmode-account",
|
|
|
|
|
- "name": "fmode-account",
|
|
|
|
|
- "slug": "fmode-skill-fmode-account",
|
|
|
|
|
- "version": "0.1.0",
|
|
|
|
|
- "title": "Fmode 账号(手机验证码注册/登录)",
|
|
|
|
|
- "summary": "Fmode 账号注册登录:手机验证码 → sessionToken → 企业开通。数字分身初始化第一步。",
|
|
|
|
|
- "triggers": "注册、登录、验证码、sessionToken、账号、手机号、数字分身初始化、fmod账号",
|
|
|
|
|
- "endpoints": [
|
|
|
|
|
- ("POST https://server.fmode.cn/api/apig/message", "发送验证码 {mobile,company}"),
|
|
|
|
|
- ("GET https://server.fmode.cn/api/fmode/mobile", "验证码登录 {mobile,code} → data.token/data.newapiToken"),
|
|
|
|
|
- ("GET https://server.fmode.cn/parse/users/me", "校验会话 Bearer token"),
|
|
|
|
|
- ],
|
|
|
|
|
- "keypoints": ["token 走受保护 profile(0700),不进聊天/project/Git/日志", "验证码只用于立即登录请求", "Windows 用当前用户目录,POSIX 0700/0600"],
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "dir": "fmode-enterprise",
|
|
|
|
|
- "name": "fmode-enterprise",
|
|
|
|
|
- "slug": "fmode-skill-fmode-enterprise",
|
|
|
|
|
- "version": "0.1.0",
|
|
|
|
|
- "title": "Fmode 企业(开通状态/独立部署)",
|
|
|
|
|
- "summary": "Fmode 企业状态:查询订阅、申请独立部署、轮询开通。数字分身企业开通。",
|
|
|
|
|
- "triggers": "企业、开通、订阅、enterprise、Company、独立部署、sub、trial",
|
|
|
|
|
- "endpoints": [
|
|
|
|
|
- ("POST https://server.fmode.cn/api/fmode/enterprise/subscription/status", "查企业状态 {sessionToken}"),
|
|
|
|
|
- ("POST https://server.fmode.cn/api/fmode/enterprise/subscription/trial-standalone", "申请独立部署 {name,sessionToken}"),
|
|
|
|
|
- ("POST https://server.fmode.cn/api/fmode/enterprise/subscription/provision/retry", "重试开通(仅失败后)"),
|
|
|
|
|
- ],
|
|
|
|
|
- "keypoints": ["不在企业时问人名(非企业名)再trial-standalone", "仅 provision pending/running 时轮询状态", "绝不索要数据库URI"],
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "dir": "fmode-cloud-functions",
|
|
|
|
|
- "name": "fmode-cloud-functions",
|
|
|
|
|
- "slug": "fmode-skill-fmode-cloud-functions",
|
|
|
|
|
- "version": "0.1.0",
|
|
|
|
|
- "title": "Fmode 云函数(Function 合同 + /api/functions)",
|
|
|
|
|
- "summary": "Fmode 云函数部署与调用:Function 合同表存动态函数源,/api/functions 发布执行。",
|
|
|
|
|
- "triggers": "云函数、Function、/api/functions、后端函数、业务接口、动态函数",
|
|
|
|
|
- "endpoints": [
|
|
|
|
|
- ("POST https://server.fmode.cn/api/functions", "调用/注册云函数 {token, path, params}"),
|
|
|
|
|
- ],
|
|
|
|
|
- "keypoints": ["CRUD 不建用户维护服务器,动态函数进 Function 合同表", "handler(request,response) 签名 + 会话鉴权 + 租户校验 + 幂等", "masterKey/dbURI/平台session 绝不进浏览器 bundle"],
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "dir": "fmode-cloud-resources",
|
|
|
|
|
- "name": "fmode-cloud-resources",
|
|
|
|
|
- "slug": "fmode-skill-fmode-cloud-resources",
|
|
|
|
|
- "version": "0.1.0",
|
|
|
|
|
- "title": "Fmode 云资源(华为云 STS 部署)",
|
|
|
|
|
- "summary": "Fmode 云资源领取:平台签发项目级 STS,华为云 OBS 部署,无需用户华为账号。",
|
|
|
|
|
- "triggers": "云资源、领取、部署、华为云、STS、obs、huaweicloud、deploy",
|
|
|
|
|
- "endpoints": [
|
|
|
|
|
- ("POST https://server.fmode.cn/api/apig/deploy/huaweicloud", "取 STS {token, projectId} → accessKey/secretKey/securityToken/expiresAt/obsPath"),
|
|
|
|
|
- ],
|
|
|
|
|
- "keypoints": ["STS 平台签发,非用户华为账号,用户无需华为账号/服务器", "过期(<5min)丢弃整套后重取,最多重试2次", "绝不替换为永久密钥"],
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "dir": "fmode-static-publish",
|
|
|
|
|
- "name": "fmode-static-publish",
|
|
|
|
|
- "slug": "fmode-skill-fmode-static-publish",
|
|
|
|
|
- "version": "0.1.0",
|
|
|
|
|
- "title": "Fmode 静态发布(OBS+CDN 公开 URL)",
|
|
|
|
|
- "summary": "Fmode 前后端发布:构建 → 注册 Project → STS → obsutil 同步 OBS → CDN 刷新 → 验证公开 URL。",
|
|
|
|
|
- "triggers": "发布、部署、上线、静态站、前端、课件、CDN、obsutil、public URL、huaweicloud-cdn-refresh",
|
|
|
|
|
- "endpoints": [
|
|
|
|
|
- ("POST https://server.fmode.cn/api/functions", "注册 Project {token,path:/fmode/project-register,params:{name,version,gitUrl}}"),
|
|
|
|
|
- ("POST https://server.fmode.cn/api/apig/deploy/huaweicloud", "取 STS {token,projectId}"),
|
|
|
|
|
- ("POST https://server.fmode.cn/api/apig/deploy/huaweicloud-cdn-refresh", "CDN 刷新 {token,projectId,path}"),
|
|
|
|
|
- ],
|
|
|
|
|
- "keypoints": ["注册Project→构建→扫token→取STS→上传obsPath→CDN刷新→验证URL 逐门禁报告", "obsPath 必须是 dev/<projectId>/", "会话过期先重播登录再取新STS,不求华为凭据"],
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "dir": "fmode-git-archive",
|
|
|
|
|
- "name": "fmode-git-archive",
|
|
|
|
|
- "slug": "fmode-skill-fmode-git-archive",
|
|
|
|
|
- "version": "0.1.0",
|
|
|
|
|
- "title": "Fmode Git 归档(Gitea + 源码入库)",
|
|
|
|
|
- "summary": "Fmode 项目归档:源码进 git.fmode.cn,建 Gogs 账号/个人 token/建仓/推送/验证 SHA。",
|
|
|
|
|
- "triggers": "归档、git、Gogs、Gitea、git.fmode.cn、仓库、源码入库、git archive",
|
|
|
|
|
- "endpoints": [
|
|
|
|
|
- ("POST https://server.fmode.cn/api/functions", "Gogs admin proxy 建用户 {token,path:/gogs/admin/proxy,params:{method:POST,path:/admin/users,...}}"),
|
|
|
|
|
- ("POST https://git.fmode.cn/api/v1/users/<username>/tokens", "创建个人 token"),
|
|
|
|
|
- ("POST https://git.fmode.cn/api/v1/user/repos", "创建私有仓库"),
|
|
|
|
|
- ],
|
|
|
|
|
- "keypoints": ["用户名强制 fmode-<phone>,请求值忽略占位", "token 绝不进 remote URL,用 HTTPS + token 密码", "排除 .env/密钥/构建产物/日志", "git ls-remote 验证远端 SHA,发布与归档分开报告"],
|
|
|
|
|
- },
|
|
|
|
|
-]
|
|
|
|
|
-
|
|
|
|
|
-# 通用 ESM 脚本模板(fetch 封装)
|
|
|
|
|
-FETCH_TMPL = '''#!/usr/bin/env node
|
|
|
|
|
-/**
|
|
|
|
|
- * {title} — 辅助脚本(零 npm 依赖,Node>=18 自带 fetch)
|
|
|
|
|
- * Copyright (c) 未来飞马 MPL-2.0
|
|
|
|
|
- *
|
|
|
|
|
- * 用法:node index.mjs <action> [jsonPayload]
|
|
|
|
|
- */
|
|
|
|
|
-const BASE = "https://server.fmode.cn";
|
|
|
|
|
-
|
|
|
|
|
-async function call(method, path, body, token) {{
|
|
|
|
|
- const headers = {{ "content-type": "application/json" }};
|
|
|
|
|
- if (token) headers["authorization"] = "Bearer " + token;
|
|
|
|
|
- const res = await fetch(BASE + path, {{
|
|
|
|
|
- method, headers, body: body ? JSON.stringify(body) : undefined,
|
|
|
|
|
- }});
|
|
|
|
|
- const text = await res.text();
|
|
|
|
|
- // 脱敏输出:token/密钥不打印
|
|
|
|
|
- const safe = text.replace(/(token|authorization|accessKey|secretKey|securityToken)["'\\s:]+([^",}}]+)/gi, "$1:***");
|
|
|
|
|
- console.log(safe);
|
|
|
|
|
- return res;
|
|
|
|
|
-}}
|
|
|
|
|
-
|
|
|
|
|
-const [action, raw] = process.argv.slice(2);
|
|
|
|
|
-let payload = {{}};
|
|
|
|
|
-try {{ if (raw) payload = JSON.parse(raw); }} catch {{ payload = {{ _raw: raw }}; }}
|
|
|
|
|
-
|
|
|
|
|
-{actions}
|
|
|
|
|
-
|
|
|
|
|
-'''
|
|
|
|
|
-
|
|
|
|
|
-def actions_for(epoints):
|
|
|
|
|
- lines = []
|
|
|
|
|
- for ep in epoints:
|
|
|
|
|
- method, path = ep[0].split(' ')
|
|
|
|
|
- parts = path.replace('https://server.fmode.cn','').strip()
|
|
|
|
|
- # 生成一个如 call("<METHOD>","<PATH>", payload) 的示例
|
|
|
|
|
- lines.append(f'// 示例端点: {method} {ep[1]}')
|
|
|
|
|
- return "\n".join(lines)
|
|
|
|
|
-
|
|
|
|
|
-for s in skills:
|
|
|
|
|
- d = os.path.join(BASE, s['dir'])
|
|
|
|
|
- os.makedirs(os.path.join(d, 'scripts'), exist_ok=True)
|
|
|
|
|
- os.makedirs(os.path.join(d, 'references'), exist_ok=True)
|
|
|
|
|
-
|
|
|
|
|
- # SKILL.md
|
|
|
|
|
- ep_lines = "\n".join(f"| `{m} {p}` | {desc} |" for m, p, desc in [
|
|
|
|
|
- (m, p, dsc) for m, p, dsc in [(ep[0].split(' ')[0], ep[0].split(' ')[1], ep[1]) for ep in s['endpoints']]
|
|
|
|
|
- ])
|
|
|
|
|
- kp_lines = "\n".join(f"- ⚠️ {k}" for k in s['keypoints'])
|
|
|
|
|
-
|
|
|
|
|
- skill_md = f"""---
|
|
|
|
|
-slug: {s['slug']}
|
|
|
|
|
-displayName: {s['dir']}
|
|
|
|
|
-version: {s['version']}
|
|
|
|
|
-name: {s['dir']}
|
|
|
|
|
-description: {s['summary']} 触发词:{s['triggers']}
|
|
|
|
|
-tags: [FmodeAgent, FmodeCode, 服务级, {s['dir'].replace('fmode-','')}]
|
|
|
|
|
-platform: Both
|
|
|
|
|
-level: 服务级
|
|
|
|
|
-category: 平台基础设施
|
|
|
|
|
-icon: ⚙️
|
|
|
|
|
-license: MPL-2.0
|
|
|
|
|
-author: Fmode (未来飞马)
|
|
|
|
|
----
|
|
|
|
|
-
|
|
|
|
|
-# {s['title']}
|
|
|
|
|
-
|
|
|
|
|
-## 触发词
|
|
|
|
|
-
|
|
|
|
|
-{s['triggers']}
|
|
|
|
|
-
|
|
|
|
|
-## 快速开始(ESM)
|
|
|
|
|
-
|
|
|
|
|
-```bash
|
|
|
|
|
-node scripts/index.mjs <action> '{{"...": ...}}'
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-或 Agent 直接按流程调用下述端点。
|
|
|
|
|
-
|
|
|
|
|
-## 端点清单
|
|
|
|
|
-
|
|
|
|
|
-| 端点 | 作用 |
|
|
|
|
|
-|------|------|
|
|
|
|
|
-{ep_lines}
|
|
|
|
|
-
|
|
|
|
|
-## 关键纪律
|
|
|
|
|
-
|
|
|
|
|
-{kp_lines}
|
|
|
|
|
-
|
|
|
|
|
-## References
|
|
|
|
|
-
|
|
|
|
|
-- 详见 `references/` 目录
|
|
|
|
|
-- 完整平台规范见 skill-core-guide(`fmode-skills` 自带)
|
|
|
|
|
-
|
|
|
|
|
-## License
|
|
|
|
|
-
|
|
|
|
|
-MPL-2.0 © 2026 Fmode (未来飞马)
|
|
|
|
|
-"""
|
|
|
|
|
- with open(os.path.join(d, 'SKILL.md'), 'w', encoding='utf-8') as f:
|
|
|
|
|
- f.write(skill_md)
|
|
|
|
|
-
|
|
|
|
|
- # scripts/index.mjs(零依赖 fetch 封装)
|
|
|
|
|
- fetch_js = FETCH_TMPL.format(title=s['title'], actions=actions_for(s['endpoints']))
|
|
|
|
|
- with open(os.path.join(d, 'scripts', 'index.mjs'), 'w', encoding='utf-8') as f:
|
|
|
|
|
- f.write(fetch_js)
|
|
|
|
|
-
|
|
|
|
|
- # references/endpoints.md
|
|
|
|
|
- with open(os.path.join(d, 'references', 'endpoints.md'), 'w', encoding='utf-8') as f:
|
|
|
|
|
- f.write(f"# {s['title']} 端点参考\n\n" + ep_lines + "\n")
|
|
|
|
|
-
|
|
|
|
|
- print(f"✅ 生成 {s['dir']}")
|
|
|
|
|
-
|
|
|
|
|
-print("🎉 服务层子技能生成完毕")
|
|
|