@asframe/opencode-iflow-auth 1.0.0

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.
Files changed (42) hide show
  1. package/README.md +278 -0
  2. package/dist/constants.d.ts +33 -0
  3. package/dist/constants.js +303 -0
  4. package/dist/iflow/apikey.d.ts +6 -0
  5. package/dist/iflow/apikey.js +17 -0
  6. package/dist/iflow/oauth.d.ts +20 -0
  7. package/dist/iflow/oauth.js +113 -0
  8. package/dist/iflow/proxy.d.ts +23 -0
  9. package/dist/iflow/proxy.js +435 -0
  10. package/dist/index.d.ts +4 -0
  11. package/dist/index.js +2 -0
  12. package/dist/plugin/accounts.d.ts +24 -0
  13. package/dist/plugin/accounts.js +205 -0
  14. package/dist/plugin/auth-page.d.ts +3 -0
  15. package/dist/plugin/auth-page.js +573 -0
  16. package/dist/plugin/cli.d.ts +11 -0
  17. package/dist/plugin/cli.js +77 -0
  18. package/dist/plugin/config/index.d.ts +2 -0
  19. package/dist/plugin/config/index.js +2 -0
  20. package/dist/plugin/config/loader.d.ts +3 -0
  21. package/dist/plugin/config/loader.js +110 -0
  22. package/dist/plugin/config/schema.d.ts +35 -0
  23. package/dist/plugin/config/schema.js +22 -0
  24. package/dist/plugin/errors.d.ts +14 -0
  25. package/dist/plugin/errors.js +25 -0
  26. package/dist/plugin/logger.d.ts +8 -0
  27. package/dist/plugin/logger.js +63 -0
  28. package/dist/plugin/server.d.ts +7 -0
  29. package/dist/plugin/server.js +98 -0
  30. package/dist/plugin/storage.d.ts +4 -0
  31. package/dist/plugin/storage.js +91 -0
  32. package/dist/plugin/token.d.ts +3 -0
  33. package/dist/plugin/token.js +26 -0
  34. package/dist/plugin/types.d.ts +58 -0
  35. package/dist/plugin/types.js +1 -0
  36. package/dist/plugin-iflow.d.ts +2 -0
  37. package/dist/plugin-iflow.js +141 -0
  38. package/dist/plugin-proxy.d.ts +2 -0
  39. package/dist/plugin-proxy.js +155 -0
  40. package/dist/plugin.d.ts +2 -0
  41. package/dist/plugin.js +2 -0
  42. package/package.json +63 -0
