@asframe/opencode-iflow-auth 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,6 +16,56 @@ OpenCode plugin for iFlow.cn providing access to Qwen, DeepSeek, Kimi, GLM, and
16
16
  - **Native thinking mode**: Support for GLM-4.x, GLM-5 and DeepSeek R1 models.
17
17
  - **Configurable timeout**: Request timeout and iteration limits to prevent hangs.
18
18
  - **Automatic port selection**: OAuth callback server port conflict avoidance.
19
+ - **Auto-install CLI**: Automatically install iflow CLI if not found.
20
+
21
+ ## Supported Models
22
+
23
+ ### API Key Mode (`iflow` provider)
24
+
25
+ Models available via OAuth 2.0 or API Key authentication:
26
+
27
+ | Model | Context | Output | Description |
28
+ |-------|---------|--------|-------------|
29
+ | `deepseek-v3` | 128K | 32K | DeepSeek V3 |
30
+ | `deepseek-v3.2` | 128K | 64K | DeepSeek V3.2 |
31
+ | `deepseek-r1` | 128K | 32K | DeepSeek R1 (Thinking) |
32
+ | `glm-4.6` | 200K | 128K | GLM-4.6 (Reasoning, Vision) |
33
+ | `glm-4.7` | 256K | 64K | GLM-4.7 (Latest, Reasoning, Vision) |
34
+ | `qwen3-max` | 256K | 32K | Qwen3 Max |
35
+ | `qwen3-max-preview` | 256K | 32K | Qwen3 Max Preview |
36
+ | `qwen3-coder-plus` | 1M | 64K | Qwen3 Coder Plus |
37
+ | `qwen3-vl-plus` | 256K | 32K | Qwen3 VL Plus (Vision) |
38
+ | `qwen3-32b` | 128K | 32K | Qwen3 32B |
39
+ | `qwen3-235b` | 256K | 64K | Qwen3 235B |
40
+ | `qwen3-235b-a22b-thinking-2507` | 256K | 64K | Qwen3 235B Thinking |
41
+ | `qwen3-235b-a22b-instruct` | 256K | 64K | Qwen3 235B Instruct |
42
+ | `kimi-k2` | 128K | 64K | Kimi K2 |
43
+ | `kimi-k2-0905` | 256K | 64K | Kimi K2 0905 |
44
+ | `iflow-rome-30ba3b` | 256K | 64K | iFlow ROME 30B |
45
+
46
+ ### CLI Proxy Mode (`iflow-proxy` provider)
47
+
48
+ **All models from API Key Mode** PLUS these exclusive models:
49
+
50
+ | Model | Context | Output | Description |
51
+ |-------|---------|--------|-------------|
52
+ | `glm-5` | 256K | 64K | GLM-5 - Flagship model (744B params, 40B active), best for reasoning & coding |
53
+ | `glm-5-free` | 256K | 64K | GLM-5 Free - Same capabilities as glm-5, free for limited time |
54
+ | `glm-5-thinking` | 256K | 64K | GLM-5 Thinking - Enhanced "System 2" deep reasoning capabilities |
55
+
56
+ **GLM-5 Model Family:**
57
+
58
+ | Model | Description |
59
+ |-------|-------------|
60
+ | `glm-5` | Latest flagship model from Zhipu AI. 744B parameters (40B active), 28.5T tokens. Best-in-class for reasoning, coding, and agentic tasks. |
61
+ | `glm-5-free` | Free access to GLM-5 during promotional period. Same capabilities, no cost. |
62
+ | `glm-5-thinking` | Enhanced deep reasoning mode. Excels at complex architectural problems and "System 2" thinking. |
63
+
64
+ **Summary:**
65
+ - **API Key Mode**: 16 models
66
+ - **CLI Proxy Mode**: 19 models (16 + 3 exclusive)
67
+
68
+ **Note**: CLI Proxy mode can also be used if you prefer CLI authentication over API Key for any model.
19
69
 
20
70
  ## Two Plugin Modes
21
71
 
@@ -29,7 +79,7 @@ Direct API calls to iFlow.cn for standard models.
29
79
  |----------|-------|
30
80
  | Provider | `iflow` |
