mirror of
https://github.com/di-sukharev/opencommit.git
synced 2026-04-20 03:02:51 -04:00
fix: stabilize e2e flow in clean CI env
Signed-off-by: majiayu000 <majiayu000@users.noreply.github.com>
This commit is contained in:
@@ -3,15 +3,18 @@ import { MODEL_LIST, OCO_AI_PROVIDER_ENUM } from '../commands/config';
|
||||
|
||||
// Provider billing/help URLs for common errors
|
||||
export const PROVIDER_BILLING_URLS: Record<string, string | null> = {
|
||||
[OCO_AI_PROVIDER_ENUM.ANTHROPIC]: 'https://console.anthropic.com/settings/billing',
|
||||
[OCO_AI_PROVIDER_ENUM.OPENAI]: 'https://platform.openai.com/settings/organization/billing',
|
||||
[OCO_AI_PROVIDER_ENUM.ANTHROPIC]:
|
||||
'https://console.anthropic.com/settings/billing',
|
||||
[OCO_AI_PROVIDER_ENUM.OPENAI]:
|
||||
'https://platform.openai.com/settings/organization/billing',
|
||||
[OCO_AI_PROVIDER_ENUM.GEMINI]: 'https://aistudio.google.com/app/plan',
|
||||
[OCO_AI_PROVIDER_ENUM.GROQ]: 'https://console.groq.com/settings/billing',
|
||||
[OCO_AI_PROVIDER_ENUM.MISTRAL]: 'https://console.mistral.ai/billing/',
|
||||
[OCO_AI_PROVIDER_ENUM.DEEPSEEK]: 'https://platform.deepseek.com/usage',
|
||||
[OCO_AI_PROVIDER_ENUM.OPENROUTER]: 'https://openrouter.ai/credits',
|
||||
[OCO_AI_PROVIDER_ENUM.AIMLAPI]: 'https://aimlapi.com/app/billing',
|
||||
[OCO_AI_PROVIDER_ENUM.AZURE]: 'https://portal.azure.com/#view/Microsoft_Azure_CostManagement',
|
||||
[OCO_AI_PROVIDER_ENUM.AZURE]:
|
||||
'https://portal.azure.com/#view/Microsoft_Azure_CostManagement',
|
||||
[OCO_AI_PROVIDER_ENUM.OLLAMA]: null,
|
||||
[OCO_AI_PROVIDER_ENUM.MLX]: null,
|
||||
[OCO_AI_PROVIDER_ENUM.FLOWISE]: null,
|
||||
@@ -23,7 +26,9 @@ export class InsufficientCreditsError extends Error {
|
||||
public readonly provider: string;
|
||||
|
||||
constructor(provider: string, message?: string) {
|
||||
super(message || `Insufficient credits or quota for provider '${provider}'`);
|
||||
super(
|
||||
message || `Insufficient credits or quota for provider '${provider}'`
|
||||
);
|
||||
this.name = 'InsufficientCreditsError';
|
||||
this.provider = provider;
|
||||
}
|
||||
@@ -345,7 +350,10 @@ export interface FormattedError {
|
||||
}
|
||||
|
||||
// Format an error into a user-friendly structure
|
||||
export function formatUserFriendlyError(error: unknown, provider: string): FormattedError {
|
||||
export function formatUserFriendlyError(
|
||||
error: unknown,
|
||||
provider: string
|
||||
): FormattedError {
|
||||
const billingUrl = PROVIDER_BILLING_URLS[provider] || null;
|
||||
|
||||
// Handle our custom error types first
|
||||
@@ -460,7 +468,9 @@ export function printFormattedError(formatted: FormattedError): string {
|
||||
output += ` ${formatted.message}\n`;
|
||||
|
||||
if (formatted.helpUrl) {
|
||||
output += `\n ${chalk.cyan('Help:')} ${chalk.underline(formatted.helpUrl)}\n`;
|
||||
output += `\n ${chalk.cyan('Help:')} ${chalk.underline(
|
||||
formatted.helpUrl
|
||||
)}\n`;
|
||||
}
|
||||
|
||||
if (formatted.suggestion) {
|
||||
|
||||
@@ -125,9 +125,7 @@ export async function fetchMistralModels(apiKey: string): Promise<string[]> {
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const models = data.data
|
||||
?.map((m: { id: string }) => m.id)
|
||||
.sort();
|
||||
const models = data.data?.map((m: { id: string }) => m.id).sort();
|
||||
|
||||
return models && models.length > 0 ? models : MODEL_LIST.mistral;
|
||||
} catch {
|
||||
@@ -148,9 +146,7 @@ export async function fetchGroqModels(apiKey: string): Promise<string[]> {
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const models = data.data
|
||||
?.map((m: { id: string }) => m.id)
|
||||
.sort();
|
||||
const models = data.data?.map((m: { id: string }) => m.id).sort();
|
||||
|
||||
return models && models.length > 0 ? models : MODEL_LIST.groq;
|
||||
} catch {
|
||||
@@ -173,8 +169,9 @@ export async function fetchOpenRouterModels(apiKey: string): Promise<string[]> {
|
||||
const data = await response.json();
|
||||
// Filter to text-capable models only (exclude image/audio models)
|
||||
const models = data.data
|
||||
?.filter((m: { id: string; context_length?: number }) =>
|
||||
m.context_length && m.context_length > 0
|
||||
?.filter(
|
||||
(m: { id: string; context_length?: number }) =>
|
||||
m.context_length && m.context_length > 0
|
||||
)
|
||||
.map((m: { id: string }) => m.id)
|
||||
.sort();
|
||||
@@ -198,9 +195,7 @@ export async function fetchDeepSeekModels(apiKey: string): Promise<string[]> {
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const models = data.data
|
||||
?.map((m: { id: string }) => m.id)
|
||||
.sort();
|
||||
const models = data.data?.map((m: { id: string }) => m.id).sort();
|
||||
|
||||
return models && models.length > 0 ? models : MODEL_LIST.deepseek;
|
||||
} catch {
|
||||
@@ -312,7 +307,10 @@ export function clearModelCache(): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function getCacheInfo(): { timestamp: number | null; providers: string[] } {
|
||||
export function getCacheInfo(): {
|
||||
timestamp: number | null;
|
||||
providers: string[];
|
||||
} {
|
||||
const cache = readCache();
|
||||
if (!cache) {
|
||||
return { timestamp: null, providers: [] };
|
||||
|
||||
Reference in New Issue
Block a user