package/README.md ADDED
@@ -0,0 +1,278 @@
1
+ # OpenCode iFlow Auth Plugin
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@asframe/opencode-iflow-auth)](https://www.npmjs.com/package/@asframe/opencode-iflow-auth)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@asframe/opencode-iflow-auth)](https://www.npmjs.com/package/@asframe/opencode-iflow-auth)
5
+ [![license](https://img.shields.io/npm/l/@asframe/opencode-iflow-auth)](https://www.npmjs.com/package/@asframe/opencode-iflow-auth)
6
+ [![GitHub](https://img.shields.io/badge/GitHub-asframe%2Fopencode--iflow--auth-blue)](https://github.com/asframe/opencode-iflow-auth)
7
+
8
+ OpenCode plugin for iFlow.cn providing access to Qwen, DeepSeek, Kimi, GLM, and iFlow ROME models with dual authentication and CLI Proxy support.
9
+
10
+ ## Features
11
+
12
+ - **Dual authentication**: OAuth 2.0 (PKCE) and API Key support.
13
+ - **CLI Proxy mode**: Support GLM-5 through iflow CLI with automatic proxy server.
14
+ - **Multi-account rotation**: Sticky and round-robin strategies.
15
+ - **Automated token refresh**: Rate limit handling with exponential backoff.
16
+ - **Native thinking mode**: Support for GLM-4.x, GLM-5 and DeepSeek R1 models.
17
+ - **Configurable timeout**: Request timeout and iteration limits to prevent hangs.
18
+ - **Automatic port selection**: OAuth callback server port conflict avoidance.
19
+
20
+ ## Two Plugin Modes
21
+
22
+ This package exports two plugins:
23
+
24
+ ### 1. `IFlowPlugin` - Direct API Mode
25
+
26
+ Direct API calls to iFlow.cn for standard models.
27
+
28
+ | Property | Value |
29
+ |----------|-------|
30
+ | Provider | `iflow` |
31
+ | baseURL | `https://apis.iflow.cn/v1` |
32
+ | Models | deepseek-v3.2, glm-4.6, kimi-k2.5, qwen3-coder-plus, etc. |
33
+
34
+ ### 2. `IFlowProxyPlugin` - CLI Proxy Mode
35
+
36
+ Routes requests through iflow CLI for GLM-5 support. The proxy server starts automatically when OpenCode loads the plugin.
37
+
38
+ | Property | Value |
39
+ |----------|-------|
40
+ | Provider | `iflow-proxy` |
41
+ | Proxy Port | `127.0.0.1:19998` |
42
+ | Models | glm-5, glm-5-free, glm-5-thinking |
43
+
44
+ **How it works:**
45
+ 1. Plugin detects if model requires CLI (glm-5, glm-5-free, glm-5-thinking)
46
+ 2. Starts a local proxy server on port 19998
47
+ 3. Routes CLI-required models through `iflow` CLI via stdin
48
+ 4. Routes other models directly to iFlow API
49
+
50
+ ## Installation
51
+
52
+ Add the plugin to your `opencode.json` or `opencode.jsonc`:
53
+
54
+ ```json
55
+ {
56
+ "plugin": ["@asframe/opencode-iflow-auth"],
57
+ "provider": {
58
+ "iflow": {
59
+ "npm": "@ai-sdk/openai-compatible",
60
+ "options": {
61
+ "baseURL": "https://apis.iflow.cn/v1"
62
+ },
63
+ "models": {
64
+ "deepseek-v3.2": {
65
+ "name": "DeepSeek V3.2",
66
+ "limit": { "context": 128000, "output": 64000 },
67
+ "modalities": { "input": ["text"], "output": ["text"] }
68
+ },
69
+ "glm-4.6": {
70
+ "name": "GLM-4.6",
71
+ "limit": { "context": 128000, "output": 64000 },
72
+ "modalities": { "input": ["text"], "output": ["text"] }
73
+ },
74
+ "kimi-k2.5": {
75
+ "name": "Kimi K2.5",
76
+ "limit": { "context": 256000, "output": 64000 },
77
+ "modalities": { "input": ["text"], "output": ["text"] }
78
+ },
79
+ "qwen3-coder-plus": {
80
+ "name": "Qwen3 Coder Plus",
81
+ "limit": { "context": 1000000, "output": 64000 },
82
+ "modalities": { "input": ["text"], "output": ["text"] }
83
+ }
84
+ }
85
+ },
86
+ "iflow-proxy": {
87
+ "npm": "@ai-sdk/openai-compatible",
88
+ "options": {
89
+ "baseURL": "http://127.0.0.1:19998/v1"
90
+ },
91
+ "models": {
92
+ "glm-5": {
93
+ "name": "GLM-5 (via CLI Proxy)",
94
+ "limit": { "context": 202000, "output": 64000 },
95
+ "modalities": { "input": ["text"], "output": ["text"] }
96
+ },
97
+ "glm-5-free": {
98
+ "name": "GLM-5 Free (via CLI Proxy)",
99
+ "limit": { "context": 202000, "output": 64000 },
100
+ "modalities": { "input": ["text"], "output": ["text"] }
101
+ },
102
+ "glm-5-thinking": {
103
+ "name": "GLM-5 Thinking (via CLI Proxy)",
104
+ "limit": { "context": 202000, "output": 64000 },
105
+ "modalities": { "input": ["text"], "output": ["text"] }
106
+ }
107
+ }
108
+ }
109
+ }
110
+ }
111
+ ```
112
+
113
+ ## Setup
114
+
115
+ ### Direct API Mode
116
+
117
+ 1. Run `opencode auth login`.
118
+ 2. Select `Other`, type `iflow`, and press enter.
119
+ 3. Choose authentication method:
120
+ - **OAuth 2.0**: Follow browser flow for secure token-based authentication.
121
+ - **API Key**: Enter your iFlow API key (starts with `sk-`).
122
+
123
+ ### CLI Proxy Mode (for GLM-5)
124
+
125
+ 1. Install iflow CLI: `npm install -g iflow-cli`
126
+ 2. Login to iflow CLI: `iflow login`
127
+ 3. The proxy server will start automatically when using `iflow-proxy` provider.
128
+
129
+ **Auto-install CLI:**
130
+
131
+ If iflow CLI is not installed, the plugin can automatically install it for you. Enable this feature by setting the environment variable:
132
+
133
+ ```bash
134
+ # PowerShell
135
+ $env:IFLOW_AUTO_INSTALL_CLI = "true"
136
+
137
+ # Bash
138
+ export IFLOW_AUTO_INSTALL_CLI=true
139
+ ```
140
+
141
+ **Requirements for CLI Proxy:**
142
+ - Node.js 18+
143
+ - iflow CLI installed and logged in (or set `IFLOW_AUTO_INSTALL_CLI=true` to auto-install)
144
+ - Port 19998 available (or will use existing proxy if already running)
145
+
146
+ ## Usage
147
+
148
+ ```bash
149
+ # Direct API mode
150
+ opencode run "你好" --model iflow/deepseek-v3.2
151
+ opencode run "你好" --model iflow/glm-4.6
152
+ opencode run "你好" --model iflow/kimi-k2.5
153
+
154
+ # CLI Proxy mode (GLM-5)
155
+ opencode run "你好" --model iflow-proxy/glm-5
156
+ opencode run "你好" --model iflow-proxy/glm-5-thinking
157
+ ```
158
+
159
+ ## Configuration
160
+
161
+ Edit `~/.config/opencode/iflow.json`:
162
+
163
+ ```json
164
+ {
165
+ "default_auth_method": "oauth",
166
+ "account_selection_strategy": "round-robin",
167
+ "auth_server_port_start": 8087,
168
+ "auth_server_port_range": 10,
169
+ "max_request_iterations": 50,
170
+ "request_timeout_ms": 300000,
171
+ "enable_log_api_request": false
172
+ }
173
+ ```
174
+
175
+ ### Configuration Options
176
+
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)
184
+
185
+ ### Environment Variables
186
+
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`
197
+
198
+ ## Storage
199
+
200
+ **Linux/macOS:**
201
+ - Credentials: `~/.config/opencode/iflow-accounts.json`
202
+ - Plugin Config: `~/.config/opencode/iflow.json`
203
+
204
+ **Windows:**
205
+ - Credentials: `%APPDATA%\opencode\iflow-accounts.json`
206
+ - Plugin Config: `%APPDATA%\opencode\iflow.json`
207
+
208
+ ## Thinking Models
209
+
210
+ iFlow supports thinking models with customizable thinking budgets via variants:
211
+
212
+ ### GLM-4.6, GLM-5 & DeepSeek R1
213
+
214
+ ```json
215
+ {
216
+ "variants": {
217
+ "low": { "thinkingConfig": { "thinkingBudget": 1024 } },
218
+ "medium": { "thinkingConfig": { "thinkingBudget": 8192 } },
219
+ "max": { "thinkingConfig": { "thinkingBudget": 32768 } }
220
+ }
221
+ }
222
+ ```
223
+
224
+ ## Troubleshooting
225
+
226
+ ### CLI Proxy Issues
227
+
228
+ If you encounter issues with the CLI proxy:
229
+
230
+ 1. **Check if iflow CLI is installed:**
231
+ ```bash
232
+ iflow --version
233
+ ```
234
+
235
+ 2. **Check if you're logged in:**
236
+ ```bash
237
+ iflow login
238
+ ```
239
+
240
+ 3. **Test iflow CLI directly:**
241
+ ```bash
242
+ echo "你好" | iflow -m glm-5
243
+ ```
244
+
245
+ 4. **Enable debug logging:**
246
+ ```bash
247
+ $env:IFLOW_PROXY_DEBUG = "true"
248
+ opencode run "你好" --model iflow-proxy/glm-5
249
+ ```
250
+
251
+ ### Port Already in Use
252
+
253
+ If port 19998 is already in use, the plugin will detect it and use the existing proxy. If you need to restart the proxy:
254
+
255
+ ```bash
256
+ # Kill existing process on port 19998
257
+ # Windows
258
+ Get-Process -Id (Get-NetTCPConnection -LocalPort 19998).OwningProcess | Stop-Process -Force
259
+
260
+ # Linux/macOS
261
+ lsof -i :19998 | grep LISTEN | awk '{print $2}' | xargs kill -9
262
+ ```
263
+
264
+ ## License
265
+
266
+ MIT License - see [LICENSE](LICENSE) for details.
267
+
268
+ ## Disclaimer
269
+
270
+ This plugin is provided strictly for learning and educational purposes. It is an independent implementation and is not affiliated with, endorsed by, or supported by iFlow.cn. Use of this plugin is at your own risk.
271
+
272
+ Feel free to open a PR to optimize this plugin further.
273
+
274
+ ## Links
275
+
276
+ - [GitHub Repository](https://github.com/asframe/opencode-iflow-auth)
277
+ - [npm Package](https://www.npmjs.com/package/@asframe/opencode-iflow-auth)
278
+ - [iFlow.cn](https://iflow.cn)
@@ -0,0 +1,33 @@
1
+ export type IFlowAuthMethod = 'oauth' | 'apikey';
2
+ export declare function isValidAuthMethod(method: string): method is IFlowAuthMethod;
3
+ export declare const IFLOW_CONSTANTS: {
4
+ BASE_URL: string;
5
+ OAUTH_TOKEN_URL: string;
6
+ OAUTH_AUTHORIZE_URL: string;
7
+ USER_INFO_URL: string;
8
+ SUCCESS_REDIRECT: string;
9
+ CLIENT_ID: string;
10
+ CLIENT_SECRET: string;
11
+ AXIOS_TIMEOUT: number;
12
+ USER_AGENT: string;
13
+ CALLBACK_PORT_START: number;
14
+ CALLBACK_PORT_RANGE: number;
15
+ };
16
+ export declare const THINKING_MODELS: string[];
17
+ export declare function isThinkingModel(model: string): boolean;
18
+ export declare function applyThinkingConfig(body: any, model: string): any;
19
+ export interface IFlowModelConfig {
20
+ id: string;
21
+ name: string;
22
+ context: number;
23
+ output: number;
24
+ inputModalities: ('text' | 'image' | 'audio' | 'video' | 'pdf')[];
25
+ outputModalities: ('text' | 'image' | 'audio' | 'video' | 'pdf')[];
26
+ reasoning?: boolean;
27
+ toolcall?: boolean;
28
+ temperature?: boolean;
29
+ family?: string;
30
+ variants?: Record<string, Record<string, any>>;
31
+ }
32
+ export declare const IFLOW_MODELS: IFlowModelConfig[];
33
+ export declare function registerIFlowModels(provider: any): void;
@@ -0,0 +1,303 @@
1
+ export function isValidAuthMethod(method) {
2
+ return method === 'oauth' || method === 'apikey';
3
+ }
4
+ export const IFLOW_CONSTANTS = {
5
+ BASE_URL: 'https://apis.iflow.cn/v1',
6
+ OAUTH_TOKEN_URL: 'https://iflow.cn/oauth/token',
7
+ OAUTH_AUTHORIZE_URL: 'https://iflow.cn/oauth',
8
+ USER_INFO_URL: 'https://iflow.cn/api/oauth/getUserInfo',
9
+ SUCCESS_REDIRECT: 'https://iflow.cn/oauth/success',
10
+ CLIENT_ID: '10009311001',
11
+ CLIENT_SECRET: '4Z3YjXycVsQvyGF1etiNlIBB4RsqSDtW',
12
+ AXIOS_TIMEOUT: 120000,
13
+ USER_AGENT: 'OpenCode-iFlow',
14
+ CALLBACK_PORT_START: 8087,
15
+ CALLBACK_PORT_RANGE: 10
16
+ };
17
+ export const THINKING_MODELS = ['glm-4.6', 'glm-5', 'qwen3-235b-a22b-thinking-2507', 'deepseek-r1'];
18
+ export function isThinkingModel(model) {
19
+ return THINKING_MODELS.some((m) => model.startsWith(m));
20
+ }
21
+ export function applyThinkingConfig(body, model) {
22
+ const thinkingBudget = body.providerOptions?.thinkingConfig?.thinkingBudget;
23
+ const isThinkingEnabled = body.providerOptions?.thinkingConfig?.enabled !== false;
24
+ if (model.startsWith('glm-5')) {
25
+ const result = {
26
+ ...body,
27
+ temperature: 1,
28
+ top_p: 0.95,
29
+ };
30
+ if (isThinkingEnabled) {
31
+ result.chat_template_kwargs = { enable_thinking: true };
32
+ result.enable_thinking = true;
33
+ result.thinking = { type: 'enabled' };
34
+ if (thinkingBudget) {
35
+ result.thinking_budget = thinkingBudget;
36
+ }
37
+ }
38
+ else {
39
+ result.chat_template_kwargs = { enable_thinking: false };
40
+ result.enable_thinking = false;
41
+ result.thinking = { type: 'disabled' };
42
+ }
43
+ return result;
44
+ }
45
+ if (model.startsWith('glm-4')) {
46
+ const result = {
47
+ ...body,
48
+ chat_template_kwargs: {
49
+ enable_thinking: true,
50
+ clear_thinking: false
51
+ }
52
+ };
53
+ if (thinkingBudget) {
54
+ result.thinking_budget = thinkingBudget;
55
+ }
56
+ return result;
57
+ }
58
+ if (model.startsWith('deepseek-r1')) {
59
+ const result = { ...body };
60
+ if (thinkingBudget) {
61
+ result.thinking_budget = thinkingBudget;
62
+ }
63
+ return result;
64
+ }
65
+ return body;
66
+ }
67
+ export const IFLOW_MODELS = [
68
+ {
69
+ id: 'glm-5',
70
+ name: 'GLM-5',
71
+ context: 256000,
72
+ output: 64000,
73
+ inputModalities: ['text', 'image'],
74
+ outputModalities: ['text'],
75
+ reasoning: true,
76
+ toolcall: true,
77
+ family: 'glm',
78
+ variants: {
79
+ low: { thinkingConfig: { thinkingBudget: 1024 } },
80
+ medium: { thinkingConfig: { thinkingBudget: 8192 } },
81
+ max: { thinkingConfig: { thinkingBudget: 32768 } }
82
+ }
83
+ },
84
+ {
85
+ id: 'glm-4.6',
86
+ name: 'GLM-4.6 Thinking',
87
+ context: 200000,
88
+ output: 128000,
89
+ inputModalities: ['text', 'image'],
90
+ outputModalities: ['text'],
91
+ reasoning: true,
92
+ toolcall: true,
93
+ family: 'glm',
94
+ variants: {
95
+ low: { thinkingConfig: { thinkingBudget: 1024 } },
96
+ medium: { thinkingConfig: { thinkingBudget: 8192 } },
97
+ max: { thinkingConfig: { thinkingBudget: 32768 } }
98
+ }
99
+ },
100
+ {
101
+ id: 'qwen3-max',
102
+ name: 'Qwen3 Max',
103
+ context: 256000,
104
+ output: 32000,
105
+ inputModalities: ['text'],
106
+ outputModalities: ['text'],
107
+ toolcall: true,
108
+ family: 'qwen3'
109
+ },
110
+ {
111
+ id: 'qwen3-max-preview',
112
+ name: 'Qwen3 Max Preview',
113
+ context: 256000,
114
+ output: 32000,
115
+ inputModalities: ['text'],
116
+ outputModalities: ['text'],
117
+ toolcall: true,
118
+ family: 'qwen3'
119
+ },
120
+ {
121
+ id: 'qwen3-coder-plus',
122
+ name: 'Qwen3 Coder Plus',
123
+ context: 1000000,
124
+ output: 64000,
125
+ inputModalities: ['text'],
126
+ outputModalities: ['text'],
127
+ toolcall: true,
128
+ family: 'qwen3-coder'
129
+ },
130
+ {
131
+ id: 'qwen3-vl-plus',
132
+ name: 'Qwen3 VL Plus',
133
+ context: 256000,
134
+ output: 32000,
135
+ inputModalities: ['text', 'image'],
136
+ outputModalities: ['text'],
137
+ family: 'qwen3-vl'
138
+ },
139
+ {
140
+ id: 'qwen3-32b',
141
+ name: 'Qwen3 32B',
142
+ context: 128000,
143
+ output: 32000,
144
+ inputModalities: ['text'],
145
+ outputModalities: ['text'],
146
+ toolcall: true,
147
+ family: 'qwen3'
148
+ },
149
+ {
150
+ id: 'qwen3-235b',
151
+ name: 'Qwen3 235B',
152
+ context: 256000,
153
+ output: 64000,
154
+ inputModalities: ['text'],
155
+ outputModalities: ['text'],
156
+ toolcall: true,
157
+ family: 'qwen3'
158
+ },
159
+ {
160
+ id: 'qwen3-235b-a22b-thinking-2507',
161
+ name: 'Qwen3 235B Thinking',
162
+ context: 256000,
163
+ output: 64000,
164
+ inputModalities: ['text'],
165
+ outputModalities: ['text'],
166
+ reasoning: true,
167
+ toolcall: true,
168
+ family: 'qwen3-thinking',
169
+ variants: {
170
+ low: { thinkingConfig: { thinkingBudget: 1024 } },
171
+ medium: { thinkingConfig: { thinkingBudget: 8192 } },
172
+ max: { thinkingConfig: { thinkingBudget: 32768 } }
173
+ }
174
+ },
175
+ {
176
+ id: 'qwen3-235b-a22b-instruct',
177
+ name: 'Qwen3 235B Instruct',
178
+ context: 256000,
179
+ output: 64000,
180
+ inputModalities: ['text'],
181
+ outputModalities: ['text'],
182
+ toolcall: true,
183
+ family: 'qwen3'
184
+ },
185
+ {
186
+ id: 'kimi-k2',
187
+ name: 'Kimi K2',
188
+ context: 128000,
189
+ output: 64000,
190
+ inputModalities: ['text'],
191
+ outputModalities: ['text'],
192
+ toolcall: true,
193
+ family: 'kimi'
194
+ },
195
+ {
196
+ id: 'kimi-k2-0905',
197
+ name: 'Kimi K2 0905',
198
+ context: 256000,
199
+ output: 64000,
200
+ inputModalities: ['text'],
201
+ outputModalities: ['text'],
202
+ toolcall: true,
203
+ family: 'kimi'
204
+ },
205
+ {
206
+ id: 'deepseek-v3',
207
+ name: 'DeepSeek V3',
208
+ context: 128000,
209
+ output: 32000,
210
+ inputModalities: ['text'],
211
+ outputModalities: ['text'],
212
+ toolcall: true,
213
+ family: 'deepseek'
214
+ },
215
+ {
216
+ id: 'deepseek-v3.2',
217
+ name: 'DeepSeek V3.2',
218
+ context: 128000,
219
+ output: 64000,
220
+ inputModalities: ['text'],
221
+ outputModalities: ['text'],
222
+ toolcall: true,
223
+ family: 'deepseek'
224
+ },
225
+ {
226
+ id: 'deepseek-r1',
227
+ name: 'DeepSeek R1',
228
+ context: 128000,
229
+ output: 32000,
230
+ inputModalities: ['text'],
231
+ outputModalities: ['text'],
232
+ reasoning: true,
233
+ toolcall: true,
234
+ family: 'deepseek-r',
235
+ variants: {
236
+ low: { thinkingConfig: { thinkingBudget: 1024 } },
237
+ medium: { thinkingConfig: { thinkingBudget: 8192 } },
238
+ max: { thinkingConfig: { thinkingBudget: 32768 } }
239
+ }
240
+ },
241
+ {
242
+ id: 'iflow-rome-30ba3b',
243
+ name: 'iFlow ROME 30B',
244
+ context: 256000,
245
+ output: 64000,
246
+ inputModalities: ['text'],
247
+ outputModalities: ['text'],
248
+ family: 'iflow-rome'
249
+ }
250
+ ];
251
+ export function registerIFlowModels(provider) {
252
+ for (const modelConfig of IFLOW_MODELS) {
253
+ const actualApiId = modelConfig.id;
254
+ if (!provider.models[modelConfig.id]) {
255
+ provider.models[modelConfig.id] = {
256
+ id: modelConfig.id,
257
+ providerID: 'iflow',
258
+ api: {
259
+ id: actualApiId,
260
+ url: IFLOW_CONSTANTS.BASE_URL,
261
+ npm: '@ai-sdk/openai-compatible'
262
+ },
263
+ name: modelConfig.name,
264
+ family: modelConfig.family || modelConfig.id.split('-')[0],
265
+ capabilities: {
266
+ temperature: modelConfig.temperature ?? true,
267
+ reasoning: modelConfig.reasoning ?? false,
268
+ attachment: modelConfig.inputModalities.includes('image'),
269
+ toolcall: modelConfig.toolcall ?? false,
270
+ input: {
271
+ text: modelConfig.inputModalities.includes('text'),
272
+ audio: modelConfig.inputModalities.includes('audio'),
273
+ image: modelConfig.inputModalities.includes('image'),
274
+ video: modelConfig.inputModalities.includes('video'),
275
+ pdf: modelConfig.inputModalities.includes('pdf')
276
+ },
277
+ output: {
278
+ text: modelConfig.outputModalities.includes('text'),
279
+ audio: modelConfig.outputModalities.includes('audio'),
280
+ image: modelConfig.outputModalities.includes('image'),
281
+ video: modelConfig.outputModalities.includes('video'),
282
+ pdf: modelConfig.outputModalities.includes('pdf')
283
+ },
284
+ interleaved: modelConfig.reasoning ?? false
285
+ },
286
+ cost: {
287
+ input: 0,
288
+ output: 0,
289
+ cache: { read: 0, write: 0 }
290
+ },
291
+ limit: {
292
+ context: modelConfig.context,
293
+ output: modelConfig.output
294
+ },
295
+ status: 'active',
296
+ options: {},
297
+ headers: {},
298
+ release_date: '2025-01-01',
299
+ variants: modelConfig.variants || {}
300
+ };
301
+ }
302
+ }
303
+ }
@@ -0,0 +1,6 @@
1
+ export interface IFlowApiKeyResult {
2
+ apiKey: string;
3
+ email: string;
4
+ authMethod: 'apikey';
5
+ }
6
+ export declare function validateApiKey(apiKey: string): Promise<IFlowApiKeyResult>;
@@ -0,0 +1,17 @@
1
+ import { IFLOW_CONSTANTS } from '../constants.js';
2
+ export async function validateApiKey(apiKey) {
3
+ const response = await fetch(`${IFLOW_CONSTANTS.BASE_URL}/models`, {
4
+ headers: {
5
+ Authorization: `Bearer ${apiKey}`,
6
+ 'User-Agent': IFLOW_CONSTANTS.USER_AGENT
7
+ }
8
+ });
9
+ if (!response.ok) {
10
+ throw new Error(`API key validation failed: ${response.status}`);
11
+ }
12
+ return {
13
+ apiKey,
14
+ email: 'api-key-user',
15
+ authMethod: 'apikey'
16
+ };
17
+ }
@@ -0,0 +1,20 @@
1
+ export interface IFlowOAuthAuthorization {
2
+ authUrl: string;
3
+ state: string;
4
+ redirectUri: string;
5
+ }
6
+ export interface IFlowOAuthTokenResult {
7
+ accessToken: string;
8
+ refreshToken: string;
9
+ expiresAt: number;
10
+ apiKey: string;
11
+ email: string;
12
+ authMethod: 'oauth';
13
+ }
14
+ export declare function authorizeIFlowOAuth(port: number): Promise<IFlowOAuthAuthorization>;
15
+ export declare function exchangeOAuthCode(code: string, redirectUri: string): Promise<IFlowOAuthTokenResult>;
16
+ export declare function refreshOAuthToken(refreshToken: string): Promise<IFlowOAuthTokenResult>;
17
+ export declare function fetchUserInfo(accessToken: string): Promise<{
18
+ apiKey: string;
19
+ email: string;
20
+ }>;