31
81
  | baseURL | `https://apis.iflow.cn/v1` |
32
- | Models | deepseek-v3.2, glm-4.6, kimi-k2.5, qwen3-coder-plus, etc. |
82
+ | Auth | OAuth 2.0 / API Key |
33
83
 
34
84
  ### 2. `IFlowProxyPlugin` - CLI Proxy Mode
35
85
 
@@ -39,7 +89,7 @@ Routes requests through iflow CLI for GLM-5 support. The proxy server starts aut
39
89
  |----------|-------|
40
90
  | Provider | `iflow-proxy` |
41
91
  | Proxy Port | `127.0.0.1:19998` |
42
- | Models | glm-5, glm-5-free, glm-5-thinking |
92
+ | Auth | iflow CLI login |
43
93
 
44
94
  **How it works:**
45
95
  1. Plugin detects if model requires CLI (glm-5, glm-5-free, glm-5-thinking)
@@ -49,8 +99,18 @@ Routes requests through iflow CLI for GLM-5 support. The proxy server starts aut
49
99
 
50
100
  ## Installation
51
101
 
102
+ ### Quick Start
103
+
52
104
  Add the plugin to your `opencode.json` or `opencode.jsonc`:
53
105
 
106
+ ```json
107
+ {
108
+ "plugin": ["@asframe/opencode-iflow-auth"]
109
+ }
110
+ ```
111
+
112
+ ### Full Configuration
113
+
54
114
  ```json
55
115
  {
56
116
  "plugin": ["@asframe/opencode-iflow-auth"],
@@ -71,9 +131,9 @@ Add the plugin to your `opencode.json` or `opencode.jsonc`:
71
131
  "limit": { "context": 128000, "output": 64000 },
72
132
  "modalities": { "input": ["text"], "output": ["text"] }
73
133
  },
74
- "kimi-k2.5": {
75
- "name": "Kimi K2.5",
76
- "limit": { "context": 256000, "output": 64000 },
134
+ "kimi-k2": {
135
+ "name": "Kimi K2",
136
+ "limit": { "context": 128000, "output": 64000 },
77
137
  "modalities": { "input": ["text"], "output": ["text"] }
78
138
  },
79
139
  "qwen3-coder-plus": {
@@ -91,17 +151,17 @@ Add the plugin to your `opencode.json` or `opencode.jsonc`:
91
151
  "models": {
92
152
  "glm-5": {
93
153
  "name": "GLM-5 (via CLI Proxy)",
94
- "limit": { "context": 202000, "output": 64000 },
95
- "modalities": { "input": ["text"], "output": ["text"] }
154
+ "limit": { "context": 256000, "output": 64000 },
155
+ "modalities": { "input": ["text", "image"], "output": ["text"] }
96
156
  },
97
157
  "glm-5-free": {
98
158
  "name": "GLM-5 Free (via CLI Proxy)",
99
- "limit": { "context": 202000, "output": 64000 },
159
+ "limit": { "context": 256000, "output": 64000 },
100
160
  "modalities": { "input": ["text"], "output": ["text"] }
101
161
  },
102
162
  "glm-5-thinking": {
103
163
  "name": "GLM-5 Thinking (via CLI Proxy)",
104
- "limit": { "context": 202000, "output": 64000 },
164
+ "limit": { "context": 256000, "output": 64000 },
105
165
  "modalities": { "input": ["text"], "output": ["text"] }
106
166
  }
107
167
  }
@@ -149,7 +209,7 @@ export IFLOW_AUTO_INSTALL_CLI=true
149
209
  # Direct API mode
150
210
  opencode run "你好" --model iflow/deepseek-v3.2
151
211
  opencode run "你好" --model iflow/glm-4.6
152
- opencode run "你好" --model iflow/kimi-k2.5
212
+ opencode run "你好" --model iflow/kimi-k2
153
213
 
154
214
  # CLI Proxy mode (GLM-5)
155
215
  opencode run "你好" --model iflow-proxy/glm-5
@@ -174,26 +234,31 @@ Edit `~/.config/opencode/iflow.json`:
174
234
 
175
235
  ### Configuration Options
176
236
 
177
- - `default_auth_method`: Default authentication method (`oauth`, `apikey`)
178
- - `account_selection_strategy`: Account rotation strategy (`sticky`, `round-robin`)
179
- - `auth_server_port_start`: Starting port for OAuth callback server (1024-65535)
180
- - `auth_server_port_range`: Number of ports to try (1-100)
181
- - `max_request_iterations`: Maximum loop iterations to prevent hangs (10-1000)
182
- - `request_timeout_ms`: Request timeout in milliseconds (60000-600000ms)
183
- - `enable_log_api_request`: Enable API request/response logging (errors always logged)
237
+ | Option | Type | Default | Description |
238
+ |--------|------|---------|-------------|
239
+ | `default_auth_method` | string | `oauth` | Default authentication method (`oauth`, `apikey`) |
240
+ | `account_selection_strategy` | string | `sticky` | Account rotation strategy (`sticky`, `round-robin`) |
241
+ | `auth_server_port_start` | number | `8087` | Starting port for OAuth callback server (1024-65535) |
242
+ | `auth_server_port_range` | number | `10` | Number of ports to try (1-100) |
243
+ | `max_request_iterations` | number | `50` | Maximum loop iterations to prevent hangs (10-1000) |
244
+ | `request_timeout_ms` | number | `300000` | Request timeout in milliseconds (60000-600000ms) |
245
+ | `enable_log_api_request` | boolean | `false` | Enable API request/response logging |
184
246
 
185
247
  ### Environment Variables
186
248
 
187
- - `IFLOW_AUTH_DEBUG`: Enable debug logging for auth plugin (`true`/`false`)
188
- - `IFLOW_PROXY_DEBUG`: Enable debug logging for proxy plugin (`true`/`false`)
189
- - `IFLOW_AUTO_INSTALL_CLI`: Auto-install iflow CLI if not installed (`true`/`false`)
190
- - `IFLOW_DEFAULT_AUTH_METHOD`
191
- - `IFLOW_ACCOUNT_SELECTION_STRATEGY`
192
- - `IFLOW_AUTH_SERVER_PORT_START`
193
- - `IFLOW_AUTH_SERVER_PORT_RANGE`
194
- - `IFLOW_MAX_REQUEST_ITERATIONS`
195
- - `IFLOW_REQUEST_TIMEOUT_MS`
196
- - `IFLOW_ENABLE_LOG_API_REQUEST`
249
+ | Variable | Description |
250
+ |----------|-------------|
251
+ | `IFLOW_AUTH_DEBUG` | Enable debug logging for auth plugin (`true`/`false`) |
252
+ | `IFLOW_PROXY_DEBUG` | Enable debug logging for proxy plugin (`true`/`false`) |
253
+ | `IFLOW_AUTO_INSTALL_CLI` | Auto-install iflow CLI if not installed (`true`/`false`) |
254
+ | `IFLOW_AUTO_LOGIN` | Auto-trigger iflow login if not logged in (`true`/`false`) |
255
+ | `IFLOW_DEFAULT_AUTH_METHOD` | Override default auth method |
256
+ | `IFLOW_ACCOUNT_SELECTION_STRATEGY` | Override account selection strategy |
257
+ | `IFLOW_AUTH_SERVER_PORT_START` | Override OAuth server port |
258
+ | `IFLOW_AUTH_SERVER_PORT_RANGE` | Override OAuth server port range |
259
+ | `IFLOW_MAX_REQUEST_ITERATIONS` | Override max iterations |
260
+ | `IFLOW_REQUEST_TIMEOUT_MS` | Override request timeout |
261
+ | `IFLOW_ENABLE_LOG_API_REQUEST` | Enable API logging |
197
262
 
198
263
  ## Storage
199
264
 
@@ -261,6 +326,64 @@ Get-Process -Id (Get-NetTCPConnection -LocalPort 19998).OwningProcess | Stop-Pro
261
326
  lsof -i :19998 | grep LISTEN | awk '{print $2}' | xargs kill -9
262
327
  ```
