Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@hung319/opencode-iflow-cli

Package Overview
Dependencies
Maintainers
1
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@hung319/opencode-iflow-cli - npm Package Compare versions

Comparing version
4.1.0
to
5.0.0
+39
dist/iflow/models.d.ts
/**
* Auto-update models from iFlow API
* Fetches available models from https://apis.iflow.cn/v1/models
*/
export interface IFlowModel {
id: string;
name: string;
context_window: number;
max_tokens: number;
modalities: {
input: string[];
output: string[];
};
supports_thinking?: boolean;
variants?: Record<string, any>;
}
export interface IFlowModelsResponse {
data: IFlowModel[];
last_updated: string;
}
/**
* Fetch models from iFlow API
* @param apiKey - API key or OAuth token
* @param authType - 'oauth' | 'apikey'
*/
export declare function fetchModelsFromAPI(apiKey: string, authType?: 'oauth' | 'apikey'): Promise<IFlowModel[] | null>;
/**
* Fetch models from web scraping (fallback)
* Note: This is a fallback method if API fails
*/
export declare function fetchModelsFromWeb(): Promise<IFlowModel[] | null>;
/**
* Transform iFlow models to OpenCode format
*/
export declare function transformModelsToOpenCode(models: IFlowModel[]): Record<string, any>;
/**
* Get cached models or fetch new ones
*/
export declare function getModels(apiKey: string | undefined, authType: 'oauth' | 'apikey' | undefined): Promise<Record<string, any>>;
/**
* Auto-update models from iFlow API
* Fetches available models from https://apis.iflow.cn/v1/models
*/
import * as logger from '../plugin/logger.js';
/**
* Fetch models from iFlow API
* @param apiKey - API key or OAuth token
* @param authType - 'oauth' | 'apikey'
*/
export async function fetchModelsFromAPI(apiKey, authType = 'apikey') {
try {
const headers = {
'Content-Type': 'application/json',
};
if (authType === 'oauth') {
headers['Authorization'] = `Bearer ${apiKey}`;
}
else {
headers['Authorization'] = `Bearer ${apiKey}`;
}
const response = await fetch('https://apis.iflow.cn/v1/models', {
method: 'GET',
headers,
});
if (!response.ok) {
logger.warn(`Failed to fetch models: ${response.status} ${response.statusText}`);
return null;
}
const data = await response.json();
return data.data || null;
}
catch (error) {
logger.warn(`Error fetching models from API: ${error.message}`);
return null;
}
}
/**
* Fetch models from web scraping (fallback)
* Note: This is a fallback method if API fails
*/
export async function fetchModelsFromWeb() {
try {
const response = await fetch('https://platform.iflow.cn/en/models', {
method: 'GET',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
},
});
if (!response.ok) {
return null;
}
const html = await response.text();
// Parse models from HTML (basic implementation)
// In production, this would use a proper HTML parser
// Try to extract model data from JSON-LD or script tags
const scriptMatch = html.match(/window\.__MODELS__\s*=\s*(\[.*?\]);/s);
if (scriptMatch && scriptMatch[1]) {
try {
const parsed = JSON.parse(scriptMatch[1]);
return parsed.map((m) => ({
id: m.id,
name: m.name,
context_window: m.context_window || 128000,
max_tokens: m.max_tokens || 32000,
modalities: m.modalities || { input: ['text'], output: ['text'] },
supports_thinking: m.supports_thinking || false,
}));
}
catch {
// Fall through to default
}
}
return null;
}
catch (error) {
logger.warn(`Error fetching models from web: ${error.message}`);
return null;
}
}
/**
* Transform iFlow models to OpenCode format
*/
export function transformModelsToOpenCode(models) {
const result = {};
for (const model of models) {
result[model.id] = {
name: model.name,
limit: {
context: model.context_window,
output: model.max_tokens,
},
modalities: model.modalities,
...(model.variants && { variants: model.variants }),
};
}
return result;
}
/**
* Get cached models or fetch new ones
*/
export async function getModels(apiKey, authType) {
// Try to fetch from API if credentials available
if (apiKey && authType) {
const apiModels = await fetchModelsFromAPI(apiKey, authType);
if (apiModels) {
return transformModelsToOpenCode(apiModels);
}
}
// Fallback to web scraping
const webModels = await fetchModelsFromWeb();
if (webModels) {
return transformModelsToOpenCode(webModels);
}
// Final fallback: use default models
return {};
}
+1
-1

@@ -1,2 +0,2 @@

export declare const IFLOW_PROVIDER_ID = "iflow-oauth";
export declare const IFLOW_PROVIDER_ID = "iflow";
export declare const createIFlowPlugin: (id: string) => ({ client, directory }: any) => Promise<{

@@ -3,0 +3,0 @@ config: (config: any) => Promise<void>;

@@ -8,2 +8,3 @@ import { loadConfig } from './plugin/config';

import { validateApiKey } from './iflow/apikey';
import { getModels } from './iflow/models';
import { startOAuthServer } from './plugin/server';

@@ -13,3 +14,3 @@ import { promptAddAnotherAccount, promptLoginMode, promptApiKey, promptEmail, promptOAuthCallback } from './plugin/cli';

import * as logger from './plugin/logger';
export const IFLOW_PROVIDER_ID = 'iflow-oauth';
export const IFLOW_PROVIDER_ID = 'iflow';
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

@@ -161,3 +162,32 @@ const isNetworkError = (e) => e instanceof Error && /econnreset|etimedout|enotfound|network|fetch failed/i.test(e.message);

config.provider[id] = config.provider[id] || {};
config.provider[id].models = { ...DEFAULT_MODELS, ...(config.provider[id].models || {}) };
// Try to fetch models from API
let fetchedModels = {};
try {
const am = await AccountManager.loadFromDisk(config.account_selection_strategy);
const accounts = am.getAccounts();
if (accounts.length > 0) {
// Use first available account to fetch models
const firstAccount = accounts[0];
if (firstAccount) {
const authType = firstAccount.authMethod === 'oauth' ? 'oauth' : 'apikey';
const token = firstAccount.authMethod === 'oauth'
? firstAccount.accessToken
: firstAccount.apiKey;
if (token) {
logger.log('Fetching models from iFlow API...');
fetchedModels = await getModels(token, authType);
logger.log(`Fetched ${Object.keys(fetchedModels).length} models from API`);
}
}
}
}
catch (error) {
logger.warn(`Failed to fetch models from API: ${error.message}`);
}
// Merge: fetched models > default models > existing config
config.provider[id].models = {
...DEFAULT_MODELS,
...fetchedModels,
...(config.provider[id].models || {})
};
},

@@ -164,0 +194,0 @@ auth: {

{
"name": "@hung319/opencode-iflow-cli",
"version": "4.1.0",
"version": "5.0.0",
"description": "OpenCode plugin for iFlow providing access to Qwen, DeepSeek, Kimi, GLM, and iFlow ROME models with auto-config and headless OAuth support",

@@ -5,0 +5,0 @@ "type": "module",

@@ -11,2 +11,3 @@ # OpenCode iFlow CLI Plugin

- **Auto-update models**: Automatically fetches latest models from iFlow API every time OpenCode runs
- **Auto-configuration**: Models are automatically configured, no manual setup needed.

@@ -34,3 +35,3 @@ - **Dual authentication**: OAuth 2.0 (PKCE) and API Key support.

Then select **"iflow-oauth"** from the provider list when logging in (this is the enhanced iFlow with OAuth support).
Then select **"iflow"** from the provider list when logging in.

@@ -37,0 +38,0 @@ That's it! Models are automatically configured. No manual provider configuration needed.