XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/gpt4free

feat: add CLI entry points for GeminiCLI and QwenCode providers

6472b477
hlohaus <983577+hlohaus@users.noreply.github.com>
提交于

代码差异

3 个文件 +737 -4
Modified g4f/Provider/qwen/QwenCode.py +162 -2
@@ -1,10 +1,18 @@
1 1 from __future__ import annotations
2 2
3 import sys
4 import json
5 import time
6 import asyncio
7 from pathlib import Path
8 from typing import Optional
9
3 10 from ...typing import Messages, AsyncResult
4 11 from ..template import OpenaiTemplate
5 12 from .qwenContentGenerator import QwenContentGenerator
6 13 from .qwenOAuth2 import QwenOAuth2Client
7 from .sharedTokenManager import TokenManagerError
14 from .sharedTokenManager import TokenManagerError, SharedTokenManager
15 from .oauthFlow import launch_browser_for_oauth
8 16
9 17 class QwenCode(OpenaiTemplate):
10 18 label = "Qwen Code 🤖"
@@ -70,4 +78,156 @@ class QwenCode(OpenaiTemplate):
70 78 else:
71 79 yield chunk
72 80 except:
73 raise
81 raise
82
83 @classmethod
84 async def login(cls, credentials_path: Optional[Path] = None) -> SharedTokenManager:
85 """
86 Perform interactive OAuth login and save credentials.
87
88 Args:
89 credentials_path: Path to save credentials (default: g4f cache)
90
91 Returns:
92 SharedTokenManager with active credentials
93
94 Example:
95 >>> import asyncio
96 >>> from g4f.Provider.qwen import QwenCode
97 >>> asyncio.run(QwenCode.login())
98 """
99 print("\n" + "=" * 60)
100 print("QwenCode OAuth Login")
101 print("=" * 60)
102
103 await launch_browser_for_oauth()
104
105 shared_manager = SharedTokenManager.getInstance()
106 print("=" * 60 + "\n")
107
108 return shared_manager
109
110 @classmethod
111 def has_credentials(cls) -> bool:
112 """Check if valid credentials exist."""
113 shared_manager = SharedTokenManager.getInstance()
114 path = shared_manager.getCredentialFilePath()
115 return path.exists()
116
117 @classmethod
118 def get_credentials_path(cls) -> Optional[Path]:
119 """Get path to credentials file if it exists."""
120 shared_manager = SharedTokenManager.getInstance()
121 path = shared_manager.getCredentialFilePath()
122 if path.exists():
123 return path
124 return None
125
126
127 async def main():
128 """CLI entry point for QwenCode authentication."""
129 import argparse
130
131 parser = argparse.ArgumentParser(
132 description="QwenCode OAuth Authentication for gpt4free",
133 formatter_class=argparse.RawDescriptionHelpFormatter,
134 epilog="""
135 Examples:
136 %(prog)s login # Interactive device code login
137 %(prog)s status # Check authentication status
138 %(prog)s logout # Remove saved credentials
139 """
140 )
141
142 subparsers = parser.add_subparsers(dest="command", help="Commands")
143
144 # Login command
145 subparsers.add_parser("login", help="Authenticate with Qwen")
146
147 # Status command
148 subparsers.add_parser("status", help="Check authentication status")
149
150 # Logout command
151 subparsers.add_parser("logout", help="Remove saved credentials")
152
153 args = parser.parse_args()
154
155 if args.command == "login":
156 try:
157 await QwenCode.login()
158 except KeyboardInterrupt:
159 print("\n\nLogin cancelled.")
160 sys.exit(1)
161 except Exception as e:
162 print(f"\n❌ Login failed: {e}")
163 sys.exit(1)
164
165 elif args.command == "status":
166 print("\nQwenCode Authentication Status")
167 print("=" * 40)
168
169 if QwenCode.has_credentials():
170 creds_path = QwenCode.get_credentials_path()
171 print(f"✓ Credentials found at: {creds_path}")
172
173 try:
174 with creds_path.open() as f:
175 creds = json.load(f)
176
177 expiry = creds.get("expiry_date")
178 if expiry:
179 expiry_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(expiry / 1000))
180 if expiry / 1000 > time.time():
181 print(f" Token expires: {expiry_time}")
182 else:
183 print(f" Token expired: {expiry_time} (will auto-refresh)")
184
185 if creds.get("resource_url"):
186 print(f" Endpoint: {creds['resource_url']}")
187 except Exception as e:
188 print(f" (Could not read credential details: {e})")
189 else:
190 print("✗ No credentials found")
191 print(f"\nRun 'g4f-qwencode login' to authenticate.")
192
193 print()
194
195 elif args.command == "logout":
196 print("\nQwenCode Logout")
197 print("=" * 40)
198
199 removed = False
200
201 shared_manager = SharedTokenManager.getInstance()
202 path = shared_manager.getCredentialFilePath()
203
204 if path.exists():
205 path.unlink()
206 print(f"✓ Removed: {path}")
207 removed = True
208
209 # Also try the default location
210 default_path = Path.home() / ".qwen" / "oauth_creds.json"
211 if default_path.exists() and default_path != path:
212 default_path.unlink()
213 print(f"✓ Removed: {default_path}")
214 removed = True
215
216 if removed:
217 print("\n✓ Credentials removed successfully.")
218 else:
219 print("No credentials found to remove.")
220
221 print()
222
223 else:
224 parser.print_help()
225
226
227 def cli_main():
228 """Synchronous CLI entry point for setup.py console_scripts."""
229 asyncio.run(main())
230
231
232 if __name__ == "__main__":
233 cli_main()
Modified setup.py +2 -0
@@ -120,6 +120,8 @@ setup(
120 120 'g4f=g4f.cli:main',
121 121 'g4f-mcp=g4f.mcp.server:main',
122 122 'g4f-antigravity=g4f.Provider.needs_auth.Antigravity:cli_main',
123 'g4f-geminicli=g4f.Provider.needs_auth.GeminiCLI:cli_main',
124 'g4f-qwencode=g4f.Provider.qwen.QwenCode:cli_main',
123 125 ],
124 126 },
125 127 url='https://github.com/xtekky/gpt4free', # Link to your GitHub repository