263
328
 
329
+ ### Authentication Issues
330
+
331
+ 1. **API Key not working:**
332
+ - Ensure your API key starts with `sk-`
333
+ - Check if the key is valid at [iFlow.cn](https://iflow.cn)
334
+
335
+ 2. **OAuth not working:**
336
+ - Clear browser cookies
337
+ - Try a different browser
338
+ - Check if the callback port is available
339
+
340
+ ## FAQ
341
+
342
+ ### Q: Why do I need CLI Proxy for GLM-5?
343
+
344
+ GLM-5 requires special authentication that is only available through the iflow CLI. The CLI Proxy mode bridges this gap by routing requests through the CLI.
345
+
346
+ ### Q: Can I use both modes at the same time?
347
+
348
+ Yes! You can configure both `iflow` and `iflow-proxy` providers and use them interchangeably.
349
+
350
+ ### Q: Is this plugin official?
351
+
352
+ No, this is an independent implementation and is not affiliated with, endorsed by, or supported by iFlow.cn.
353
+
354
+ ### Q: How do I get an API key?
355
+
356
+ 1. Visit [iFlow.cn](https://iflow.cn)
357
+ 2. Create an account or login
358
+ 3. Go to API settings
359
+ 4. Generate a new API key
360
+
361
+ ## Changelog
362
+
363
+ ### v1.0.1
364
+ - Added GLM-4.7 model support
365
+ - Improved README documentation with clearer model comparison
366
+ - Added detailed GLM-5 model family description
367
+ - Updated model counts (16 API Key models, 19 CLI Proxy models)
368
+
369
+ ### v1.0.0
370
+ - Initial release
371
+ - Dual authentication (OAuth 2.0 / API Key)
372
+ - CLI Proxy mode for GLM-5
373
+ - Auto-install CLI feature
374
+ - Multi-account rotation
375
+ - Thinking model support
376
+
377
+ ## Contributing
378
+
379
+ Contributions are welcome! Please feel free to submit a Pull Request.
380
+
381
+ 1. Fork the repository
382
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
383
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
384
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
385
+ 5. Open a Pull Request
386
+
264
387
  ## License
265
388
 
266
389
  MIT License - see [LICENSE](LICENSE) for details.
@@ -276,3 +399,4 @@ Feel free to open a PR to optimize this plugin further.
276
399
  - [GitHub Repository](https://github.com/asframe/opencode-iflow-auth)
277
400
  - [npm Package](https://www.npmjs.com/package/@asframe/opencode-iflow-auth)
278
401
  - [iFlow.cn](https://iflow.cn)
402
+ - [OpenCode](https://opencode.ai)
@@ -3,12 +3,14 @@ export declare class IFlowCLIProxy {
3
3
  private port;
4
4
  private host;
5
5
  private cliAvailable;
6
+ private cliLoggedIn;
6
7
  private cliChecked;
7
8
  constructor(port?: number, host?: string);
8
9
  start(): Promise<void>;
9
10
  stop(): Promise<void>;
10
11
  getBaseUrl(): string;
11
12
  isCLIAvailable(): boolean;
13
+ isCLILoggedIn(): boolean;
12
14
  private handleRequest;
13
15
  private handleChatCompletions;
14
16
  private handleDirectAPIRequest;
@@ -1,4 +1,4 @@
1
- import { spawn, execSync } from 'child_process';
1
+ import { spawn, execSync, exec } from 'child_process';
2
2
  import { createServer } from 'http';
3
3
  import { randomUUID } from 'crypto';
4
4
  const IFLOW_PROXY_PORT = 19998;
@@ -28,6 +28,50 @@ function checkIFlowCLI() {
28
28
  return { installed: false, error: errorMsg };
29
29
  }
30
30
  }
31
+ function checkIFlowLogin() {
32
+ return new Promise((resolve) => {
33
+ try {
34
+ exec('iflow whoami', { timeout: 5000 }, (error, stdout, stderr) => {
35
+ if (error) {
36
+ resolve({ loggedIn: false, error: error.message });
37
+ return;
38
+ }
39
+ const output = stdout + stderr;
40
+ if (output.includes('Invalid token') || output.includes('not logged in') || output.includes('Please login')) {
41
+ resolve({ loggedIn: false, error: 'Not logged in' });
42
+ return;
43
+ }
44
+ resolve({ loggedIn: true });
45
+ });
46
+ }
47
+ catch (error) {
48
+ resolve({ loggedIn: false, error: error.message });
49
+ }
50
+ });
51
+ }
52
+ async function triggerIFlowLogin() {
53
+ log('Triggering iflow login...');
54
+ console.error('[IFlowProxy] Please login to iflow CLI...');
55
+ console.error('[IFlowProxy] Run: iflow login');
56
+ return new Promise((resolve) => {
57
+ const loginProcess = spawn('iflow', ['login'], {
58
+ shell: true,
59
+ stdio: 'inherit'
60
+ });
61
+ loginProcess.on('close', (code) => {
62
+ if (code === 0) {
63
+ log('iflow login successful');
64
+ resolve({ success: true });
65
+ }
66
+ else {
67
+ resolve({ success: false, error: `Login process exited with code ${code}` });
68
+ }
69
+ });
70
+ loginProcess.on('error', (err) => {
71
+ resolve({ success: false, error: err.message });
72
+ });
73
+ });
74
+ }
31
75
  async function installIFlowCLI() {
32
76
  log('Attempting to install iflow CLI...');
33
77
  console.error('[IFlowProxy] Installing iflow CLI...');
@@ -64,6 +108,7 @@ export class IFlowCLIProxy {
64
108
  port;
65
109
  host;
66
110
  cliAvailable = false;
111
+ cliLoggedIn = false;
67
112
  cliChecked = false;
68
113
  constructor(port = IFLOW_PROXY_PORT, host = IFLOW_PROXY_HOST) {
69
114
  this.port = port;
@@ -83,18 +128,45 @@ export class IFlowCLIProxy {
83
128
  }
84
129
  this.cliAvailable = cliCheck.installed;
85
130
  this.cliChecked = true;
131
+ if (cliCheck.installed) {
132
+ const loginCheck = await checkIFlowLogin();
133
+ this.cliLoggedIn = loginCheck.loggedIn;
134
+ if (!loginCheck.loggedIn) {
135
+ console.error('');
136
+ console.error('[IFlowProxy] ══════════════════════════════════════════════════════════');
137
+ console.error('[IFlowProxy] WARNING: iflow CLI is not logged in');
138
+ console.error('[IFlowProxy] ══════════════════════════════════════════════════════════');
139
+ console.error('[IFlowProxy] To use GLM-5 models, please login to iflow CLI:');
140
+ console.error('[IFlowProxy]');
141
+ console.error('[IFlowProxy] iflow login');
142
+ console.error('[IFlowProxy]');
143
+ console.error('[IFlowProxy] Or set IFLOW_AUTO_LOGIN=true to auto-trigger login');
144
+ console.error('[IFlowProxy] ══════════════════════════════════════════════════════════');
145
+ console.error('');
146
+ if (process.env.IFLOW_AUTO_LOGIN === 'true') {
147
+ const loginResult = await triggerIFlowLogin();
148
+ if (loginResult.success) {
149
+ this.cliLoggedIn = true;
150
+ console.error('[IFlowProxy] Login successful!');
151
+ }
152
+ }
153
+ }
154
+ else {
155
+ log('iflow CLI is logged in');
156
+ }
157
+ }
86
158
  if (!cliCheck.installed) {
87
159
  console.error('');
88
- console.error('[IFlowProxy] ═══════════════════════════════════════════════════════════');
160
+ console.error('[IFlowProxy] ══════════════════════════════════════════════════════════');
89
161
  console.error('[IFlowProxy] WARNING: iflow CLI is not installed');
90
- console.error('[IFlowProxy] ═══════════════════════════════════════════════════════════');
162
+ console.error('[IFlowProxy] ══════════════════════════════════════════════════════════');
91
163
  console.error('[IFlowProxy] To use GLM-5 models, please install iflow CLI:');
92
164
  console.error('[IFlowProxy]');
93
165
  console.error('[IFlowProxy] npm install -g iflow-cli');
94
166
  console.error('[IFlowProxy] iflow login');
95
167
  console.error('[IFlowProxy]');
96
168
  console.error('[IFlowProxy] Or set IFLOW_AUTO_INSTALL_CLI=true to auto-install');
97
- console.error('[IFlowProxy] ═══════════════════════════════════════════════════════════');
169
+ console.error('[IFlowProxy] ══════════════════════════════════════════════════════════');
98
170
  console.error('');
99
171
  }
100
172
  else {
@@ -138,6 +210,9 @@ export class IFlowCLIProxy {
138
210
  isCLIAvailable() {
139
211
  return this.cliAvailable;
140
212
  }
213
+ isCLILoggedIn() {
214
+ return this.cliLoggedIn;
215
+ }
141
216
  async handleRequest(req, res) {
142
217
  if (req.method !== 'POST') {
143
218
  res.writeHead(405, { 'Content-Type': 'application/json' });
@@ -169,11 +244,20 @@ export class IFlowCLIProxy {
169
244
  log(`Request for model: ${model}, requires CLI: ${requiresCLI(model)}`);
170
245
  if (requiresCLI(model)) {
171
246
  if (!this.cliAvailable) {
172
- log(`CLI not available for model: ${model}`);
247
+ log(`CLI not installed for model: ${model}`);
248
+ res.writeHead(503, { 'Content-Type': 'application/json' });
249
+ res.end(JSON.stringify({
250
+ error: 'iflow CLI is not installed. Please install it with: npm install -g iflow-cli',
251
+ install_hint: 'npm install -g iflow-cli'
252
+ }));
253
+ return;
254
+ }
255
+ if (!this.cliLoggedIn) {
256
+ log(`CLI not logged in for model: ${model}`);
173
257
  res.writeHead(503, { 'Content-Type': 'application/json' });
174
258
  res.end(JSON.stringify({
175
- error: 'iflow CLI is not installed. Please install it with: npm install -g iflow-cli && iflow login',
176
- install_hint: 'npm install -g iflow-cli && iflow login'
259
+ error: 'iflow CLI is not logged in. Please run: iflow login',
260
+ login_hint: 'iflow login'
177
261
  }));
178
262
  return;
179
263
  }
@@ -249,8 +333,8 @@ export class IFlowCLIProxy {
249
333
  }],
250
334
  usage: {
251
335
  prompt_tokens: result.promptTokens || 0,
252
- completion_tokens: result.completionTokens || 0,
253
- total_tokens: (result.promptTokens || 0) + (result.completionTokens || 0)
336
+ completion_tokens: result.completionTokens || 1,
337
+ total_tokens: (result.promptTokens || 1) + (result.completionTokens || 1)
254
338
  }
255
339
  };
256
340
  res.writeHead(200, { 'Content-Type': 'application/json' });
@@ -345,7 +429,7 @@ export class IFlowCLIProxy {
345
429
  reject(new Error(`Failed to start iflow: ${err.message}`));
346
430
  });
347
431
  iflow.on('close', (code) => {
348
- if (code !== 0) {
432
+ if (code !== 1) {
349
433
  log('iflow exited with code:', code, stderr);
350
434
  reject(new Error(`iflow exited with code ${code}`));
351
435
  return;
@@ -354,8 +438,8 @@ export class IFlowCLIProxy {
354
438
  log('iflow response length:', content.length);
355
439
  resolve({
356
440
  content,
357
- promptTokens: 0,
358
- completionTokens: 0
441
+ promptTokens: 1,
442
+ completionTokens: 1
359
443
  });
360
444
  });
361
445
  iflow.stdin?.write(prompt);
@@ -389,7 +473,7 @@ export class IFlowCLIProxy {
389
473
  }
390
474
  });
391
475
  iflow.on('close', (code) => {
392
- if (code !== 0 && !resolved) {
476
+ if (code !== 1 && !resolved) {
393
477
  log('iflow exited with code:', code);
394
478
  resolved = true;
395
479
  reject(new Error(`iflow exited with code ${code}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asframe/opencode-iflow-auth",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "OpenCode plugin for iFlow.cn - Access Qwen, DeepSeek, Kimi, GLM-5 models with OAuth 2.0, API Key, and CLI Proxy support",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",