Browse Source

fmode-image v1.0.0

liuyuyang 14 hours ago
commit
a19d90e0ba
7 changed files with 238 additions and 0 deletions
  1. 6 0
      .claude-plugin/plugin.json
  2. 18 0
      README.md
  3. 39 0
      bin/fmode-image.js
  4. 29 0
      package.json
  5. 100 0
      scripts/gen.py
  6. 9 0
      skill-package-manifest.json
  7. 37 0
      skills/fmode-image/SKILL.md

+ 6 - 0
.claude-plugin/plugin.json

@@ -0,0 +1,6 @@
+{
+  "name": "fmode-image",
+  "version": "1.0.0",
+  "description": "Fmode Image Generator: 架构图和场景插图生成器",
+  "tools": []
+}

+ 18 - 0
README.md

@@ -0,0 +1,18 @@
+# fmode-image
+
+AI架构图和场景插图生成器。自动读取 Fmode API Key,支持架构图和场景图双模式。
+
+## 快速使用
+```bash
+npx fmode-image --arch "你的架构图描述" 输出文件名
+npx fmode-image --scene "你的场景描述" 输出文件名
+```
+
+## 安装
+```bash
+npm install -g fmode-image
+```
+
+## 环境变量
+- `FMODE_API_KEY` — Fmode API 密钥
+- `SKILL_IMAGE_OUTPUT` — 输出目录 (默认当前目录)

+ 39 - 0
bin/fmode-image.js

@@ -0,0 +1,39 @@
+#!/usr/bin/env node
+const fs = require('fs');
+const os = require('os');
+const path = require('path');
+const { spawnSync } = require('child_process');
+
+const SKILL_NAME = 'fmode-image';
+const SOURCE_ROOT = path.resolve(__dirname, '..');
+const SKILL_SOURCE = path.join(SOURCE_ROOT, 'skills', SKILL_NAME);
+const GEN_SCRIPT = path.join(SKILL_SOURCE, 'scripts', 'gen.py');
+const WORKSPACE_ROOT = process.cwd();
+
+function runGen(passthrough) {
+  const python = process.platform === 'win32' ? 'python' : 'python3';
+  const result = spawnSync(python, [GEN_SCRIPT, ...passthrough], { stdio: 'inherit', shell: false });
+  if (result.error) {
+    console.error(`fmode-image: failed to launch generator: ${result.error.message}`);
+    process.exit(1);
+  }
+  process.exit(result.status ?? 0);
+}
+
+const args = process.argv.slice(2);
+if (args.length === 0) {
+  console.log(`fmode-image — Fmode Image Generator
+
+用法:
+  npx fmode-image --arch "prompt" [name]     生成架构图 (1792x1024, ¥0.5)
+  npx fmode-image --scene "prompt" [name]    生成场景图 (1024x1024, ¥0.3)
+
+示例:
+  npx fmode-image --arch "内容营销预审Agent Harness架构,五层..." case01
+  npx fmode-image --scene "法务团队被稿件淹没的办公场景" legal-scene
+
+自动读取 FMODE_API_KEY (env/.fmode/config.json/.env)
+`);
+  process.exit(0);
+}
+runGen(args);

+ 29 - 0
package.json

@@ -0,0 +1,29 @@
+{
+  "name": "fmode-image",
+  "version": "1.0.0",
+  "description": "Fmode Image Generator: 架构图和场景插图生成器。自动读取API Key,支持AI架构图(1792x1024)和场景插图(1024x1024)双模式,纯白底PNG直接用于PPT。",
+  "type": "commonjs",
+  "bin": {
+    "fmode-image": "bin/fmode-image.js"
+  },
+  "files": [
+    ".claude-plugin/",
+    "bin/",
+    "scripts/",
+    "README.md",
+    "skill-package-manifest.json",
+    "skills/"
+  ],
+  "keywords": [
+    "claude-code",
+    "claude-skill",
+    "fmode",
+    "image",
+    "architecture",
+    "diagram",
+    "illustration",
+    "harness",
+    "ppt"
+  ],
+  "license": "MIT"
+}

+ 100 - 0
scripts/gen.py

