From e13e1aeedea084642782407cd1e14bcbbb4cc8cb Mon Sep 17 00:00:00 2001 From: pandy <1272175942@qq.com> Date: Sun, 8 Mar 2026 11:10:30 +0800 Subject: [PATCH] Initial commit from comfyui-PD_comfy api node --- .cursorrules | 4 + .gitignore | Bin 0 -> 251 bytes README.md | 182 +++++++ __init__.py | 74 +++ gittools.py | 590 ++++++++++++++++++++++ image/comfyui-node-apikey.png | Bin 0 -> 78550 bytes image/comfyui-node-auth.png | Bin 0 -> 115436 bytes py/IMAGE_GPT_apikey.py | 312 ++++++++++++ py/IMAGE_GPT_authtoken.py | 313 ++++++++++++ py/IMAGE_GeminiNanoBanana2.py | 279 ++++++++++ py/IMGE_GeminiNode_apikey.py | 284 +++++++++++ py/IMGE_GeminiNode_authtoken.py | 281 +++++++++++ py/IMGE_GeminiPro_apikey.py | 294 +++++++++++ py/IMGE_GeminiPro_authtoken.py | 300 +++++++++++ py/PD_comfyplus_image.py | 78 +++ py/README.md | 352 +++++++++++++ temperay/PD_comfyui_token_grabber.user.js | 506 +++++++++++++++++++ 17 files changed, 3849 insertions(+) create mode 100644 .cursorrules create mode 100644 .gitignore create mode 100644 README.md create mode 100644 __init__.py create mode 100644 gittools.py create mode 100644 image/comfyui-node-apikey.png create mode 100644 image/comfyui-node-auth.png create mode 100644 py/IMAGE_GPT_apikey.py create mode 100644 py/IMAGE_GPT_authtoken.py create mode 100644 py/IMAGE_GeminiNanoBanana2.py create mode 100644 py/IMGE_GeminiNode_apikey.py create mode 100644 py/IMGE_GeminiNode_authtoken.py create mode 100644 py/IMGE_GeminiPro_apikey.py create mode 100644 py/IMGE_GeminiPro_authtoken.py create mode 100644 py/PD_comfyplus_image.py create mode 100644 py/README.md create mode 100644 temperay/PD_comfyui_token_grabber.user.js diff --git a/.cursorrules b/.cursorrules new file mode 100644 index 0000000..c06a209 --- /dev/null +++ b/.cursorrules @@ -0,0 +1,4 @@ +1. 你是一个经验丰富的python开发者,擅长制作commfyui的节点,现在需要创建一个新的节点 +2. 确保输入输出图像或者遮罩的张量形状分别为B H W C ,B H W +3. 需要包含导入,节点注册等构建节点所需的完整代码 + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d50b56d7d7e1898cd917df864dc808c129b8075b GIT binary patch literal 251 zcmZ`xOA3Q95S?`(cM$BVi}VoHg`2iu>!y?tHPwJ-f{7`)eMh9r@?hrietC9FVMNQB zlrD9u8?}@t&W^&RXNUcZ=)on?P0IUC_Q;v|bvVnj#w=k~Q&!q&7PParfwQP>q?P@a zmxlP3t%{P`(bKRdNtj+M`n39S`@=nWt;sEFSqEG+XZLZPTQB-{ch5M#)1%rN6Aqg; TfPp|j!UP@!I7q;O!GGrqAM`&1 literal 0 HcmV?d00001 diff --git a/README.md b/README.md new file mode 100644 index 0000000..bb1c778 --- /dev/null +++ b/README.md @@ -0,0 +1,182 @@ +# ComfyUI PD Comfy API Node + +ComfyUI 自定义节点套件,集成 Gemini 和 GPT 图像生成 API,支持两种认证方式。 + +## ✨ 功能特性 + +- 🎨 **多模型支持**:Gemini 2.5 Flash Image、GPT Image 1/1.5 +- 🔑 **双认证方式**:支持 API Key 和 Auth Token 两种调用方式 +- 💰 **成本追踪**:实时显示 API 调用成本 +- 🖼️ **图像处理**:支持文生图、图生图、图像编辑 +- ⚙️ **灵活配置**:多种宽高比、质量、分辨率选项 + +## 📦 安装方法 + +```bash +cd ComfyUI/custom_nodes +git clone https://github.com/7BEII/comfyui-PD_comfy-api-node.git +pip install -r comfyui-PD_comfy-api-node/requirements.txt +``` + +重启 ComfyUI 后,在节点菜单的 `PD_Tools/Image_Generation` 分类中找到节点。 + +## 🔑 两种认证方式 + +### 方式一:API Key(推荐) + +使用 ComfyUI 官方 API Key,简单直接。 + +**获取方法**: +1. 访问 [ComfyUI API](https://www.comfy.org/api-keys) +2. 登录并创建 API Key +3. 复制 Key 并粘贴到节点中 + +![API Key 节点示例](image/comfyui-node-apikey.png) + +**优点**: +- ✅ 官方支持,稳定可靠 +- ✅ 配置简单,一个 Key 搞定 +- ✅ 支持所有模型 + +### 方式二:Auth Token + +使用浏览器 Auth Token,适合高级用户。 + +**获取方法**: +1. 安装油猴脚本(Tampermonkey):具体B站有教程:小熊猫pandy +2. 安装 Token 抓取脚本 +3. 访问 ComfyUI 网站并登录 +4. 脚本会自动抓取 Token +5. 复制 Token 并粘贴到节点中 + +![Auth Token 节点示例](image/comfyui-node-auth.png) + +**优点**: +- ✅ 无需申请 API Key +- ✅ 使用现有账号权限 +- ✅ 适合测试和开发 + +## 📝 更新日志 + +### v2.0.0 -2026.0112 +- 新增 Auth Token 认证方式 +- 新增 GPT Image 节点 +- 优化成本计算 +- 改进错误处理 + +### v1.0.0 +- 初始版本 +- 支持 Gemini 图像生成 +- 支持 API Key 认证 + +## 📋 节点说明 + +### 1. PD: Gemini Image (apikey) + +使用 API Key 调用 Gemini 图像生成。 + +**主要参数**: +- `api_key`:ComfyUI API Key +- `prompt`:图像生成提示词 +- `model`:模型选择(gemini-2.5-flash-image / gemini-2.5-flash-image-preview) +- `aspect_ratio`:宽高比(auto / 1:1 / 16:9 / 9:16 等) +- `image_ref`:参考图像(可选) + +**输出**: +- `image`:生成的图像 +- `info`:成本和状态信息 + +### 2. PD: Gemini Image (comfyui_AuthToken) + +使用 Auth Token 调用 Gemini 图像生成。 + +**主要参数**: +- `auth_token`:ComfyUI Auth Token +- `prompt`:图像生成提示词 +- `model`:模型选择 +- `aspect_ratio`:宽高比 +- `resolution`:分辨率(auto / 1K / 2K / 4K) +- `image_ref`:参考图像(可选) + +**输出**: +- `image`:生成的图像 +- `info`:成本和状态信息 + +### 3. PD: GPT Image (apikey) + +使用 API Key 调用 OpenAI GPT 图像生成。 + +**主要参数**: +- `api_key`:ComfyUI API Key +- `prompt`:图像生成提示词 +- `model`:模型选择(gpt-image-1 / gpt-image-1.5) +- `quality`:质量(low / medium / high) +- `size`:尺寸(auto / 1024x1024 / 1024x1536 / 1536x1024) +- `background`:背景(auto / opaque / transparent) +- `image`:输入图像(可选,用于编辑) +- `mask`:遮罩(可选,用于局部编辑) + +**输出**: +- `image`:生成的图像 +- `info`:成本和状态信息 + +**特性**: +- 支持文生图 +- 支持图生图编辑 +- 支持遮罩局部编辑 + +## 💡 使用示例 + +### 示例 1:使用 Gemini 生成图像(API Key) + +``` +1. 添加 "PD: Gemini Image (apikey)" 节点 +2. 输入 API Key +3. 输入提示词:"A futuristic city with flying cars" +4. 选择宽高比:16:9 +5. 连接输出到预览节点 +6. 执行工作流 +``` + +### 示例 2:使用 GPT 编辑图像 + +``` +1. 添加 "PD: GPT Image (apikey)" 节点 +2. 输入 API Key +3. 连接输入图像到 image 端口 +4. 输入编辑提示词:"Add a sunset sky" +5. 设置质量为 high +6. 执行工作流 +``` + +## ⚠️ 注意事项 + +1. **API Key 安全**:请妥善保管 API Key,不要分享给他人 +2. **成本控制**:注意查看成本信息,控制 API 调用次数 +3. **网络连接**:需要稳定的网络连接 +4. **生成时间**:高质量图像可能需要较长时间 + +## 🐛 故障排除 + +### 节点未显示 +- 检查是否正确安装到 `custom_nodes` 目录 +- 重启 ComfyUI +- 查看控制台错误信息 + +### API 调用失败 +- 验证 API Key 或 Auth Token 是否正确 +- 检查网络连接 +- 查看控制台详细错误信息 + +### 图像格式错误 +- 确保输入图像格式为 ComfyUI 标准格式(B H W C) +- 检查图像通道数是否为 3 (RGB) + +## 📄 许可证 + +MIT License + +## 🤝 贡献 +欢迎提交 Issue 和 Pull Request! +--- + diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..9b9e0f8 --- /dev/null +++ b/__init__.py @@ -0,0 +1,74 @@ +""" +Comfyui_PDuse - PD ComfyUI 自定义节点套件 +包含多种实用的图像处理和工具节点 +""" + +import importlib +import os +import sys + +# 初始化节点映射 +NODE_CLASS_MAPPINGS = {} +NODE_DISPLAY_NAME_MAPPINGS = {} + +def get_ext_dir(subpath=None, mkdir=False): + """获取扩展目录路径""" + dir = os.path.dirname(__file__) + if subpath is not None: + dir = os.path.join(dir, subpath) + return os.path.abspath(dir) + +def safe_import_module(module_path, file_name): + """安全导入模块,避免导入错误导致崩溃""" + try: + imported_module = importlib.import_module(module_path) + + # 检查模块是否包含所需的映射 + if hasattr(imported_module, 'NODE_CLASS_MAPPINGS'): + NODE_CLASS_MAPPINGS.update(imported_module.NODE_CLASS_MAPPINGS) + print(f"✅ 成功加载模块: {file_name}") + + if hasattr(imported_module, 'NODE_DISPLAY_NAME_MAPPINGS'): + NODE_DISPLAY_NAME_MAPPINGS.update(imported_module.NODE_DISPLAY_NAME_MAPPINGS) + + return True + + except Exception as e: + print(f"❌ 加载模块 {file_name} 失败: {e}") + return False + +# 动态扫描并加载 py/ 目录下的所有模块 +py_dir = get_ext_dir("py") + +if os.path.exists(py_dir): + files = os.listdir(py_dir) + + for file in files: + if not file.endswith(".py") or file.startswith("_"): + continue + + module_name = os.path.splitext(file)[0] + module_path = f"{__name__}.py.{module_name}" + + safe_import_module(module_path, file) +else: + print(f"警告: py目录不存在: {py_dir}") + +# Web界面目录 +WEB_DIRECTORY = "./js" + +# 显示加载信息 +if NODE_CLASS_MAPPINGS: + print("=" * 50) + print("🎨 Comfyui_PDuse 节点套件加载完成") + print("=" * 50) + print(f"📦 总计加载节点数量: {len(NODE_CLASS_MAPPINGS)}") + print("📋 已加载的节点:") + for name, display_name in NODE_DISPLAY_NAME_MAPPINGS.items(): + print(f" • {display_name}") + print("=" * 50) +else: + print("⚠️ 警告: 没有找到任何可用的节点") + +# 导出变量 +__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"] diff --git a/gittools.py b/gittools.py new file mode 100644 index 0000000..20239c3 --- /dev/null +++ b/gittools.py @@ -0,0 +1,590 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Git 自动同步工具 +用法: python gitrun.py [命令] + +命令说明: + push - 强制推送本地到远程(直接覆盖,保留历史记录) + pull - 强制拉取远程到本地(直接覆盖,保留历史记录) + sync - 智能同步(先拉取合并,再推送) + log - 查看提交历史并支持快速回退版本 + history - 查看完整提交历史 + config - 配置远程仓库地址 + + + + +重要说明: + • push/pull 都会保留完整的 Git 历史记录,可以随时回退 + • push 是纯粹的本地覆盖远程,不会先拉取远程内容 + • pull 是纯粹的远程覆盖本地,不会保留本地未推送的修改 + • sync 才会进行智能合并 + • log 命令可以查看历史并直接回退版本(输入数字选择,0或回车跳过) + • 所有历史提交都保存在 .git 目录中,永不丢失 +""" + +import os +import sys +import subprocess +import json +from pathlib import Path +from datetime import datetime + +CONFIG_FILE = Path.home() / '.gitrun_config.json' + + +class GitSyncTool: + def __init__(self): + self.config = self.load_config() + self.repo_path = os.getcwd() + + def load_config(self): + """加载配置文件""" + if CONFIG_FILE.exists(): + with open(CONFIG_FILE, 'r', encoding='utf-8') as f: + return json.load(f) + return {} + + def save_config(self): + """保存配置文件""" + with open(CONFIG_FILE, 'w', encoding='utf-8') as f: + json.dump(self.config, f, indent=2, ensure_ascii=False) + + def run_command(self, cmd, check=True, silent=False): + """执行命令并返回结果""" + try: + # Windows 上使用 GBK 编码,其他系统使用 UTF-8 + encoding = 'gbk' if sys.platform == 'win32' else 'utf-8' + + result = subprocess.run( + cmd, + shell=True, + cwd=self.repo_path, + capture_output=True, + text=True, + encoding=encoding, + errors='ignore' # 忽略无法解码的字符 + ) + if check and result.returncode != 0: + if not silent: + print(f"❌ 命令执行失败: {cmd}") + if result.stderr: + print(f"错误信息: {result.stderr}") + return None + return result + except Exception as e: + if not silent: + print(f"❌ 执行命令时出错: {e}") + return None + + def is_git_repo(self): + """检查当前目录是否是 Git 仓库""" + result = self.run_command("git rev-parse --is-inside-work-tree", check=False, silent=True) + return result and result.returncode == 0 + + def get_current_branch(self): + """获取当前分支名""" + result = self.run_command("git branch --show-current", silent=True) + return result.stdout.strip() if result else None + + def has_changes(self): + """检查是否有未提交的更改""" + result = self.run_command("git status --porcelain", silent=True) + return bool(result and result.stdout.strip()) + + def get_remote_url(self): + """获取远程仓库地址""" + result = self.run_command("git remote get-url origin", check=False, silent=True) + return result.stdout.strip() if result and result.returncode == 0 else None + + def config_remote(self): + """配置远程仓库地址""" + print("🔧 配置远程仓库地址") + + # 检查是否是 Git 仓库,如果不是则初始化 + if not self.is_git_repo(): + print("⚠️ 当前目录不是 Git 仓库") + init = input("是否初始化为 Git 仓库? (y/n): ").strip().lower() + if init == 'y': + result = self.run_command("git init") + if result: + print("✅ Git 仓库初始化成功") + else: + print("❌ Git 仓库初始化失败") + return + else: + print("❌ 操作已取消") + return + + current_url = self.get_remote_url() + if current_url: + print(f"当前远程仓库: {current_url}") + change = input("是否修改? (y/n): ").strip().lower() + if change != 'y': + return + + remote_url = input("请输入远程仓库地址 (如: https://github.com/username/repo.git): ").strip() + + if not remote_url: + print("❌ 远程仓库地址不能为空") + return + + # 检查是否已有 origin + if current_url: + result = self.run_command(f"git remote set-url origin {remote_url}") + else: + result = self.run_command(f"git remote add origin {remote_url}") + + if result: + print(f"✅ 远程仓库配置成功: {remote_url}") + + # 保存到配置文件 + repo_name = os.path.basename(self.repo_path) + if repo_name not in self.config: + self.config[repo_name] = {} + self.config[repo_name]['remote_url'] = remote_url + self.save_config() + + # 询问是否设置默认分支 + print("\n💡 提示: 首次推送前需要设置默认分支") + set_branch = input("是否设置默认分支为 main? (y/n): ").strip().lower() + if set_branch == 'y': + # 检查当前分支 + current_branch = self.get_current_branch() + if not current_branch: + # 创建初始提交 + print("\n📝 创建初始提交...") + self.run_command("git add .") + self.run_command('git commit -m "Initial commit" --allow-empty') + self.run_command("git branch -M main") + print("✅ 默认分支已设置为 main") + elif current_branch != 'main': + self.run_command("git branch -M main") + print("✅ 分支已重命名为 main") + else: + print("✅ 当前分支已是 main") + + def commit_changes(self, message=None): + """提交本地更改""" + if not self.has_changes(): + print("ℹ️ 没有需要提交的更改") + return True + + print("\n📝 检测到以下更改:") + self.run_command("git status --short") + + if message is None: + message = input("\n请输入提交信息: ").strip() + + if not message: + print("❌ 提交信息不能为空") + return False + + # 添加所有更改 + print("\n📦 正在暂存所有更改...") + result = self.run_command("git add -A") + if not result: + return False + + # 提交更改 + print(f"💾 正在提交: {message}") + result = self.run_command(f'git commit -m "{message}"') + if result: + print(f"✅ 提交成功") + return True + return False + + def force_push(self): + """纯粹的本地覆盖远程(不拉取,直接强制推送)""" + print("🚀 强制推送本地到远程") + + if not self.is_git_repo(): + print("❌ 当前目录不是 Git 仓库") + return + + branch = self.get_current_branch() + if not branch: + print("❌ 无法获取当前分支") + return + + print(f"📍 当前分支: {branch}") + + # 检查远程仓库 + remote_url = self.get_remote_url() + if not remote_url: + print("⚠️ 未配置远程仓库") + self.config_remote() + remote_url = self.get_remote_url() + if not remote_url: + return + + print(f"🌐 远程仓库: {remote_url}") + + # 提交本地更改 + print() + if not self.commit_changes(): # 改为交互式提交,不自动 + print("❌ 提交失败,推送中止") + return + + # 强制推送(不拉取远程) + print(f"\n⬆️ 正在强制推送到远程 ({branch})...") + result = self.run_command(f"git push -f origin {branch}") + + if result: + print(f"\n✅ 推送成功!") + else: + print("\n❌ 推送失败") + + def force_pull(self): + """纯粹的远程覆盖本地(不保留本地未推送的修改)""" + print("⬇️ 强制拉取远程到本地") + + if not self.is_git_repo(): + print("❌ 当前目录不是 Git 仓库") + return + + branch = self.get_current_branch() + if not branch: + print("❌ 无法获取当前分支") + return + + print(f"📍 当前分支: {branch}") + + # 检查远程仓库 + remote_url = self.get_remote_url() + if not remote_url: + print("⚠️ 未配置远程仓库") + self.config_remote() + return + + print(f"🌐 远程仓库: {remote_url}") + + # 检查本地更改 + if self.has_changes(): + print("\n⚠️ 检测到未提交的本地更改,这些更改将会被丢弃") + self.run_command("git status --short") + + # 先获取远程最新信息 + print(f"\n📡 正在获取远程仓库信息...") + self.run_command("git fetch origin") + + # 强制重置到远程版本 + print(f"⬇️ 正在强制拉取远程 ({branch})...") + self.run_command(f"git reset --hard origin/{branch}") + self.run_command("git clean -fd") + + print(f"\n✅ 拉取成功!") + + def smart_sync(self): + """智能同步(先拉取合并,再推送)""" + print("🔄 智能同步") + + if not self.is_git_repo(): + print("❌ 当前目录不是 Git 仓库") + return + + branch = self.get_current_branch() + if not branch: + print("❌ 无法获取当前分支") + return + + print(f"📍 当前分支: {branch}") + + # 检查远程仓库 + remote_url = self.get_remote_url() + if not remote_url: + print("⚠️ 未配置远程仓库") + self.config_remote() + return + + print(f"🌐 远程仓库: {remote_url}") + + # 提交本地更改 + print() + if self.has_changes(): + if not self.commit_changes(): # 改为交互式提交 + print("❌ 提交失败") + return + + # 拉取远程更改 + print(f"\n⬇️ 正在拉取远程更新 ({branch})...") + result = self.run_command(f"git pull origin {branch}", check=False) + + if result and result.returncode != 0: + # 如果有冲突 + if "conflict" in result.stderr.lower() or "conflict" in result.stdout.lower(): + print("\n⚠️ 检测到合并冲突!") + print("\n冲突文件:") + self.run_command("git diff --name-only --diff-filter=U") + + choice = input("\n选择操作:\n1. 保留本地版本\n2. 保留远程版本\n3. 手动解决后继续\n请选择 (1/2/3): ").strip() + + if choice == '1': + self.run_command("git checkout --ours .") + self.run_command("git add -A") + self.run_command('git commit --no-edit') + print("✅ 已保留本地版本") + elif choice == '2': + self.run_command("git checkout --theirs .") + self.run_command("git add -A") + self.run_command('git commit --no-edit') + print("✅ 已保留远程版本") + else: + print("ℹ️ 请手动解决冲突后执行: git add . && git commit") + return + else: + print("❌ 拉取失败") + return + else: + print("✅ 拉取成功") + + # 推送到远程 + print(f"\n⬆️ 正在推送到远程 ({branch})...") + push_result = self.run_command(f"git push origin {branch}") + + if push_result: + print(f"\n✅ 同步成功!") + else: + print("⚠️ 推送失败或无新内容需要推送") + + def show_log(self, num=10): + """查看提交历史并支持直接回退""" + print(f"📋 最近 {num} 次提交历史") + + if not self.is_git_repo(): + print("❌ 当前目录不是 Git 仓库") + return + + branch = self.get_current_branch() + print(f"📍 当前分支: {branch}\n") + + # 使用 git log 的简单格式,然后解析 + result = self.run_command(f'git log -{num} --format="COMMIT_START%nHASH:%H%nSUBJECT:%s%nAUTHOR:%an%nDATE:%ar%nCOMMIT_END"') + + if not result: + return + + commits = result.stdout.strip().split('COMMIT_START') + commit_hashes = [] + idx = 1 + + for commit in commits: + if not commit.strip(): + continue + + lines = commit.strip().split('\n') + commit_info = {} + for line in lines: + if ':' in line: + key, value = line.split(':', 1) + commit_info[key] = value.strip() + + if 'HASH' in commit_info: + hash_full = commit_info['HASH'] + hash_short = hash_full[:7] + subject = commit_info.get('SUBJECT', '') + date = commit_info.get('DATE', '') + + commit_hashes.append(hash_full) + print(f"{idx}. [{hash_short}] {subject} -- {date}") + idx += 1 + + # 询问是否回退 + print() + choice = input("是否回退版本? (输入数字1-10回退,直接回车或输入0跳过): ").strip() + + if not choice or choice == '0': + print("✅ 未进行回退") + return + + # 判断是数字还是哈希值 + if choice.isdigit(): + idx = int(choice) - 1 + if 0 <= idx < len(commit_hashes): + commit_hash = commit_hashes[idx][:7] + else: + print(f"❌ 无效的数字,请输入 1-{len(commit_hashes)}") + return + else: + commit_hash = choice + + # 验证提交是否存在 + verify = self.run_command(f"git cat-file -t {commit_hash}", check=False, silent=True) + if not verify or verify.returncode != 0: + print(f"❌ 提交 {commit_hash} 不存在") + return + + # 显示目标提交信息 + print(f"\n📍 即将回退到: {commit_hash}") + + # 选择回退方式 + print("\n回退方式:") + print("1. 软回退 (保留工作区和暂存区的更改)") + print("2. 混合回退 (保留工作区更改,清空暂存区) [推荐]") + print("3. 硬回退 (完全回退,丢弃所有更改)") + + mode_choice = input("\n请选择 (1/2/3,直接回车默认选2): ").strip() + + if not mode_choice: + mode_choice = '2' + + mode_map = { + '1': ('--soft', '软回退'), + '2': ('--mixed', '混合回退'), + '3': ('--hard', '硬回退') + } + + if mode_choice not in mode_map: + print("❌ 无效选择") + return + + mode, mode_name = mode_map[mode_choice] + + # 执行回退 + print(f"\n⏮️ 正在执行{mode_name}...") + result = self.run_command(f"git reset {mode} {commit_hash}") + + if result: + print(f"\n✅ {mode_name}成功!") + print(f"📍 已回退到: {commit_hash}\n") + self.run_command("git status --short") + else: + print(f"\n❌ 回退失败") + + def show_full_history(self): + """查看完整提交历史""" + print("📚 完整提交历史") + + if not self.is_git_repo(): + print("❌ 当前目录不是 Git 仓库") + return + + branch = self.get_current_branch() + print(f"📍 当前分支: {branch}\n") + + # 显示完整历史(简化格式以兼容 Windows) + self.run_command("git log --graph --oneline --decorate --all") + + def rollback(self): + """回退到指定版本""" + print("⏮️ 版本回退") + + if not self.is_git_repo(): + print("❌ 当前目录不是 Git 仓库") + return + + # 显示最近10次提交 + print("📋 最近10次提交:\n") + result = self.run_command("git log -10 --pretty=format:%H|%s|%an|%ar") + + if not result: + return + + lines = result.stdout.strip().split('\n') + commits = [] + + for i, line in enumerate(lines, 1): + if '|' in line: + hash_full, subject, author, date = line.split('|', 3) + hash_short = hash_full[:7] + commits.append(hash_full) + print(f"{i}. [{hash_short}] {subject}") + print(f" 作者: {author} | 时间: {date}\n") + + print() + + # 获取用户输入 + choice = input("请输入要回退到的版本 (输入数字1-10,或输入提交哈希值,q 取消): ").strip() + + if not choice or choice.lower() == 'q': + print("❌ 操作已取消") + return + + # 判断是数字还是哈希值 + if choice.isdigit(): + idx = int(choice) - 1 + if 0 <= idx < len(commits): + commit_hash = commits[idx][:7] + else: + print(f"❌ 无效的数字,请输入 1-{len(commits)}") + return + else: + commit_hash = choice + + # 验证提交是否存在 + verify = self.run_command(f"git cat-file -t {commit_hash}", check=False, silent=True) + if not verify or verify.returncode != 0: + print(f"❌ 提交 {commit_hash} 不存在") + return + + # 显示目标提交信息 + print(f"\n📍 即将回退到:") + self.run_command(f"git log -1 {commit_hash} --pretty=format:[%h] %s%n作者: %an | 时间: %ar") + + # 选择回退方式 + print("\n\n回退方式:") + print("1. 软回退 (保留工作区和暂存区的更改)") + print("2. 混合回退 (保留工作区更改,清空暂存区) [推荐]") + print("3. 硬回退 (完全回退,丢弃所有更改)") + + mode_choice = input("\n请选择 (1/2/3,输入 q 取消): ").strip() + + if mode_choice.lower() == 'q': + print("❌ 操作已取消") + return + + mode_map = { + '1': ('--soft', '软回退'), + '2': ('--mixed', '混合回退'), + '3': ('--hard', '硬回退') + } + + if mode_choice not in mode_map: + print("❌ 无效选择") + return + + mode, mode_name = mode_map[mode_choice] + + # 执行回退 + print(f"\n⏮️ 正在执行{mode_name}...") + result = self.run_command(f"git reset {mode} {commit_hash}") + + if result: + print(f"\n✅ {mode_name}成功!") + print(f"📍 已回退到: {commit_hash}\n") + self.run_command("git status --short") + else: + print(f"\n❌ 回退失败") + + +def main(): + tool = GitSyncTool() + + if len(sys.argv) < 2: + print(__doc__) + return + + command = sys.argv[1].lower() + + if command == 'push': + tool.force_push() + elif command == 'pull': + tool.force_pull() + elif command == 'sync': + tool.smart_sync() + elif command == 'log': + tool.show_log(5) + elif command == 'history': + tool.show_full_history() + elif command == 'rollback': + tool.rollback() + elif command == 'config': + tool.config_remote() + else: + print(f"❌ 未知命令: {command}") + print(__doc__) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/image/comfyui-node-apikey.png b/image/comfyui-node-apikey.png new file mode 100644 index 0000000000000000000000000000000000000000..75c2d06be3a6a73bc35c77bbce7aec6ff608610b GIT binary patch literal 78550 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⋙gH_;EeXG1}=by{t?8N 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 JPDHLkV1ff#k?H^d literal 0 HcmV?d00001 diff --git a/image/comfyui-node-auth.png b/image/comfyui-node-auth.png new file mode 100644 index 0000000000000000000000000000000000000000..98aa1a8141e0d0e79d59de01cef2c44f3cb17f1e GIT binary patch literal 115436 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 URdl_Gxc~qF07*qoM6N<$f&)o;v;Y7A literal 0 HcmV?d00001 diff --git a/py/IMAGE_GPT_apikey.py b/py/IMAGE_GPT_apikey.py new file mode 100644 index 0000000..317f203 --- /dev/null +++ b/py/IMAGE_GPT_apikey.py @@ -0,0 +1,312 @@ +""" +PD: OpenAI GPT Image Node (ComfyUI API Key) +使用 ComfyUI API Key 调用 ComfyUI 代理 API +参数和官方节点完全一样 +""" + +import torch +import requests +import time +import io +import base64 +import numpy as np +from PIL import Image + + +def tensor_to_bytes(tensor, max_pixels=2048*2048): + """将 Tensor 转换为 PNG BytesIO,并进行下采样""" + if tensor.ndim == 4: + tensor = tensor[0] + + # 下采样大图片 + height, width = tensor.shape[:2] + current_pixels = height * width + if current_pixels > max_pixels: + scale = (max_pixels / current_pixels) ** 0.5 + new_height = int(height * scale) + new_width = int(width * scale) + + # 使用 PIL 进行高质量缩放 + array = np.clip(255. * tensor.cpu().numpy(), 0, 255).astype(np.uint8) + image = Image.fromarray(array) + image = image.resize((new_width, new_height), Image.Resampling.LANCZOS) + else: + array = np.clip(255. * tensor.cpu().numpy(), 0, 255).astype(np.uint8) + image = Image.fromarray(array) + + buffered = io.BytesIO() + image.save(buffered, format="PNG") + buffered.seek(0) + return buffered + + +def load_image_to_tensor(image_data): + """将图片数据(URL 或 bytes)转换为 Tensor""" + try: + if isinstance(image_data, str) and image_data.startswith("http"): + response = requests.get(image_data, timeout=30) + response.raise_for_status() + img = Image.open(io.BytesIO(response.content)) + else: + img = Image.open(io.BytesIO(image_data)) + + img = img.convert("RGB") + image_np = np.array(img).astype(np.float32) / 255.0 + return torch.from_numpy(image_np).unsqueeze(0) + except Exception as e: + print(f"[IMAGE_GPT_APIKEY] Error loading image: {e}") + return torch.zeros((1, 512, 512, 3)) + + +class PDOpenAIGPTImageAPIKey: + """ + PD: OpenAI GPT Image (API Key) + 使用 ComfyUI API Key 调用 ComfyUI 代理 API + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "api_key": ("STRING", { + "default": "", + "multiline": False, + "placeholder": "Your ComfyUI API Key" + }), + "prompt": ("STRING", { + "multiline": True, + "default": "", + "tooltip": "Text prompt for GPT Image" + }), + "seed": ("INT", { + "default": 0, + "min": 0, + "max": 2**31 - 1, + "step": 1, + "tooltip": "not implemented yet in backend" + }), + "quality": (["low", "medium", "high"], { + "default": "low", + "tooltip": "Image quality, affects cost and generation time" + }), + "background": (["auto", "opaque", "transparent"], { + "default": "auto", + "tooltip": "Return image with or without background" + }), + "size": (["auto", "1024x1024", "1024x1536", "1536x1024"], { + "default": "auto", + "tooltip": "Image size" + }), + "n": ("INT", { + "default": 1, + "min": 1, + "max": 8, + "step": 1, + "tooltip": "How many images to generate" + }), + }, + "optional": { + "image": ("IMAGE", { + "tooltip": "Optional reference image for image editing." + }), + "mask": ("MASK", { + "tooltip": "Optional mask for inpainting (white areas will be replaced)" + }), + "model": (["gpt-image-1", "gpt-image-1.5"], { + "default": "gpt-image-1" + }), + }, + "hidden": { + "unique_id": "UNIQUE_ID", + } + } + + RETURN_TYPES = ("IMAGE", "STRING") + RETURN_NAMES = ("image", "info") + FUNCTION = "generate_image" + CATEGORY = "PD_Tools/Image_Generation" + + def generate_image(self, api_key, prompt, seed, quality, background, size, n, unique_id, image=None, mask=None, model="gpt-image-1"): + """生成或编辑图片""" + + # 验证 API Key + if not api_key or not api_key.strip(): + error_msg = "Error: ComfyUI API Key is required" + print(f"[IMAGE_GPT_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + # 清理 API Key + api_key = api_key.strip() + + # 判断模式:编辑 vs 生成 + is_edit_mode = image is not None + + # ComfyUI 代理 API URL + if is_edit_mode: + base_url = "https://api.comfy.org/proxy/openai/images/edits" + else: + base_url = "https://api.comfy.org/proxy/openai/images/generations" + + start_time = time.time() + + try: + if is_edit_mode: + # 图片编辑模式 - 使用 multipart/form-data + # 准备文件 + files = {} + img_bytes = tensor_to_bytes(image) + files['image'] = ('image.png', img_bytes, 'image/png') + + # 处理 mask + if mask is not None: + m_tensor = mask + if m_tensor.ndim == 3: + m_tensor = m_tensor[0] + + mask_h, mask_w = m_tensor.shape + rgba = np.zeros((mask_h, mask_w, 4), dtype=np.uint8) + + mask_np = m_tensor.cpu().numpy() + alpha = ((1.0 - mask_np) * 255).astype(np.uint8) + rgba[..., 3] = alpha + + mask_pil = Image.fromarray(rgba) + mask_buffer = io.BytesIO() + mask_pil.save(mask_buffer, format="PNG") + mask_buffer.seek(0) + files['mask'] = ('mask.png', mask_buffer, 'image/png') + + # 表单数据 - multipart/form-data 模式下所有值都应该是字符串 + data = { + "model": model, + "prompt": prompt, + "n": str(n), + "size": size, + "quality": quality, + "background": background, + "moderation": "low" + } + + # 请求头 + headers = { + "X-API-KEY": api_key, + "Accept": "application/json", + "User-Agent": "ComfyUI-PD-Node/2.0" + } + + print(f"[IMAGE_GPT_APIKEY] Sending edit request") + print(f"[IMAGE_GPT_APIKEY] Model: {model}, Size: {size}, Quality: {quality}") + print(f"[IMAGE_GPT_APIKEY] Image size: {image.shape}, Mask: {'Yes' if mask is not None else 'No'}") + + response = requests.post(base_url, headers=headers, files=files, data=data, timeout=300) + + else: + # 文生图模式 - 使用 JSON + payload = { + "model": model, + "prompt": prompt, + "n": n, + "size": size, + "quality": quality, + "background": background, + "response_format": "url" + } + + headers = { + "X-API-KEY": api_key, + "Accept": "application/json", + "Content-Type": "application/json", + "User-Agent": "ComfyUI-PD-Node/2.0" + } + + print(f"[IMAGE_GPT_APIKEY] Sending generation request") + print(f"[IMAGE_GPT_APIKEY] Model: {model}, Size: {size}, Quality: {quality}") + print(f"[IMAGE_GPT_APIKEY] Prompt length: {len(prompt)} chars") + + response = requests.post(base_url, headers=headers, json=payload, timeout=300) + + # 检查响应 + if response.status_code != 200: + error_msg = f"API Error {response.status_code}: {response.text[:200]}" + print(f"[IMAGE_GPT_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + result = response.json() + data_list = result.get("data", []) + + if not data_list: + error_msg = "Error: No image data in response" + print(f"[IMAGE_GPT_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + # 提取图片 + image_tensors = [] + for item in data_list: + if "url" in item: + img_tensor = load_image_to_tensor(item["url"]) + image_tensors.append(img_tensor) + elif "b64_json" in item: + img_data = base64.b64decode(item["b64_json"]) + img_tensor = load_image_to_tensor(img_data) + image_tensors.append(img_tensor) + + if not image_tensors: + error_msg = "Error: Failed to process output images" + print(f"[IMAGE_GPT_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + final_image = torch.cat(image_tensors, dim=0) + + # 计算耗时和成本 + end_time = time.time() + duration = end_time - start_time + + # 估算成本 + cost_map = { + "gpt-image-1": {"low": 0.02, "medium": 0.04, "high": 0.08}, + "gpt-image-1.5": {"low": 0.03, "medium": 0.06, "high": 0.12} + } + cost = cost_map.get(model, {}).get(quality, 0.04) + total_cost = cost * n + + info_str = ( + f"Model: {model}\n" + f"Mode: {'Edit' if is_edit_mode else 'Generate'}\n" + f"Status: Success\n" + f"Time: {duration:.2f}s\n" + f"Images: {len(image_tensors)}\n" + f"Size: {size}\n" + f"Quality: {quality}\n" + f"Background: {background}\n" + f"Est. Cost: ${total_cost:.3f}" + ) + + print(f"[IMAGE_GPT_APIKEY] Success! Generated {len(image_tensors)} images in {duration:.2f}s") + return (final_image, info_str) + + except requests.exceptions.Timeout: + error_msg = "Error: Request timeout (300s)" + print(f"[IMAGE_GPT_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + except requests.exceptions.ConnectionError as e: + error_msg = f"Error: Connection failed - {str(e)}" + print(f"[IMAGE_GPT_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + except Exception as e: + error_msg = f"Error: {str(e)}" + print(f"[IMAGE_GPT_APIKEY] {error_msg}") + import traceback + traceback.print_exc() + return (torch.zeros((1, 512, 512, 3)), error_msg) + + +# 节点注册 +NODE_CLASS_MAPPINGS = { + "PDOpenAIGPTImageAPIKey": PDOpenAIGPTImageAPIKey +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "PDOpenAIGPTImageAPIKey": "PD: GPT Image (apikey)" +} diff --git a/py/IMAGE_GPT_authtoken.py b/py/IMAGE_GPT_authtoken.py new file mode 100644 index 0000000..d8d392e --- /dev/null +++ b/py/IMAGE_GPT_authtoken.py @@ -0,0 +1,313 @@ +""" +PD: OpenAI GPT Image Node (ComfyUI Auth Token) +基于 gemini_image_api 的 Auth Token 认证方式 +支持文生图和图片编辑 +""" + +import torch +import requests +import time +import io +import base64 +import numpy as np +from PIL import Image + + +def tensor_to_bytes(tensor, max_pixels=2048*2048): + """将 Tensor 转换为 PNG BytesIO,并进行下采样""" + if tensor.ndim == 4: + tensor = tensor[0] + + # 下采样大图片 + height, width = tensor.shape[:2] + current_pixels = height * width + if current_pixels > max_pixels: + scale = (max_pixels / current_pixels) ** 0.5 + new_height = int(height * scale) + new_width = int(width * scale) + + # 使用 PIL 进行高质量缩放 + array = np.clip(255. * tensor.cpu().numpy(), 0, 255).astype(np.uint8) + image = Image.fromarray(array) + image = image.resize((new_width, new_height), Image.Resampling.LANCZOS) + else: + array = np.clip(255. * tensor.cpu().numpy(), 0, 255).astype(np.uint8) + image = Image.fromarray(array) + + buffered = io.BytesIO() + image.save(buffered, format="PNG") + buffered.seek(0) + return buffered + + +def load_image_to_tensor(image_data): + """将图片数据(URL 或 bytes)转换为 Tensor""" + try: + if isinstance(image_data, str) and image_data.startswith("http"): + response = requests.get(image_data, timeout=30) + response.raise_for_status() + img = Image.open(io.BytesIO(response.content)) + else: + img = Image.open(io.BytesIO(image_data)) + + img = img.convert("RGB") + image_np = np.array(img).astype(np.float32) / 255.0 + return torch.from_numpy(image_np).unsqueeze(0) + except Exception as e: + print(f"[IMAGE_GPT_AUTHTOKEN] Error loading image: {e}") + return torch.zeros((1, 512, 512, 3)) + + +class PDOpenAIGPTImageAuthToken: + """ + PD: OpenAI GPT Image (Auth Token) + 使用 ComfyUI Auth Token 调用 GPT Image API + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "auth_token": ("STRING", { + "default": "", + "multiline": False, + "placeholder": "Paste your Auth Token here" + }), + "prompt": ("STRING", { + "multiline": True, + "default": "", + "tooltip": "Describe what you want to generate or edit" + }), + "model": (["gpt-image-1", "gpt-image-1.5"], { + "default": "gpt-image-1", + "tooltip": "GPT Image model version" + }), + "quality": (["low", "medium", "high"], { + "default": "low", + "tooltip": "Image quality, affects cost and generation time" + }), + "background": (["auto", "opaque", "transparent"], { + "default": "auto", + "tooltip": "Background transparency (GPT Image only)" + }), + "size": (["auto", "1024x1024", "1024x1536", "1536x1024"], { + "default": "auto", + "tooltip": "Image size" + }), + "n": ("INT", { + "default": 1, + "min": 1, + "max": 8, + "step": 1, + "tooltip": "Number of images to generate" + }), + "seed": ("INT", { + "default": 0, + "min": 0, + "max": 0xFFFFFFFFFFFFFFFF + }), + }, + "optional": { + "image": ("IMAGE", {"default": None, "tooltip": "Input image for editing"}), + "mask": ("MASK", {"default": None, "tooltip": "Mask for inpainting"}), + }, + "hidden": { + "unique_id": "UNIQUE_ID", + } + } + + RETURN_TYPES = ("IMAGE", "STRING") + RETURN_NAMES = ("image", "info") + FUNCTION = "generate_image" + CATEGORY = "PD_Tools/Image_Generation" + + def generate_image(self, auth_token, prompt, model, quality, background, size, n, seed, unique_id, image=None, mask=None): + """生成或编辑图片""" + + # 验证 Token + if not auth_token or not auth_token.strip(): + error_msg = "Error: Auth Token is required" + print(f"[IMAGE_GPT_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + # 清理 Token + auth_token = auth_token.strip() + if auth_token.lower().startswith("bearer "): + auth_token = auth_token[7:].strip() + + # API 基础地址 + base_url = "https://api.comfy.org" + + # 判断模式:编辑 vs 生成 + is_edit_mode = image is not None + + start_time = time.time() + + try: + if is_edit_mode: + # 图片编辑模式 - 使用 multipart/form-data + url = f"{base_url}/proxy/openai/images/edits" + + # 准备文件 + files = {} + img_bytes = tensor_to_bytes(image) + files['image'] = ('image.png', img_bytes, 'image/png') + + # 处理 mask + if mask is not None: + m_tensor = mask + if m_tensor.ndim == 3: + m_tensor = m_tensor[0] + + mask_h, mask_w = m_tensor.shape + rgba = np.zeros((mask_h, mask_w, 4), dtype=np.uint8) + + mask_np = m_tensor.cpu().numpy() + alpha = ((1.0 - mask_np) * 255).astype(np.uint8) + rgba[..., 3] = alpha + + mask_pil = Image.fromarray(rgba) + mask_buffer = io.BytesIO() + mask_pil.save(mask_buffer, format="PNG") + mask_buffer.seek(0) + files['mask'] = ('mask.png', mask_buffer, 'image/png') + + # 表单数据 - multipart/form-data 模式下所有值都应该是字符串 + data = { + "model": model, + "prompt": prompt, + "n": str(n), + "size": size, + "quality": quality, + "background": background, + "moderation": "low" + } + + # 请求头 + headers = { + "Authorization": f"Bearer {auth_token}", + "User-Agent": "ComfyUI-PD-Node/2.0" + } + + print(f"[IMAGE_GPT_AUTHTOKEN] Sending edit request to {url}") + print(f"[IMAGE_GPT_AUTHTOKEN] Model: {model}, Size: {size}, Quality: {quality}, Background: {background}") + print(f"[IMAGE_GPT_AUTHTOKEN] Image size: {image.shape}, Mask: {'Yes' if mask is not None else 'No'}") + + response = requests.post(url, headers=headers, files=files, data=data, timeout=300) + + else: + # 文生图模式 - 使用 JSON + url = f"{base_url}/proxy/openai/images/generations" + + payload = { + "model": model, + "prompt": prompt, + "n": n, + "size": size, + "quality": quality, + "background": background, + "moderation": "low", + "response_format": "url" + } + + headers = { + "Authorization": f"Bearer {auth_token}", + "Content-Type": "application/json", + "User-Agent": "ComfyUI-PD-Node/2.0" + } + + print(f"[IMAGE_GPT_AUTHTOKEN] Sending generation request to {url}") + print(f"[IMAGE_GPT_AUTHTOKEN] Model: {model}, Size: {size}, Quality: {quality}, Background: {background}") + print(f"[IMAGE_GPT_AUTHTOKEN] Prompt length: {len(prompt)} chars") + + response = requests.post(url, headers=headers, json=payload, timeout=300) + + # 检查响应 + if response.status_code != 200: + error_msg = f"API Error {response.status_code}: {response.text[:200]}" + print(f"[IMAGE_GPT_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + result = response.json() + data_list = result.get("data", []) + + if not data_list: + error_msg = "Error: No image data in response" + print(f"[IMAGE_GPT_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + # 提取图片 + image_tensors = [] + for item in data_list: + if "url" in item: + img_tensor = load_image_to_tensor(item["url"]) + image_tensors.append(img_tensor) + elif "b64_json" in item: + img_data = base64.b64decode(item["b64_json"]) + img_tensor = load_image_to_tensor(img_data) + image_tensors.append(img_tensor) + + if not image_tensors: + error_msg = "Error: Failed to process output images" + print(f"[IMAGE_GPT_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + final_image = torch.cat(image_tensors, dim=0) + + # 计算耗时和成本 + end_time = time.time() + duration = end_time - start_time + + # 估算成本 + if model == "gpt-image-1": + # GPT Image 1: $10/1M input tokens, $40/1M output tokens + # 估算:约 1000 tokens input, 2000 tokens output per image + cost = (1000 * 10 + 2000 * 40) / 1_000_000 + elif model == "gpt-image-1.5": + # GPT Image 1.5: $8/1M input tokens, $32/1M output tokens + cost = (1000 * 8 + 2000 * 32) / 1_000_000 + else: + cost = 0.10 # 默认估算 + total_cost = cost * n + + info_str = ( + f"Model: {model}\n" + f"Mode: {'Edit' if is_edit_mode else 'Generate'}\n" + f"Status: Success\n" + f"Time: {duration:.2f}s\n" + f"Images: {len(image_tensors)}\n" + f"Size: {size}\n" + f"Quality: {quality}\n" + f"Background: {background}\n" + f"Est. Cost: ${total_cost:.4f}" + ) + + print(f"[IMAGE_GPT_AUTHTOKEN] Success! Generated {len(image_tensors)} images in {duration:.2f}s") + return (final_image, info_str) + + except requests.exceptions.Timeout: + error_msg = "Error: Request timeout (300s)" + print(f"[IMAGE_GPT_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + except requests.exceptions.ConnectionError as e: + error_msg = f"Error: Connection failed - {str(e)}" + print(f"[IMAGE_GPT_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + except Exception as e: + error_msg = f"Error: {str(e)}" + print(f"[IMAGE_GPT_AUTHTOKEN] {error_msg}") + import traceback + traceback.print_exc() + return (torch.zeros((1, 512, 512, 3)), error_msg) + + +# 节点注册 +NODE_CLASS_MAPPINGS = { + "PDOpenAIGPTImageAuthToken": PDOpenAIGPTImageAuthToken +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "PDOpenAIGPTImageAuthToken": "PD: GPT Image (comfyui_AuthToken)" +} diff --git a/py/IMAGE_GeminiNanoBanana2.py b/py/IMAGE_GeminiNanoBanana2.py new file mode 100644 index 0000000..5d82445 --- /dev/null +++ b/py/IMAGE_GeminiNanoBanana2.py @@ -0,0 +1,279 @@ +""" +PD: Nano Banana 2 (ComfyUI Key) +基于 Google Gemini 3.1 Flash Image 模型的图像生成/编辑节点 +支持进度反馈、Token 成本计算、及其独立输出接口 +""" + +import torch +import base64 +import json +import time +import uuid +import requests +import numpy as np +import io +from PIL import Image +from typing import Optional, List +from server import PromptServer +import comfy.utils + +# 默认系统提示词 +GEMINI_IMAGE_SYS_PROMPT = ( + "You are an expert image-generation engine. You must ALWAYS produce an image.\n" + "Interpret all user input—regardless of " + "format, intent, or abstraction—as literal visual directives for image composition.\n" + "If a prompt is conversational or lacks specific visual details, " + "you must creatively invent a concrete visual scenario that depicts the concept.\n" + "Prioritize generating the visual representation above any text, formatting, or conversational requests." +) + +def tensor_to_base64(tensor): + """将 Tensor 转换为 base64 字符串""" + if tensor.ndim == 4: + tensor = tensor[0] + + array = np.clip(255. * tensor.cpu().numpy(), 0, 255).astype(np.uint8) + image = Image.fromarray(array) + buffered = io.BytesIO() + image.save(buffered, format="PNG") + return base64.b64encode(buffered.getvalue()).decode("utf-8") + +def bytes_to_tensor(data): + """将图片字节数据转换为 Tensor""" + try: + img = Image.open(io.BytesIO(data)).convert("RGB") + image_np = np.array(img).astype(np.float32) / 255.0 + return torch.from_numpy(image_np).unsqueeze(0) + except Exception as e: + print(f"[PD_NB2] Image decode error: {e}") + return torch.zeros((1, 512, 512, 3)) + +class PDGeminiNanoBanana2: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "comfy_api_key": ("STRING", { + "default": "", + "multiline": False, + "placeholder": "Paste your ComfyUI API Key here" + }), + "prompt": ("STRING", { + "multiline": True, + "default": "A futuristic cityscape with flying cars and neon lights", + }), + "model": (["Nano Banana 2 (Gemini 3.1 Flash Image)"], { + "default": "Nano Banana 2 (Gemini 3.1 Flash Image)" + }), + "seed": ("INT", { + "default": 42, + "min": 0, + "max": 0x7FFFFFFF, + }), + "aspect_ratio": (["auto", "1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"], { + "default": "auto", + }), + "resolution": (["1K", "2K", "4K"], { + "default": "1K", + }), + "response_modalities": (["IMAGE", "IMAGE+TEXT"], { + "default": "IMAGE", + }), + "thinking_level": (["MINIMAL", "HIGH"], { + "default": "MINIMAL" + }), + }, + "optional": { + "images": ("IMAGE", ), + "files": ("GEMINI_INPUT_FILES", ), + "system_prompt": ("STRING", { + "multiline": True, + "default": GEMINI_IMAGE_SYS_PROMPT, + }), + }, + "hidden": { + "unique_id": "UNIQUE_ID", + } + } + + RETURN_TYPES = ("IMAGE", "STRING", "STRING") + RETURN_NAMES = ("image", "info", "price") + FUNCTION = "generate_image" + CATEGORY = "PD_Tools/Image_Generation" + + def generate_image(self, comfy_api_key, prompt, model, seed, aspect_ratio, resolution, response_modalities, thinking_level, unique_id, images=None, files=None, system_prompt=""): + pbar = comfy.utils.ProgressBar(100) + pbar.update(10) + + if not comfy_api_key or not comfy_api_key.strip(): + return (torch.zeros((1, 512, 512, 3)), "Error: Missing ComfyUI API Key", "$0.00") + + api_key = comfy_api_key.strip() + api_model = "gemini-3.1-flash-image-preview" + + # 发送进度文字到前端 + self._send_status(unique_id, "Preparing tokens...") + + # 构建请求内容 + parts = [{"text": prompt}] + + if images is not None: + for i in range(min(images.shape[0], 14)): + b64_str = tensor_to_base64(images[i]) + parts.append({ + "inlineData": { + "mimeType": "image/png", + "data": b64_str + } + }) + + # Files 输入处理 + if files: + for file_part in files: + if hasattr(file_part, "model_dump"): + parts.append(file_part.model_dump(exclude_none=True)) + else: + parts.append(file_part) + + # 核心参数修正:匹配官方 Pydantic 模型的 camelCase 结构 + # 且不发送 seed (官方 GeminiNanoBanana2.execute 并没有发送 seed 到 API) + image_config = { + "imageSize": resolution, + "imageOutputOptions": {"mimeType": "image/png"} + } + if aspect_ratio != "auto": + image_config["aspectRatio"] = aspect_ratio + + generation_config = { + "responseModalities": (["IMAGE"] if response_modalities == "IMAGE" else ["TEXT", "IMAGE"]), + "imageConfig": image_config, + "thinkingConfig": {"thinkingLevel": thinking_level} + } + + payload = { + "contents": [{ + "role": "user", + "parts": parts + }], + "generationConfig": generation_config + } + + if system_prompt and system_prompt.strip(): + payload["systemInstruction"] = { + "parts": [{"text": system_prompt.strip()}] + } + + headers = { + "X-API-KEY": api_key, + "Accept": "application/json", + "Content-Type": "application/json", + "User-Agent": "ComfyUI-PD-Node/2.0" + } + + base_url = f"https://api.comfy.org/proxy/vertexai/gemini/{api_model}" + + self._send_status(unique_id, "Sending request to Google...") + pbar.update(30) + + start_time = time.time() + try: + # 打印发送的 Payload 调试 (可选) + # print(f"[PD_NB2] Payload: {json.dumps(payload)}") + + response = requests.post(base_url, headers=headers, json=payload, timeout=120) + pbar.update(80) + + if response.status_code != 200: + error_body = response.text + error_msg = f"API Error {response.status_code}: {error_body}" + self._send_status(unique_id, "Error occurred") + return (torch.zeros((1, 512, 512, 3)), error_msg, "N/A") + + result = response.json() + image_tensors = [] + text_parts = [] + + self._send_status(unique_id, "Processing response...") + + candidates = result.get("candidates", []) + for cand in candidates: + content = cand.get("content", {}) + parts_out = content.get("parts", []) + for part in parts_out: + inline_data = part.get("inline_data") or part.get("inlineData") + if inline_data: + data_b64 = inline_data.get("data") + if data_b64: + raw_data = base64.b64decode(data_b64) + image_tensors.append(bytes_to_tensor(raw_data)) + + if "text" in part and part["text"]: + text_parts.append(part["text"]) + + if not image_tensors: + return (torch.zeros((1, 512, 512, 3)), "Error: No images found in response", "N/A") + + final_image = torch.cat(image_tensors, dim=0) + final_text = "\n".join(text_parts) if text_parts else "No description" + + # 计算成本 + cost_info = self._calculate_cost(result, api_model, time.time() - start_time) + + pbar.update(100) + self._send_status(unique_id, "Success") + + return (final_image, final_text, cost_info) + + except Exception as e: + self._send_status(unique_id, "Exception caught") + return (torch.zeros((1, 512, 512, 3)), f"Error: {str(e)}", "N/A") + + def _send_status(self, node_id, text): + """发送状态文字到节点下方显示""" + try: + PromptServer.instance.send_sync("progress_text", {"text": text, "node": node_id}) + except: + pass + + def _calculate_cost(self, result, model, duration): + """基于 API 响应计算成本""" + usage = result.get("usageMetadata", {}) + prompt_tokens = usage.get("promptTokenCount", 0) + candidates_tokens = usage.get("candidatesTokenCount", 0) + details = usage.get("candidatesTokensDetails", []) + thoughts_tokens = usage.get("thoughtsTokenCount", 0) + + # 价格配置 (3.1 Flash Image Preview) + prices = {"input": 0.5, "output_text": 3.0, "output_image": 60.0} + + text_tokens = thoughts_tokens + img_tokens = 0 + + for d in details: + modality = d.get("modality") + count = d.get("tokenCount", 0) + if modality == "IMAGE": + img_tokens += count + else: + text_tokens += count + + if not details and candidates_tokens > 0: + text_tokens += candidates_tokens + + input_cost = (prompt_tokens / 1_000_000) * prices["input"] + text_cost = (text_tokens / 1_000_000) * prices["output_text"] + img_cost = (img_tokens / 1_000_000) * prices["output_image"] + total_cost = input_cost + text_cost + img_cost + + info = [ + f"Model: {model}", + f"Status: Success", + f"Time: {duration:.2f}s", + f"Tokens: In:{prompt_tokens:,} | Out Text:{text_tokens:,} | Out Img:{img_tokens:,}", + f"Est. Cost: ${total_cost:.6f}" + ] + return "\n".join(info) + +# 注册 +NODE_CLASS_MAPPINGS = {"PDGeminiNanoBanana2": PDGeminiNanoBanana2} +NODE_DISPLAY_NAME_MAPPINGS = {"PDGeminiNanoBanana2": "PD: Nano Banana 2 (ComfyUI Key)"} diff --git a/py/IMGE_GeminiNode_apikey.py b/py/IMGE_GeminiNode_apikey.py new file mode 100644 index 0000000..b72c782 --- /dev/null +++ b/py/IMGE_GeminiNode_apikey.py @@ -0,0 +1,284 @@ +""" +PD: Gemini Image Generation Node (ComfyUI API Key) +使用 ComfyUI API Key 调用 ComfyUI 代理 API +参数和官方节点完全一样 +""" + +import torch +import requests +import time +import io +import base64 +import numpy as np +from PIL import Image + +# 默认系统提示词(来自 ComfyUI 官方 API 节点) +GEMINI_IMAGE_SYS_PROMPT = ( + "You are an expert image-generation engine. You must ALWAYS produce an image.\n" + "Interpret all user input—regardless of " + "format, intent, or abstraction—as literal visual directives for image composition.\n" + "If a prompt is conversational or lacks specific visual details, " + "you must creatively invent a concrete visual scenario that depicts the concept.\n" + "Prioritize generating the visual representation above any text, formatting, or conversational requests." +) + + +def tensor_to_base64(tensor): + """将 Tensor 转换为 base64 字符串""" + if tensor.ndim == 4: + tensor = tensor[0] + + array = np.clip(255. * tensor.cpu().numpy(), 0, 255).astype(np.uint8) + image = Image.fromarray(array) + buffered = io.BytesIO() + image.save(buffered, format="PNG") + return base64.b64encode(buffered.getvalue()).decode("utf-8") + + +def bytes_to_tensor(data): + """将图片字节数据转换为 Tensor""" + try: + img = Image.open(io.BytesIO(data)).convert("RGB") + image_np = np.array(img).astype(np.float32) / 255.0 + return torch.from_numpy(image_np).unsqueeze(0) + except Exception as e: + print(f"[GEMINI_APIKEY] Image decode error: {e}") + return torch.zeros((1, 512, 512, 3)) + + +class PDGeminiImageGenAPIKey: + """ + PD: Gemini Image Generation (API Key) + 使用 ComfyUI API Key 调用 ComfyUI 代理 API + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "api_key": ("STRING", { + "default": "", + "multiline": False, + "placeholder": "Your ComfyUI API Key" + }), + "prompt": ("STRING", { + "multiline": True, + "default": "A futuristic city with flying cars", + "tooltip": "Describe what you want to generate" + }), + "model": ([ + "gemini-2.5-flash-image", + "gemini-2.5-flash-image-preview" + ], { + "default": "gemini-2.5-flash-image" + }), + "aspect_ratio": ([ + "auto", "1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9" + ], { + "default": "auto" + }), + "response_modalities": (["IMAGE+TEXT", "IMAGE"], { + "default": "IMAGE+TEXT", + "tooltip": "Choose 'IMAGE' for image-only output, or 'IMAGE+TEXT' for both" + }), + "seed": ("INT", { + "default": 42, + "min": 0, + "max": 0xFFFFFFFFFFFFFFFF + }), + }, + "optional": { + "image_ref": ("IMAGE", { + "tooltip": "Reference image(s) for image-to-image generation" + }), + "system_prompt": ("STRING", { + "multiline": True, + "default": GEMINI_IMAGE_SYS_PROMPT, + "tooltip": "Optional system instructions" + }), + }, + "hidden": { + "unique_id": "UNIQUE_ID", + } + } + + RETURN_TYPES = ("IMAGE", "STRING") + RETURN_NAMES = ("image", "info") + FUNCTION = "generate_image" + CATEGORY = "PD_Tools/Image_Generation" + + def generate_image(self, api_key, prompt, model, aspect_ratio, response_modalities, seed, unique_id, image_ref=None, system_prompt=""): + """生成图片""" + + # 验证 API Key + if not api_key or not api_key.strip(): + error_msg = "Error: ComfyUI API Key is required" + print(f"[GEMINI_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + # 清理 API Key + api_key = api_key.strip() + + # ComfyUI 代理 API URL + base_url = f"https://api.comfy.org/proxy/vertexai/gemini/{model}" + + # 构建请求内容 + parts = [] + + # 添加用户提示词 + parts.append({"text": prompt}) + + # 添加参考图片(如果有) + if image_ref is not None: + for i in range(image_ref.shape[0]): + b64_str = tensor_to_base64(image_ref[i]) + parts.append({ + "inlineData": { + "mimeType": "image/png", + "data": b64_str + } + }) + print(f"[GEMINI_APIKEY] Added reference image {i+1}") + + # 生成配置 + generation_config = { + "responseModalities": ["IMAGE"] if response_modalities == "IMAGE" else ["TEXT", "IMAGE"] + } + + # 图片配置 + if aspect_ratio != "auto": + generation_config["imageConfig"] = { + "aspectRatio": aspect_ratio + } + + # 系统指令 + system_instruction = None + if system_prompt and system_prompt.strip(): + system_instruction = { + "parts": [{"text": system_prompt.strip()}] + } + + # 完整请求体 + payload = { + "contents": [{ + "role": "user", + "parts": parts + }], + "generationConfig": generation_config + } + + if system_instruction: + payload["systemInstruction"] = system_instruction + + # 请求头 + headers = { + "X-API-KEY": api_key, + "Accept": "application/json", + "Content-Type": "application/json", + "User-Agent": "ComfyUI-PD-Node/2.0" + } + + start_time = time.time() + + try: + print(f"[GEMINI_APIKEY] Sending request to {model}") + print(f"[GEMINI_APIKEY] Aspect Ratio: {aspect_ratio}") + + response = requests.post(base_url, headers=headers, json=payload, timeout=120) + + # 检查响应 + if response.status_code != 200: + error_msg = f"API Error {response.status_code}: {response.text[:200]}" + print(f"[GEMINI_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + result = response.json() + + # 提取图片和文本 + image_tensors = [] + text_parts = [] + candidates = result.get("candidates", []) + + if not candidates: + error_msg = "Error: No candidates in response" + print(f"[GEMINI_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + for cand in candidates: + content = cand.get("content", {}) + parts = content.get("parts", []) + + for part in parts: + # 提取图片 + inline_data = part.get("inline_data") or part.get("inlineData") + + if inline_data: + mime = inline_data.get("mime_type") or inline_data.get("mimeType") + data_b64 = inline_data.get("data") + + if mime in ["image/png", "image/jpeg"] and data_b64: + raw_data = base64.b64decode(data_b64) + image_tensors.append(bytes_to_tensor(raw_data)) + print(f"[GEMINI_APIKEY] Extracted image ({mime})") + + # 提取文本 + if "text" in part and part["text"]: + text_parts.append(part["text"]) + + if not image_tensors: + error_msg = f"Error: No images found in response" + print(f"[GEMINI_APIKEY] {error_msg}") + print(f"[GEMINI_APIKEY] Response: {str(result)[:500]}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + final_image = torch.cat(image_tensors, dim=0) + final_text = "\n".join(text_parts) if text_parts else "No text output" + + # 计算耗时和成本 + end_time = time.time() + duration = end_time - start_time + + # 估算成本 + cost_per_img = 0.04 + total_cost = cost_per_img * len(image_tensors) + + info_str = ( + f"Model: {model}\n" + f"Status: Success\n" + f"Time: {duration:.2f}s\n" + f"Images: {len(image_tensors)}\n" + f"Aspect Ratio: {aspect_ratio}\n" + f"Est. Cost: ${total_cost:.4f}\n" + f"---\n" + f"{final_text}" + ) + + print(f"[GEMINI_APIKEY] Success! Generated {len(image_tensors)} images in {duration:.2f}s") + return (final_image, info_str) + + except requests.exceptions.Timeout: + error_msg = "Error: Request timeout (120s)" + print(f"[GEMINI_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + except requests.exceptions.ConnectionError as e: + error_msg = f"Error: Connection failed - {str(e)}" + print(f"[GEMINI_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + except Exception as e: + error_msg = f"Error: {str(e)}" + print(f"[GEMINI_APIKEY] {error_msg}") + import traceback + traceback.print_exc() + return (torch.zeros((1, 512, 512, 3)), error_msg) + + +# 节点注册 +NODE_CLASS_MAPPINGS = { + "PDGeminiImageGenAPIKey": PDGeminiImageGenAPIKey +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "PDGeminiImageGenAPIKey": "PD: Gemini Image (apikey)" +} diff --git a/py/IMGE_GeminiNode_authtoken.py b/py/IMGE_GeminiNode_authtoken.py new file mode 100644 index 0000000..7a4597c --- /dev/null +++ b/py/IMGE_GeminiNode_authtoken.py @@ -0,0 +1,281 @@ +""" +PD: Gemini Image Generation Node (ComfyUI Auth Token) +基于 gemini_image_api 的 Auth Token 认证方式 +支持文生图和图生图 +""" + +import torch +import requests +import time +import io +import base64 +import numpy as np +from PIL import Image + +# 默认系统提示词(来自 ComfyUI 官方 API 节点) +GEMINI_IMAGE_SYS_PROMPT = ( + "You are an expert image-generation engine. You must ALWAYS produce an image.\n" + "Interpret all user input—regardless of " + "format, intent, or abstraction—as literal visual directives for image composition.\n" + "If a prompt is conversational or lacks specific visual details, " + "you must creatively invent a concrete visual scenario that depicts the concept.\n" + "Prioritize generating the visual representation above any text, formatting, or conversational requests." +) + + +def tensor_to_base64(tensor): + """将 Tensor 转换为 base64 字符串""" + if tensor.ndim == 4: + tensor = tensor[0] + + array = np.clip(255. * tensor.cpu().numpy(), 0, 255).astype(np.uint8) + image = Image.fromarray(array) + buffered = io.BytesIO() + image.save(buffered, format="PNG") + return base64.b64encode(buffered.getvalue()).decode("utf-8") + + +def bytes_to_tensor(data): + """将图片字节数据转换为 Tensor""" + try: + img = Image.open(io.BytesIO(data)).convert("RGB") + image_np = np.array(img).astype(np.float32) / 255.0 + return torch.from_numpy(image_np).unsqueeze(0) + except Exception as e: + print(f"[GEMINI_AUTHTOKEN] Image decode error: {e}") + return torch.zeros((1, 512, 512, 3)) + + +class PDGeminiImageGenAuthToken: + """ + PD: Gemini Image Generation (Auth Token) + 使用 ComfyUI Auth Token 调用 Gemini Image API + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "auth_token": ("STRING", { + "default": "", + "multiline": False, + "placeholder": "Paste your Auth Token here" + }), + "prompt": ("STRING", { + "multiline": True, + "default": "A futuristic city with flying cars", + "tooltip": "Describe what you want to generate" + }), + "model": ([ + "gemini-2.5-flash-image", + "gemini-2.5-flash-image-preview" + ], { + "default": "gemini-2.5-flash-image" + }), + "aspect_ratio": ([ + "auto", "1:1", "16:9", "9:16", "4:3", "3:4", "21:9", "9:21" + ], { + "default": "auto" + }), + "resolution": (["auto", "1K", "2K", "4K"], { + "default": "1K" + }), + "seed": ("INT", { + "default": 0, + "min": 0, + "max": 0xFFFFFFFFFFFFFFFF + }), + }, + "optional": { + "image_ref": ("IMAGE", { + "tooltip": "Reference image(s) for image-to-image generation" + }), + "system_prompt": ("STRING", { + "multiline": True, + "default": GEMINI_IMAGE_SYS_PROMPT, + "tooltip": "Optional system instructions" + }), + }, + "hidden": { + "unique_id": "UNIQUE_ID", + } + } + + RETURN_TYPES = ("IMAGE", "STRING") + RETURN_NAMES = ("image", "info") + FUNCTION = "generate_image" + CATEGORY = "PD_Tools/Image_Generation" + + def generate_image(self, auth_token, prompt, model, aspect_ratio, resolution, seed, unique_id, image_ref=None, system_prompt=""): + """生成图片""" + + print(f"[GEMINI_AUTHTOKEN] ========== 开始执行 ==========") + print(f"[GEMINI_AUTHTOKEN] Prompt: {prompt[:50]}...") + print(f"[GEMINI_AUTHTOKEN] Model: {model}") + + # 验证 Token + if not auth_token or not auth_token.strip(): + error_msg = "Error: Auth Token is required" + print(f"[GEMINI_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + # 清理 Token + auth_token = auth_token.strip() + if auth_token.lower().startswith("bearer "): + auth_token = auth_token[7:].strip() + + # 构建 API URL (不需要添加 :generateContent 后缀,API 会自动处理) + base_url = f"https://api.comfy.org/proxy/vertexai/gemini/{model}" + + # 构建请求内容 + parts = [] + + # 添加系统提示词(如果有) + if system_prompt and system_prompt.strip(): + parts.append({"text": system_prompt.strip()}) + + # 添加用户提示词 + parts.append({"text": prompt}) + + # 添加参考图片(如果有) + if image_ref is not None: + for i in range(image_ref.shape[0]): + b64_str = tensor_to_base64(image_ref[i]) + parts.append({ + "inlineData": { + "mimeType": "image/png", + "data": b64_str + } + }) + print(f"[GEMINI_AUTHTOKEN] Added reference image {i+1}") + + # 生成配置 + generation_config = { + "responseModalities": ["IMAGE"] + } + + # 图片配置 + image_config = {} + if aspect_ratio != "auto": + image_config["aspectRatio"] = aspect_ratio + if resolution != "auto": + image_config["resolution"] = resolution + + if image_config: + generation_config["imageConfig"] = image_config + + # 完整请求体 + payload = { + "contents": [{ + "role": "user", + "parts": parts + }], + "generationConfig": generation_config + } + + # 请求头 + headers = { + "Authorization": f"Bearer {auth_token}", + "Content-Type": "application/json", + "User-Agent": "ComfyUI-PD-Node/2.0" + } + + start_time = time.time() + + try: + print(f"[GEMINI_AUTHTOKEN] Sending request to {model}") + print(f"[GEMINI_AUTHTOKEN] Aspect Ratio: {aspect_ratio}, Resolution: {resolution}") + + response = requests.post(base_url, headers=headers, json=payload, timeout=120) + + # 检查响应 + if response.status_code != 200: + error_msg = f"API Error {response.status_code}: {response.text[:200]}" + print(f"[GEMINI_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + result = response.json() + + # 提取图片 + image_tensors = [] + candidates = result.get("candidates", []) + + if not candidates: + error_msg = "Error: No candidates in response" + print(f"[GEMINI_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + for cand in candidates: + content = cand.get("content", {}) + parts = content.get("parts", []) + + for part in parts: + # 支持两种字段名格式 + inline_data = part.get("inline_data") or part.get("inlineData") + + if inline_data: + mime = inline_data.get("mime_type") or inline_data.get("mimeType") + data_b64 = inline_data.get("data") + + if mime in ["image/png", "image/jpeg"] and data_b64: + raw_data = base64.b64decode(data_b64) + image_tensors.append(bytes_to_tensor(raw_data)) + print(f"[GEMINI_AUTHTOKEN] Extracted image ({mime})") + + if not image_tensors: + error_msg = f"Error: No images found in response" + print(f"[GEMINI_AUTHTOKEN] {error_msg}") + print(f"[GEMINI_AUTHTOKEN] Response: {str(result)[:500]}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + final_image = torch.cat(image_tensors, dim=0) + + # 计算耗时和成本 + end_time = time.time() + duration = end_time - start_time + + # 估算成本(根据模型) + cost_per_img = 0.04 + if "pro" in model.lower(): + cost_per_img = 0.08 + total_cost = cost_per_img * len(image_tensors) + + info_str = ( + f"Model: {model}\n" + f"Status: Success\n" + f"Time: {duration:.2f}s\n" + f"Images: {len(image_tensors)}\n" + f"Aspect Ratio: {aspect_ratio}\n" + f"Resolution: {resolution}\n" + f"Est. Cost: ${total_cost:.4f}" + ) + + print(f"[GEMINI_AUTHTOKEN] Success! Generated {len(image_tensors)} images in {duration:.2f}s") + return (final_image, info_str) + + except requests.exceptions.Timeout: + error_msg = "Error: Request timeout (120s)" + print(f"[GEMINI_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + except requests.exceptions.ConnectionError as e: + error_msg = f"Error: Connection failed - {str(e)}" + print(f"[GEMINI_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + except Exception as e: + error_msg = f"Error: {str(e)}" + print(f"[GEMINI_AUTHTOKEN] {error_msg}") + import traceback + traceback.print_exc() + return (torch.zeros((1, 512, 512, 3)), error_msg) + + +# 节点注册 +NODE_CLASS_MAPPINGS = { + "PDGeminiImageGenAuthToken": PDGeminiImageGenAuthToken +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "PDGeminiImageGenAuthToken": "PD: Gemini Image (comfyui_AuthToken)" +} diff --git a/py/IMGE_GeminiPro_apikey.py b/py/IMGE_GeminiPro_apikey.py new file mode 100644 index 0000000..0f4e955 --- /dev/null +++ b/py/IMGE_GeminiPro_apikey.py @@ -0,0 +1,294 @@ +""" +PD: Gemini Pro Image Generation Node (ComfyUI API Key) +Nano Banana Pro - 使用 ComfyUI API Key 调用 ComfyUI 代理 API +支持高分辨率图像生成(1K/2K/4K) +""" + +import torch +import requests +import time +import io +import base64 +import numpy as np +from PIL import Image + +# 默认系统提示词(来自 ComfyUI 官方 API 节点) +GEMINI_IMAGE_SYS_PROMPT = ( + "You are an expert image-generation engine. You must ALWAYS produce an image.\n" + "Interpret all user input—regardless of " + "format, intent, or abstraction—as literal visual directives for image composition.\n" + "If a prompt is conversational or lacks specific visual details, " + "you must creatively invent a concrete visual scenario that depicts the concept.\n" + "Prioritize generating the visual representation above any text, formatting, or conversational requests." +) + + +def tensor_to_base64(tensor): + """将 Tensor 转换为 base64 字符串""" + if tensor.ndim == 4: + tensor = tensor[0] + + array = np.clip(255. * tensor.cpu().numpy(), 0, 255).astype(np.uint8) + image = Image.fromarray(array) + buffered = io.BytesIO() + image.save(buffered, format="PNG") + return base64.b64encode(buffered.getvalue()).decode("utf-8") + + +def bytes_to_tensor(data): + """将图片字节数据转换为 Tensor""" + try: + img = Image.open(io.BytesIO(data)).convert("RGB") + image_np = np.array(img).astype(np.float32) / 255.0 + return torch.from_numpy(image_np).unsqueeze(0) + except Exception as e: + print(f"[GEMINI_PRO_APIKEY] Image decode error: {e}") + return torch.zeros((1, 512, 512, 3)) + + +class PDGeminiProImageGenAPIKey: + """ + PD: Gemini Pro Image Generation (API Key) + Nano Banana Pro - 使用 ComfyUI API Key 调用 ComfyUI 代理 API + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "api_key": ("STRING", { + "default": "", + "multiline": False, + "placeholder": "Your ComfyUI API Key" + }), + "prompt": ("STRING", { + "multiline": True, + "default": "A futuristic city with flying cars", + "tooltip": "Text prompt describing the image to generate or the edits to apply" + }), + "model": (["gemini-3-pro-image-preview"], { + "default": "gemini-3-pro-image-preview" + }), + "aspect_ratio": ([ + "auto", "1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9" + ], { + "default": "auto", + "tooltip": "If set to 'auto', matches your input image's aspect ratio" + }), + "resolution": (["1K", "2K", "4K"], { + "default": "1K", + "tooltip": "Target output resolution. For 2K/4K the native Gemini upscaler is used" + }), + "response_modalities": (["IMAGE+TEXT", "IMAGE"], { + "default": "IMAGE+TEXT", + "tooltip": "Choose 'IMAGE' for image-only output, or 'IMAGE+TEXT' for both" + }), + "seed": ("INT", { + "default": 42, + "min": 0, + "max": 0xFFFFFFFFFFFFFFFF + }), + }, + "optional": { + "images": ("IMAGE", { + "tooltip": "Optional reference image(s) (up to 14)" + }), + "system_prompt": ("STRING", { + "multiline": True, + "default": GEMINI_IMAGE_SYS_PROMPT, + "tooltip": "Foundational instructions that dictate an AI's behavior" + }), + }, + "hidden": { + "unique_id": "UNIQUE_ID", + } + } + + RETURN_TYPES = ("IMAGE", "STRING") + RETURN_NAMES = ("image", "text") + FUNCTION = "generate_image" + CATEGORY = "PD_Tools/Image_Generation" + + def generate_image(self, api_key, prompt, model, aspect_ratio, resolution, response_modalities, seed, unique_id, images=None, system_prompt=""): + """生成图片""" + + # 验证 API Key + if not api_key or not api_key.strip(): + error_msg = "Error: ComfyUI API Key is required" + print(f"[GEMINI_PRO_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + # 清理 API Key + api_key = api_key.strip() + + # ComfyUI 代理 API URL + base_url = f"https://api.comfy.org/proxy/vertexai/gemini/{model}" + + # 构建请求内容 + parts = [] + + # 添加用户提示词 + parts.append({"text": prompt}) + + # 添加参考图片(如果有,最多14张) + if images is not None: + num_images = min(images.shape[0], 14) + for i in range(num_images): + b64_str = tensor_to_base64(images[i]) + parts.append({ + "inlineData": { + "mimeType": "image/png", + "data": b64_str + } + }) + print(f"[GEMINI_PRO_APIKEY] Added reference image {i+1}/{num_images}") + + if images.shape[0] > 14: + print(f"[GEMINI_PRO_APIKEY] Warning: Only first 14 images will be used (provided {images.shape[0]})") + + # 生成配置 + generation_config = { + "responseModalities": ["IMAGE"] if response_modalities == "IMAGE" else ["TEXT", "IMAGE"] + } + + # 图片配置 + image_config = { + "imageSize": resolution + } + if aspect_ratio != "auto": + image_config["aspectRatio"] = aspect_ratio + + generation_config["imageConfig"] = image_config + + # 系统指令 + system_instruction = None + if system_prompt and system_prompt.strip(): + system_instruction = { + "parts": [{"text": system_prompt.strip()}] + } + + # 完整请求体 + payload = { + "contents": [{ + "role": "user", + "parts": parts + }], + "generationConfig": generation_config + } + + if system_instruction: + payload["systemInstruction"] = system_instruction + + # 请求头 + headers = { + "X-API-KEY": api_key, + "Accept": "application/json", + "Content-Type": "application/json", + "User-Agent": "ComfyUI-PD-Node/2.0" + } + + start_time = time.time() + + try: + print(f"[GEMINI_PRO_APIKEY] Sending request to {model}") + print(f"[GEMINI_PRO_APIKEY] Aspect Ratio: {aspect_ratio}, Resolution: {resolution}") + + response = requests.post(base_url, headers=headers, json=payload, timeout=180) + + # 检查响应 + if response.status_code != 200: + error_msg = f"API Error {response.status_code}: {response.text[:200]}" + print(f"[GEMINI_PRO_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + result = response.json() + + # 提取图片和文本 + image_tensors = [] + text_parts = [] + candidates = result.get("candidates", []) + + if not candidates: + error_msg = "Error: No candidates in response" + print(f"[GEMINI_PRO_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + for cand in candidates: + content = cand.get("content", {}) + parts = content.get("parts", []) + + for part in parts: + # 提取图片 + inline_data = part.get("inline_data") or part.get("inlineData") + + if inline_data: + mime = inline_data.get("mime_type") or inline_data.get("mimeType") + data_b64 = inline_data.get("data") + + if mime in ["image/png", "image/jpeg"] and data_b64: + raw_data = base64.b64decode(data_b64) + image_tensors.append(bytes_to_tensor(raw_data)) + print(f"[GEMINI_PRO_APIKEY] Extracted image ({mime})") + + # 提取文本 + if "text" in part and part["text"]: + text_parts.append(part["text"]) + + if not image_tensors: + error_msg = f"Error: No images found in response" + print(f"[GEMINI_PRO_APIKEY] {error_msg}") + print(f"[GEMINI_PRO_APIKEY] Response: {str(result)[:500]}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + final_image = torch.cat(image_tensors, dim=0) + final_text = "\n".join(text_parts) if text_parts else "No text output" + + # 计算耗时和成本 + end_time = time.time() + duration = end_time - start_time + + # 估算成本(Gemini 3 Pro Image) + cost_per_img = 0.12 # 估算 + total_cost = cost_per_img * len(image_tensors) + + info_str = ( + f"Model: {model}\n" + f"Status: Success\n" + f"Time: {duration:.2f}s\n" + f"Images: {len(image_tensors)}\n" + f"Aspect Ratio: {aspect_ratio}\n" + f"Resolution: {resolution}\n" + f"Est. Cost: ${total_cost:.4f}\n" + f"---\n" + f"{final_text}" + ) + + print(f"[GEMINI_PRO_APIKEY] Success! Generated {len(image_tensors)} images in {duration:.2f}s") + return (final_image, info_str) + + except requests.exceptions.Timeout: + error_msg = "Error: Request timeout (180s)" + print(f"[GEMINI_PRO_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + except requests.exceptions.ConnectionError as e: + error_msg = f"Error: Connection failed - {str(e)}" + print(f"[GEMINI_PRO_APIKEY] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + except Exception as e: + error_msg = f"Error: {str(e)}" + print(f"[GEMINI_PRO_APIKEY] {error_msg}") + import traceback + traceback.print_exc() + return (torch.zeros((1, 512, 512, 3)), error_msg) + + +# 节点注册 +NODE_CLASS_MAPPINGS = { + "PDGeminiProImageGenAPIKey": PDGeminiProImageGenAPIKey +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "PDGeminiProImageGenAPIKey": "PD: Gemini Pro Image (apikey)" +} diff --git a/py/IMGE_GeminiPro_authtoken.py b/py/IMGE_GeminiPro_authtoken.py new file mode 100644 index 0000000..2a606f2 --- /dev/null +++ b/py/IMGE_GeminiPro_authtoken.py @@ -0,0 +1,300 @@ +""" +PD: Gemini Pro Image Generation Node (ComfyUI Auth Token) +Nano Banana Pro - 基于 Gemini 3 Pro Image +支持高分辨率图像生成(1K/2K/4K) +""" + +import torch +import requests +import time +import io +import base64 +import numpy as np +from PIL import Image + +# 默认系统提示词(来自 ComfyUI 官方 API 节点) +GEMINI_IMAGE_SYS_PROMPT = ( + "You are an expert image-generation engine. You must ALWAYS produce an image.\n" + "Interpret all user input—regardless of " + "format, intent, or abstraction—as literal visual directives for image composition.\n" + "If a prompt is conversational or lacks specific visual details, " + "you must creatively invent a concrete visual scenario that depicts the concept.\n" + "Prioritize generating the visual representation above any text, formatting, or conversational requests." +) + + +def tensor_to_base64(tensor): + """将 Tensor 转换为 base64 字符串""" + if tensor.ndim == 4: + tensor = tensor[0] + + array = np.clip(255. * tensor.cpu().numpy(), 0, 255).astype(np.uint8) + image = Image.fromarray(array) + buffered = io.BytesIO() + image.save(buffered, format="PNG") + return base64.b64encode(buffered.getvalue()).decode("utf-8") + + +def bytes_to_tensor(data): + """将图片字节数据转换为 Tensor""" + try: + img = Image.open(io.BytesIO(data)).convert("RGB") + image_np = np.array(img).astype(np.float32) / 255.0 + return torch.from_numpy(image_np).unsqueeze(0) + except Exception as e: + print(f"[GEMINI_PRO_AUTHTOKEN] Image decode error: {e}") + return torch.zeros((1, 512, 512, 3)) + + +class PDGeminiProImageGenAuthToken: + """ + PD: Gemini Pro Image Generation (Auth Token) + Nano Banana Pro - 使用 ComfyUI Auth Token 调用 Gemini 3 Pro Image API + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "auth_token": ("STRING", { + "default": "", + "multiline": False, + "placeholder": "Paste your Auth Token here" + }), + "prompt": ("STRING", { + "multiline": True, + "default": "A futuristic city with flying cars", + "tooltip": "Text prompt describing the image to generate or the edits to apply" + }), + "model": (["gemini-3-pro-image-preview"], { + "default": "gemini-3-pro-image-preview" + }), + "aspect_ratio": ([ + "auto", "1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9" + ], { + "default": "auto", + "tooltip": "If set to 'auto', matches your input image's aspect ratio" + }), + "resolution": (["1K", "2K", "4K"], { + "default": "1K", + "tooltip": "Target output resolution. For 2K/4K the native Gemini upscaler is used" + }), + "response_modalities": (["IMAGE+TEXT", "IMAGE"], { + "default": "IMAGE+TEXT", + "tooltip": "Choose 'IMAGE' for image-only output, or 'IMAGE+TEXT' for both" + }), + "seed": ("INT", { + "default": 42, + "min": 0, + "max": 0xFFFFFFFFFFFFFFFF + }), + }, + "optional": { + "images": ("IMAGE", { + "tooltip": "Optional reference image(s) (up to 14)" + }), + "system_prompt": ("STRING", { + "multiline": True, + "default": GEMINI_IMAGE_SYS_PROMPT, + "tooltip": "Foundational instructions that dictate an AI's behavior" + }), + }, + "hidden": { + "unique_id": "UNIQUE_ID", + } + } + + RETURN_TYPES = ("IMAGE", "STRING") + RETURN_NAMES = ("image", "text") + FUNCTION = "generate_image" + CATEGORY = "PD_Tools/Image_Generation" + + def generate_image(self, auth_token, prompt, model, aspect_ratio, resolution, response_modalities, seed, unique_id, images=None, system_prompt=""): + """生成图片""" + + print(f"[GEMINI_PRO_AUTHTOKEN] ========== 开始执行 ==========") + print(f"[GEMINI_PRO_AUTHTOKEN] Prompt: {prompt[:50]}...") + print(f"[GEMINI_PRO_AUTHTOKEN] Model: {model}") + + # 验证 Token + if not auth_token or not auth_token.strip(): + error_msg = "Error: Auth Token is required" + print(f"[GEMINI_PRO_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + # 清理 Token + auth_token = auth_token.strip() + if auth_token.lower().startswith("bearer "): + auth_token = auth_token[7:].strip() + + # 构建 API URL + base_url = f"https://api.comfy.org/proxy/vertexai/gemini/{model}" + + # 构建请求内容 + parts = [] + + # 添加用户提示词 + parts.append({"text": prompt}) + + # 添加参考图片(如果有,最多14张) + if images is not None: + num_images = min(images.shape[0], 14) + for i in range(num_images): + b64_str = tensor_to_base64(images[i]) + parts.append({ + "inlineData": { + "mimeType": "image/png", + "data": b64_str + } + }) + print(f"[GEMINI_PRO_AUTHTOKEN] Added reference image {i+1}/{num_images}") + + if images.shape[0] > 14: + print(f"[GEMINI_PRO_AUTHTOKEN] Warning: Only first 14 images will be used (provided {images.shape[0]})") + + # 生成配置 + generation_config = { + "responseModalities": ["IMAGE"] if response_modalities == "IMAGE" else ["TEXT", "IMAGE"] + } + + # 图片配置 + image_config = { + "imageSize": resolution + } + if aspect_ratio != "auto": + image_config["aspectRatio"] = aspect_ratio + + generation_config["imageConfig"] = image_config + + # 系统指令 + system_instruction = None + if system_prompt and system_prompt.strip(): + system_instruction = { + "parts": [{"text": system_prompt.strip()}] + } + + # 完整请求体 + payload = { + "contents": [{ + "role": "user", + "parts": parts + }], + "generationConfig": generation_config + } + + if system_instruction: + payload["systemInstruction"] = system_instruction + + # 请求头 + headers = { + "Authorization": f"Bearer {auth_token}", + "Content-Type": "application/json", + "User-Agent": "ComfyUI-PD-Node/2.0" + } + + start_time = time.time() + + try: + print(f"[GEMINI_PRO_AUTHTOKEN] Sending request to {model}") + print(f"[GEMINI_PRO_AUTHTOKEN] Aspect Ratio: {aspect_ratio}, Resolution: {resolution}") + + response = requests.post(base_url, headers=headers, json=payload, timeout=180) + + # 检查响应 + if response.status_code != 200: + error_msg = f"API Error {response.status_code}: {response.text[:200]}" + print(f"[GEMINI_PRO_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + result = response.json() + + # 提取图片和文本 + image_tensors = [] + text_parts = [] + candidates = result.get("candidates", []) + + if not candidates: + error_msg = "Error: No candidates in response" + print(f"[GEMINI_PRO_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + for cand in candidates: + content = cand.get("content", {}) + parts = content.get("parts", []) + + for part in parts: + # 提取图片 + inline_data = part.get("inline_data") or part.get("inlineData") + + if inline_data: + mime = inline_data.get("mime_type") or inline_data.get("mimeType") + data_b64 = inline_data.get("data") + + if mime in ["image/png", "image/jpeg"] and data_b64: + raw_data = base64.b64decode(data_b64) + image_tensors.append(bytes_to_tensor(raw_data)) + print(f"[GEMINI_PRO_AUTHTOKEN] Extracted image ({mime})") + + # 提取文本 + if "text" in part and part["text"]: + text_parts.append(part["text"]) + + if not image_tensors: + error_msg = f"Error: No images found in response" + print(f"[GEMINI_PRO_AUTHTOKEN] {error_msg}") + print(f"[GEMINI_PRO_AUTHTOKEN] Response: {str(result)[:500]}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + final_image = torch.cat(image_tensors, dim=0) + final_text = "\n".join(text_parts) if text_parts else "No text output" + + # 计算耗时和成本 + end_time = time.time() + duration = end_time - start_time + + # 估算成本(Gemini 3 Pro Image) + # $2/1M input tokens, $12/1M output text tokens, $120/1M output image tokens + cost_per_img = 0.12 # 估算 + total_cost = cost_per_img * len(image_tensors) + + info_str = ( + f"Model: {model}\n" + f"Status: Success\n" + f"Time: {duration:.2f}s\n" + f"Images: {len(image_tensors)}\n" + f"Aspect Ratio: {aspect_ratio}\n" + f"Resolution: {resolution}\n" + f"Est. Cost: ${total_cost:.4f}\n" + f"---\n" + f"{final_text}" + ) + + print(f"[GEMINI_PRO_AUTHTOKEN] Success! Generated {len(image_tensors)} images in {duration:.2f}s") + return (final_image, info_str) + + except requests.exceptions.Timeout: + error_msg = "Error: Request timeout (180s)" + print(f"[GEMINI_PRO_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + except requests.exceptions.ConnectionError as e: + error_msg = f"Error: Connection failed - {str(e)}" + print(f"[GEMINI_PRO_AUTHTOKEN] {error_msg}") + return (torch.zeros((1, 512, 512, 3)), error_msg) + + except Exception as e: + error_msg = f"Error: {str(e)}" + print(f"[GEMINI_PRO_AUTHTOKEN] {error_msg}") + import traceback + traceback.print_exc() + return (torch.zeros((1, 512, 512, 3)), error_msg) + + +# 节点注册 +NODE_CLASS_MAPPINGS = { + "PDGeminiProImageGenAuthToken": PDGeminiProImageGenAuthToken +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "PDGeminiProImageGenAuthToken": "PD: Gemini Pro Image (comfyui_AuthToken)" +} diff --git a/py/PD_comfyplus_image.py b/py/PD_comfyplus_image.py new file mode 100644 index 0000000..16b5138 --- /dev/null +++ b/py/PD_comfyplus_image.py @@ -0,0 +1,78 @@ +import torch +from comfy_api_nodes.apis import GeminiPart, GeminiInlineData, GeminiMimeType +from comfy_api_nodes.util.conversions import tensor_to_base64_string + +class PD_ComfyPlusImage: + """ + 将最多9个尺寸不一的图片按顺序整合打包为 GEMINI_INPUT_FILES, + 可以直接连接给支持 files 的大模型节点 (如 Nano Banana Pro 等), + 从而完美突破 ComfyUI Batch 必须相同尺寸的限制。 + """ + @classmethod + def INPUT_TYPES(cls): + return { + # 第1张图片强制必填 + "required": { + "image1": ("IMAGE", {"tooltip": "必须输入的第1张图片"}), + }, + # 第 2-9 张及 previous_files 作为可选填 + "optional": { + "image2": ("IMAGE", {"tooltip": "可选输入的第2张图片"}), + "image3": ("IMAGE", {"tooltip": "可选输入的第3张图片"}), + "image4": ("IMAGE", {"tooltip": "可选输入的第4张图片"}), + "image5": ("IMAGE", {"tooltip": "可选输入的第5张图片"}), + "image6": ("IMAGE", {"tooltip": "可选输入的第6张图片"}), + "image7": ("IMAGE", {"tooltip": "可选输入的第7张图片"}), + "image8": ("IMAGE", {"tooltip": "可选输入的第8张图片"}), + "image9": ("IMAGE", {"tooltip": "可选输入的第9张图片"}), + "previous_files": ("GEMINI_INPUT_FILES", {"tooltip": "如超过9张图需继续打包,可连接上一个该节点输出的files"}), + } + } + + RETURN_TYPES = ("GEMINI_INPUT_FILES",) + RETURN_NAMES = ("files",) + FUNCTION = "pack_images" + CATEGORY = "PD_Tools" + + def pack_images(self, image1, image2=None, image3=None, image4=None, + image5=None, image6=None, image7=None, image8=None, + image9=None, previous_files=None): + + files_list = [] + + # 如果需要无缝串联别的节点输出的 files ,优先加进去 + if previous_files is not None: + files_list.extend(previous_files) + + images = [image1, image2, image3, image4, image5, image6, image7, image8, image9] + + for img in images: + if img is not None: + # 兼容万一单条线里输入了 Batch(N) 图片的特殊情况,分别解开处理 + for i in range(img.shape[0]): + try: + # 转换成 Base64 + img_b64 = tensor_to_base64_string(img[i].unsqueeze(0)) + # 构造为 Gemini 认证的 Part + new_part = GeminiPart( + inlineData=GeminiInlineData( + mimeType=GeminiMimeType.image_png, + data=img_b64 + ) + ) + # 转成字典防止 Pydantic 跨模块传递对象时校验失败 + files_list.append(new_part.model_dump(exclude_none=True)) + except Exception as e: + print(f"[Error] PD_comfyplus_image pack failed for an image: {e}") + + return (files_list,) + + +# 注册节点 +NODE_CLASS_MAPPINGS = { + "PD_comfyplus_image": PD_ComfyPlusImage +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "PD_comfyplus_image": "PD_comfyplus_image (Multi-Size Pack)" +} diff --git a/py/README.md b/py/README.md new file mode 100644 index 0000000..f6382c1 --- /dev/null +++ b/py/README.md @@ -0,0 +1,352 @@ +# PD ComfyUI API Nodes + +ComfyUI 自定义节点集合,用于调用各种 AI 图像生成 API(GPT Image、Gemini Image、Flux Kontext)。 + +## 📦 节点列表 + +### ComfyUI AuthToken 版本(通过 ComfyUI 代理) +ComfyUI AuthToken 版本(通过 ComfyUI 代理) + - PD: GPT Image (comfyui_AuthToken) + - PD: Gemini Image (comfyui_AuthToken) + - PD: Flux Kontext (comfyui_AuthToken) + +### 直接 API Key 版本直接调用官方comfyui的key + +API Key 版本: +- 只保留 ComfyUI API Key 输入 +- 参数和调用逻辑跟 ComfyUI 官方自带的 API 节点一样 - 只是在调用时可以手动填入 key + +| 节点名称 | 文件 | 说明 | +|---------|------|------| +| **PD: GPT Image (apikey)** | `IMAGE_GPT_apikey.py` | OpenAI GPT Image 生成/编辑 | +| **PD: Gemini Image (apikey)** | `IMGE_GeminiNode_apikey.py` | Google Gemini 图像生成 | +| **PD: Gemini Pro Image (apikey)** | `IMGE_GeminiPro_apikey.py` | Google Gemini 3 Pro 高分辨率图像生成 | +| **PD: Flux Kontext (apikey)** | `IMGE_kontext_apikey.py` | Flux Kontext 图像编辑 | + +--- + +## 🔑 两种版本的区别 + +### ComfyUI AuthToken 版本 (comfyui_AuthToken) + +**认证方式**:使用 ComfyUI Auth Token,pandy自制油猴插件获取。 + +**认证头格式**:`Authorization: Bearer {auth_token}` + +**使用示例**: +``` +auth_token: eyJhbGciOiJSUzI1NiIsImtpZCI6ImEzOGVhNmEw... +``` + +### API Key 版本 (apikey) + +**认证方式**:使用 ComfyUI 官方 API Key + +**认证头格式**:`X-API-KEY: {api_key}` (与 ComfyUI 官方 API 节点完全一致) + +**使用示例**: +``` +api_key: comfy_xxxxxxxxxxxxxxxxxxxxx +``` + +**特点**: +- 参数和调用逻辑跟 ComfyUI 官方自带的 API 节点一样 +- 只是在调用时可以手动填入 key +- 直接使用官方账号的 key 申请下来填入使用 + + +## 📖 节点详细说明 + +### 1. GPT Image 节点 + +**功能**: +- 文生图(Text-to-Image) +- 图片编辑(Image Editing) +- 图片修复(Inpainting with Mask) + +**支持模型**: + +**AuthToken 版本**: +- `gpt-image-1`:OpenAI GPT Image 1(推荐) +- `gpt-image-1.5`:OpenAI GPT Image 1.5(更高质量) + + +### 3. Gemini Pro Image 节点(Nano Banana Pro) + +**功能**: +- 高分辨率图像生成(1K/2K/4K) +- 文生图(Text-to-Image) +- 图生图(Image-to-Image) +- 支持多张参考图片(最多14张) +- 同时输出图像和文本说明 + +**支持模型**: +- `gemini-3-pro-image-preview`:Gemini 3 Pro Image(最高质量) + +**参数说明**: +- `prompt`:文本提示词,描述要生成的图像或编辑指令 +- `model`:gemini-3-pro-image-preview +- `aspect_ratio`:宽高比 + - auto:自动匹配输入图片比例,无图片时默认 16:9 + - 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9 +- `resolution`:目标输出分辨率 + - 1K:标准分辨率 + - 2K:使用原生 Gemini 放大器 + - 4K:使用原生 Gemini 放大器(最高质量) +- `response_modalities`:输出模式 + - IMAGE+TEXT:同时返回图像和文本说明 + - IMAGE:仅返回图像 +- `images`(可选):参考图片(最多14张,使用 Batch Images 节点) +- `system_prompt`(可选):系统提示词,默认使用官方优化的图像生成提示词 + +**输出**: +- `image`:生成的图像 +- `text`:文本说明(包含模型的思考过程和描述) + +**成本估算**: +- Gemini 3 Pro Image: 约 $0.12/张 + - 基于 token 使用量:$2/1M input + $12/1M output text + $120/1M output image + +**特殊说明(apikey 版本)**: +- 需要提供 `project_id`(Google Cloud 项目 ID) +- 需要提供 `location`(区域,默认 us-central1) +- 超时时间:180秒(因为高分辨率生成需要更长时间) + +**使用建议**: +- 适合需要高质量、高分辨率图像的场景 +- 2K/4K 分辨率会使用原生放大器,质量更好但成本更高 +- IMAGE+TEXT 模式可以看到模型的思考过程,有助于理解生成结果 +- 可以提供多张参考图片来引导生成风格 + +--- + +### 4. Flux Kontext 节点 + +**功能**: +- 图片编辑(Image Editing) +- 基于上下文的智能修改 + +**支持模型**: +- `flux-kontext-pro`:快速版本 +- `flux-kontext-max`:高质量版本 + +**参数说明**: +- `prompt`:编辑指令 +- `aspect_ratio`:宽高比 +- `guidance`:提示词遵循度(0.1-99.0) +- `steps`:生成步数(1-150) +- `prompt_upsampling`:AI 增强提示词 +- `input_image`(可选):输入图片 + +**成本估算**: +- Kontext Pro: $0.05/张 +- Kontext Max: $0.10/张 + +**特点**: +- 异步生成,需要轮询结果 +- 最长等待时间:10 分钟 +- 轮询间隔:2 秒 + +--- + +## 🚀 使用建议 + +### 选择 ComfyUI AuthToken 版本,如果你: +- ✅ 已经有 ComfyUI Auth Token +- ✅ 想要统一管理多个 AI 模型 +- ✅ 喜欢通过 ComfyUI 生态系统 +- ✅ 不想配置多个平台的 API Key + +### 选择直接 API Key 版本,如果你: +- ✅ 已经有各个平台的 API Key +- ✅ 想要直接控制 API 调用 +- ✅ 不想依赖 ComfyUI 代理服务 +- ✅ 需要更灵活的配置(如 Gemini 的 project_id) + +--- + +## 📝 使用示例 + +### 示例 1:使用 ComfyUI AuthToken 生成图片(GPT Image) + +``` +节点:PD: GPT Image (comfyui_AuthToken) + +参数: +- auth_token: eyJhbGciOiJSUzI1NiIsImtpZCI6ImEzOGVhNmEw... +- prompt: A futuristic city with flying cars at sunset +- model: gpt-image-1 +- quality: medium +- background: auto +- size: 1024x1024 +- n: 1 +``` + +### 示例 2:使用直接 API Key 生成图片(DALL-E) + +``` +节点:PD: GPT Image (apikey) + +参数: +- api_key: sk-proj-abc123... +- prompt: A futuristic city with flying cars at sunset +- model: dall-e-3 +- quality: hd +- size: 1024x1792 +``` + +### 示例 3:使用 Gemini 生成图片(apikey 版本) + +``` +节点:PD: Gemini Image (apikey) + +参数: +- api_key: AIzaSyD... +- project_id: my-project-123 +- location: us-central1 +- prompt: A beautiful landscape with mountains +- model: gemini-2.5-flash-image +- aspect_ratio: 16:9 +- resolution: 2K +``` + +### 示例 4:使用 Flux Kontext 编辑图片 + +``` +节点:PD: Flux Kontext (comfyui_AuthToken) + +参数: +- auth_token: eyJhbGciOiJSUzI1NiIsImtpZCI6ImEzOGVhNmEw... +- prompt: Change the sky to sunset colors +- model: flux-kontext-pro +- aspect_ratio: 16:9 +- guidance: 3.0 +- steps: 50 +- input_image: [连接输入图片] +``` + +--- + +## ⚠️ 注意事项 + +1. **API Key 安全**: + - 不要在公开的工作流中暴露 API Key + - 建议使用环境变量或配置文件管理 + +2. **成本控制**: + - 所有节点都会显示预估成本 + - 实际成本以各平台账单为准 + - 建议设置 API 使用限额 + +3. **超时设置**: + - GPT/Gemini: 120 秒超时 + - Flux Kontext: 10 分钟超时(包含轮询) + +4. **错误处理**: + - 所有节点都有详细的错误日志 + - 检查 ComfyUI 控制台查看详细信息 + +5. **网络要求**: + - 需要稳定的网络连接 + - 某些地区可能需要代理访问 + +--- + +## 🔧 故障排除 + +### 问题 1:认证失败(401 错误) + +**ComfyUI AuthToken 版本**: +- 检查 Auth Token 是否正确 +- Token 可能已过期,重新获取 +- 认证头格式:`Authorization: Bearer {auth_token}` + +**直接 API Key 版本**: +- 检查 API Key 格式是否正确 +- 确认 API Key 有效且有余额 +- 认证头格式:`X-API-KEY: {api_key}` (与 ComfyUI 官方 API 节点一致) +- Gemini 需要确认 Project ID 和 Location 正确 + +### 问题 2:请求超时 + +- 检查网络连接 +- 尝试增加超时时间 +- Flux Kontext 可能需要更长时间,属于正常现象 + +### 问题 3:图片无法生成 / 返回黑图 + +**症状**:节点返回 512x512 的黑色图片 + +**可能原因**: +1. **API 端点错误**(已修复): + - 旧版本的 Gemini AuthToken 节点使用了错误的端点格式 + - 错误:`https://api.comfy.org/proxy/vertexai/gemini/{model}:generateContent` + - 正确:`https://api.comfy.org/proxy/vertexai/gemini/{model}` + - **解决方案**:更新到最新版本(v2.1+) + +2. **模型名称不支持**: + - 检查控制台是否有 "Unsupported model" 错误 + - 确认使用的模型在支持列表中 + - Gemini AuthToken 版本支持:`gemini-2.5-flash-image`, `gemini-2.5-flash-image-preview` + +3. **提示词违规**: + - 检查提示词是否符合内容政策 + - 查看控制台日志获取详细错误信息 + +4. **API 配额不足**: + - 确认账户有足够的配额/余额 + - 检查 API 使用限制 + +**调试步骤**: +1. 打开 ComfyUI 控制台 +2. 查找 `[GEMINI_AUTHTOKEN]` 或 `[GEMINI_APIKEY]` 开头的日志 +3. 检查是否有 API Error 信息 +4. 根据错误信息采取相应措施 + +### 问题 4:认证失败(Gemini 节点) + +- 确认已启用 Vertex AI API +- 确认 Project ID 正确 +- 确认 Location 支持 Gemini 模型 +- 检查 API Key 权限 + +--- + +## 📚 相关链接 + +- [ComfyUI 官网](https://www.comfy.org) +- [OpenAI Platform](https://platform.openai.com) +- [Google Cloud Console](https://console.cloud.google.com) +- [Black Forest Labs](https://blackforestlabs.ai) +- [ComfyUI GitHub](https://github.com/comfyanonymous/ComfyUI) + +--- + +## 📄 许可证 + +本项目遵循 MIT 许可证。 + +--- + +## 🤝 贡献 + +欢迎提交 Issue 和 Pull Request! + +--- + +## 📧 联系方式 + +如有问题或建议,请通过 GitHub Issues 联系。 + +--- + +**最后更新**:2025-01-12 +**版本**:2.5 + +**更新日志**: +- 2025-01-12 v2.5: 修复 API Key 版本认证头问题(401 错误),使用 `X-API-KEY` 与官方一致 +- 2025-01-12 v2.4: 新增 Gemini Pro Image (Nano Banana Pro) 节点,支持高分辨率生成 +- 2025-01-12 v2.3: 更新 GPT Image AuthToken 节点参数,匹配官方 ComfyUI API 节点 +- 2025-01-12 v2.2: 添加官方 ComfyUI API 节点的默认 system prompt +- 2025-01-12 v2.1: 修复 Gemini AuthToken 版本黑图问题,更新模型列表 +- 2025-01-11 v2.0: 初始版本,支持 AuthToken 和 API Key 两种认证方式 diff --git a/temperay/PD_comfyui_token_grabber.user.js b/temperay/PD_comfyui_token_grabber.user.js new file mode 100644 index 0000000..817242c --- /dev/null +++ b/temperay/PD_comfyui_token_grabber.user.js @@ -0,0 +1,506 @@ +// ==UserScript== +// @name Pandy-ComfyUI Token Grabber +// @namespace http://tampermonkey.net/ +// @version 3.5 +// @description 直接从 ComfyUI 提取 auth_token_comfy_org 并同步到 Pandy +// @author You +// @match *://localhost:8188/* +// @match *://127.0.0.1:8188/* +// @match *://127.0.0.1:8180/* +// @grant GM_setValue +// @grant GM_getValue +// @grant GM_setClipboard +// @grant GM_xmlhttpRequest +// @grant unsafeWindow +// @connect 127.0.0.1 +// @connect localhost +// @run-at document-idle +// ==/UserScript== + +(function () { + 'use strict'; + + const STORAGE_KEY = 'comfyui_auth_token'; + const POS_KEY = 'token_grabber_pos'; + const COLLAPSED_KEY = 'token_grabber_collapsed'; + + let foundToken = ''; + let isCollapsed = GM_getValue(COLLAPSED_KEY, false); + let savedPos = GM_getValue(POS_KEY, { x: null, y: 10 }); + + // 确保位置在可视范围内 + function clampPosition() { + const panel = document.getElementById('token-grabber-panel'); + if (!panel) return; + + const rect = panel.getBoundingClientRect(); + let needUpdate = false; + + // 如果面板超出右边界 + if (rect.right > window.innerWidth) { + panel.style.left = 'auto'; + panel.style.right = '10px'; + needUpdate = true; + } + // 如果面板超出下边界 + if (rect.bottom > window.innerHeight) { + panel.style.top = Math.max(10, window.innerHeight - rect.height - 10) + 'px'; + needUpdate = true; + } + // 如果面板超出左边界 + if (rect.left < 0) { + panel.style.left = '10px'; + panel.style.right = 'auto'; + needUpdate = true; + } + // 如果面板超出上边界 + if (rect.top < 0) { + panel.style.top = '10px'; + needUpdate = true; + } + } + + // 搜索 token + function searchToken() { + // 1. localStorage + for (let i = 0; i < localStorage.length; i++) { + const key = localStorage.key(i); + const value = localStorage.getItem(key); + if (value && value.includes('eyJ')) { + const token = extractJWT(value); + if (token && isValidJWT(token)) return token; + } + } + // 2. sessionStorage + for (let i = 0; i < sessionStorage.length; i++) { + const key = sessionStorage.key(i); + const value = sessionStorage.getItem(key); + if (value && value.includes('eyJ')) { + const token = extractJWT(value); + if (token && isValidJWT(token)) return token; + } + } + // 3. window 对象 + const props = ['app', 'api', 'comfyAPI']; + for (const prop of props) { + if (window[prop]) { + const token = deepSearch(window[prop], 'auth_token_comfy_org', 5); + if (token) return token; + } + } + return null; + } + + function extractJWT(str) { + const match = str.match(/eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/); + return match ? match[0] : null; + } + + function isValidJWT(token) { + try { + const parts = token.split('.'); + if (parts.length !== 3) return false; + let payload = parts[1]; + payload += '='.repeat((4 - payload.length % 4) % 4); + const info = JSON.parse(atob(payload)); + return info.exp !== undefined; + } catch (e) { return false; } + } + + function deepSearch(obj, key, depth) { + if (depth <= 0 || !obj || typeof obj !== 'object') return null; + try { + if (obj[key]) return obj[key]; + for (const k in obj) { + const result = deepSearch(obj[k], key, depth - 1); + if (result) return result; + } + } catch (e) { } + return null; + } + + function parseToken(token) { + try { + const parts = token.split('.'); + let payload = parts[1]; + payload += '='.repeat((4 - payload.length % 4) % 4); + const info = JSON.parse(atob(payload)); + const remaining = Math.floor((info.exp * 1000 - Date.now()) / 60000); + return { valid: remaining > 0, remaining }; + } catch (e) { return { valid: false, remaining: 0 }; } + } + + function updatePanel() { + const statusEl = document.getElementById('tg-status'); + const previewEl = document.getElementById('tg-preview'); + const expiryEl = document.getElementById('tg-expiry'); + const iconStatus = document.getElementById('tg-icon-status'); + + if (!foundToken) { + if (statusEl) { + statusEl.textContent = '❌ 未找到'; + statusEl.className = 'status expired'; + } + if (previewEl) previewEl.textContent = '请确保已登录'; + if (iconStatus) iconStatus.style.background = '#f66'; + return; + } + + const info = parseToken(foundToken); + if (info.valid) { + if (statusEl) { + statusEl.textContent = '✅ Token 已获取'; + statusEl.className = 'status captured'; + } + if (expiryEl) expiryEl.innerHTML = `⏱️ 剩余 ${info.remaining} 分钟`; + if (iconStatus) iconStatus.style.background = '#6f6'; + } else { + if (statusEl) { + statusEl.textContent = '❌ Token 已过期'; + statusEl.className = 'status expired'; + } + if (expiryEl) expiryEl.innerHTML = '请重新登录'; + if (iconStatus) iconStatus.style.background = '#f66'; + } + if (previewEl) previewEl.textContent = foundToken.substring(0, 50) + '...'; + } + + function copyToken() { + if (foundToken) { + GM_setClipboard(foundToken); + const btn = document.getElementById('tg-copy-btn'); + if (btn) { + btn.textContent = '✅ 已复制!'; + setTimeout(() => btn.textContent = '📋 复制 Token', 1500); + } + } else { + alert('未找到 Token'); + } + } + + function refreshToken() { + foundToken = searchToken() || ''; + if (foundToken) GM_setValue(STORAGE_KEY, foundToken); + updatePanel(); + } + + function toggleCollapse() { + isCollapsed = !isCollapsed; + GM_setValue(COLLAPSED_KEY, isCollapsed); + const panel = document.getElementById('token-grabber-panel'); + if (isCollapsed) { + panel.classList.add('collapsed'); + } else { + panel.classList.remove('collapsed'); + } + } + + // 同步到 Pandy Image 页面(使用 GM_xmlhttpRequest 绕过跨域) + async function syncToPandy() { + if (!foundToken) { + alert('未找到 Token'); + return; + } + + const btn = document.getElementById('tg-sync-btn'); + if (btn) btn.textContent = '⏳ 同步中...'; + + const PANDY_BASE = 'http://127.0.0.1:8180'; + + // 使用 GM_xmlhttpRequest 绕过跨域限制 + // 1. 先获取现有配置 + GM_xmlhttpRequest({ + method: 'GET', + url: `${PANDY_BASE}/config?name=settings`, + onload: function (response) { + let config = {}; + try { + if (response.status === 200) { + config = JSON.parse(response.responseText); + } + } catch (e) { } + + // 2. 合并 token + config.token = foundToken; + + // 3. POST 回去 + GM_xmlhttpRequest({ + method: 'POST', + url: `${PANDY_BASE}/config?name=settings`, + headers: { 'Content-Type': 'application/json' }, + data: JSON.stringify(config), + onload: function (resp) { + if (resp.status === 200) { + if (btn) { + btn.textContent = '✅ 已同步!'; + setTimeout(() => btn.textContent = '🚀 同步到 Pandy', 2000); + } + console.log('🍌 Token 已同步到 Pandy'); + } else { + fallbackCopy(btn); + } + }, + onerror: function () { + fallbackCopy(btn); + } + }); + }, + onerror: function () { + fallbackCopy(btn); + } + }); + } + + function fallbackCopy(btn) { + GM_setClipboard(foundToken); + if (btn) { + btn.textContent = '❌ 服务未启动,已复制'; + setTimeout(() => btn.textContent = '🚀 同步到 Pandy', 3000); + } + console.log('🍌 同步失败,请确保 Pandy 服务器已启动 (python server.py)'); + } + + unsafeWindow.copyToken = copyToken; + unsafeWindow.refreshToken = refreshToken; + unsafeWindow.toggleCollapse = toggleCollapse; + unsafeWindow.syncToPandy = syncToPandy; + + function createPanel() { + const panel = document.createElement('div'); + panel.id = 'token-grabber-panel'; + if (isCollapsed) panel.classList.add('collapsed'); + + // 设置位置 + if (savedPos.x !== null) { + panel.style.left = savedPos.x + 'px'; + panel.style.right = 'auto'; + } + panel.style.top = savedPos.y + 'px'; + + panel.innerHTML = ` + +