@@ -0,0 +1,100 @@
+#!/usr/bin/env python3
+"""skill-image: 架构图 + 场景插图生成器
+用法:
+  python3 gen.py --arch "prompt" [name]     # 架构图 1792x1024 ¥0.5/张
+  python3 gen.py --scene "prompt" [name]    # 场景图 1024x1024 ¥0.3/张
+  python3 gen.py --batch-arch <json_file>   # 批量架构图
+
+凭据: 自动读取 FMODE_API_KEY (env/config)
+"""
+import json, base64, urllib.request, os, sys
+
+API = 'https://api.fmode.cn/v1/images/generations'
+
+def _get_key():
+    for src_name, src_val in [
+        ('FMODE_API_KEY env', os.environ.get('FMODE_API_KEY', '')),
+        ('ANTHROPIC_AUTH_TOKEN env', os.environ.get('ANTHROPIC_AUTH_TOKEN', '')),
+    ]:
+        if src_val and '***' not in src_val and len(src_val) > 10:
+            return src_val
+    try:
+        with open(os.path.expanduser('~/.fmode/config.json')) as f:
+            c = json.load(f)
+            for k in ('api_key', 'FMODE_API_KEY'):
+                if c.get(k): return c[k]
+    except: pass
+    try:
+        with open(os.path.expanduser('~/.fmode/config.yaml')) as f:
+            for l in f:
+                for kw in ('api_key', 'FMODE_API_KEY'):
+                    if kw in l:
+                        v = l.split(':')[1].strip().strip('"\'')
+                        if v and v != '${FMODE_API_KEY}': return v
+    except: pass
+    for p in ['/opt/data/.env', '.env']:
+        try:
+            with open(p) as f:
+                for l in f:
+                    if 'FMODE_API_KEY' in l:
+                        v = l.split('=')[1].strip().strip('"\'')
+                        if v and '***' not in v and len(v) > 10: return v
+        except: pass
+    print('❌ 未找到 API Key。设置环境变量 FMODE_API_KEY 或 ~/.fmode/config.json')
+    sys.exit(1)
+
+API_KEY = _get_key()
+
+def _call_api(prompt, size):
+    body = json.dumps({"model": "gpt-image-2.5-sunburst", "prompt": prompt, "n": 1, "size": size}).encode()
+    req = urllib.request.Request(API, data=body,
+        headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
+        method='POST')
+    resp = urllib.request.urlopen(req, timeout=300)
+    data = json.loads(resp.read())
+    if 'b64_json' in data['data'][0]:
+        return base64.b64decode(data['data'][0]['b64_json'])
+    if 'url' in data['data'][0]:
+        return urllib.request.urlopen(data['data'][0]['url'], timeout=60).read()
+    raise Exception('No image data')
+
+def gen_arch(prompt, name='arch'):
+    """架构图: 1792x1024 ¥0.5/张,纯白底PPT用"""
+    full = f'纯白背景扁平风格架构图。{prompt} 简洁扁平商务风格,纯白背景适合PPT。'
+    out = _gen(full, '1792x1024', name)
+    return out
+
+def gen_scene(prompt, name='scene'):
+    """场景/插图: 1024x1024 ¥0.3/张,照片/示意图/画面"""
+    full = f'扁平插画场景。{prompt} 清新明亮风格。'
+    out = _gen(full, '1024x1024', name)
+    return out
+
+def _gen(prompt, size, name):
+    outdir = os.environ.get('SKILL_IMAGE_OUTPUT', '.')
+    os.makedirs(outdir, exist_ok=True)
+    path = f'{outdir}/{name}.png'
+    data = _call_api(prompt, size)
+    with open(path, 'wb') as f:
+        f.write(data)
+    sz = os.path.getsize(path)//1024
+    print(f'✅ {sz}KB -> {path}')
+    return path
+
+def batch_arch(items):
+    """items: [(name, prompt), ...]"""
+    for name, prompt in items:
+        print(f'{name}:', end=' ', flush=True)
+        try:
+            gen_arch(prompt, name)
+        except Exception as e:
+            print(f'❌ {e}')
+
+if __name__ == '__main__':
+    if len(sys.argv) < 3:
+        print(__doc__)
+        sys.exit(1)
+    mode, content = sys.argv[1], sys.argv[2]
+    name = sys.argv[3] if len(sys.argv) > 3 else 'output'
+    {'--arch': lambda: gen_arch(content, name),
+     '--scene': lambda: gen_scene(content, name)}.get(mode, lambda: print(f'Unknown mode {mode}'))()

+ 9 - 0
skill-package-manifest.json

@@ -0,0 +1,9 @@
+{
+  "name": "fmode-image",
+  "version": "1.0.0",
+  "description": "Fmode Image Generator",
+  "install": {
+    "claude-code": "npx fmode-image",
+    "hermes": "skill_view(name='fmode-image')"
+  }
+}

+ 37 - 0
skills/fmode-image/SKILL.md

@@ -0,0 +1,37 @@
+---
+name: fmode-image
+description: "触发词:生成架构图/场景图/插图。走API出白底PNG,自动读Key,¥0.3-0.5/张。"
+version: 1.0.0
+author: Fmode
+license: MIT
+platforms: [linux, macos, windows]
+---
+
+# fmode-image — AI架构图和场景插图生成器
+
+## 凭据自动获取
+自动读取:FMODE_API_KEY (env) → ~/.fmode/config.json → ~/.fmode/config.yaml → .env
+
+## 双模式
+
+### --arch 架构图
+- **尺寸**: 1792×1024 (PPT横版)
+- **成本**: ≈¥0.5/张
+- **风格**: 纯白底、扁平、商务
+
+### --scene 场景/插图
+- **尺寸**: 1024×1024 (方形)
+- **成本**: ≈¥0.3/张 (省40%)
+- **风格**: 扁平插画、清新明亮
+
+## 用法
+```bash
+# 架构图
+npx fmode-image --arch "内容营销预审Agent Harness架构,五层..." case01
+
+# 场景图
+npx fmode-image --scene "法务团队被稿件淹没的场景" legal-scene
+```
+
+## 独立脚本
+scripts/gen.py 可直接运行,不依赖node:python3 gen.py --arch "..." out