+ 🍌 + Token Grabber + + ▼ +
+
+
🔍 搜索中...
+
正在搜索...
+
+ + + +
+ `; + document.body.appendChild(panel); + + // 拖拽功能 + const header = document.getElementById('tg-header'); + let isDragging = false; + let startX, startY, startLeft, startTop; + + header.addEventListener('mousedown', (e) => { + if (e.target.classList.contains('collapse-btn')) return; + isDragging = true; + const rect = panel.getBoundingClientRect(); + startX = e.clientX; + startY = e.clientY; + startLeft = rect.left; + startTop = rect.top; + panel.style.right = 'auto'; + panel.style.left = startLeft + 'px'; + e.preventDefault(); + }); + + document.addEventListener('mousemove', (e) => { + if (!isDragging) return; + const dx = e.clientX - startX; + const dy = e.clientY - startY; + let newLeft = startLeft + dx; + let newTop = startTop + dy; + + // 边界限制 + newLeft = Math.max(0, Math.min(newLeft, window.innerWidth - panel.offsetWidth)); + newTop = Math.max(0, Math.min(newTop, window.innerHeight - panel.offsetHeight)); + + panel.style.left = newLeft + 'px'; + panel.style.top = newTop + 'px'; + }); + + document.addEventListener('mouseup', () => { + if (isDragging) { + isDragging = false; + // 保存位置 + const rect = panel.getBoundingClientRect(); + savedPos = { x: rect.left, y: rect.top }; + GM_setValue(POS_KEY, savedPos); + } + }); + } + + function init() { + console.log('🍌 Token Grabber: init() 开始执行'); + console.log('🍌 document.body:', document.body); + + if (!document.body) { + console.log('🍌 body 不存在,延迟重试...'); + setTimeout(init, 500); + return; + } + + createPanel(); + console.log('🍌 面板已创建'); + + // 确保面板在可视范围内 + setTimeout(clampPosition, 100); + + // 监听窗口大小变化 + window.addEventListener('resize', clampPosition); + + setTimeout(() => { + foundToken = searchToken() || GM_getValue(STORAGE_KEY, ''); + if (foundToken) GM_setValue(STORAGE_KEY, foundToken); + updatePanel(); + console.log('🍌 Token 搜索完成:', foundToken ? '找到' : '未找到'); + }, 1500); + + setInterval(() => { + const newToken = searchToken(); + if (newToken && newToken !== foundToken) { + foundToken = newToken; + GM_setValue(STORAGE_KEY, foundToken); + updatePanel(); + } + }, 10000); + } + + // 多种方式确保执行 + console.log('🍌 Token Grabber: 脚本已加载, readyState:', document.readyState); + + if (document.readyState === 'complete') { + init(); + } else if (document.readyState === 'interactive') { + setTimeout(init, 100); + } else { + window.addEventListener('load', init); + document.addEventListener('DOMContentLoaded', () => setTimeout(init, 100)); + } +})();