Files
CC-Switch/src/lib/api/usage.ts
T
杨永安 07d022ba9f feat(usage): improve custom template system with variable hints and validation fixes (#628)
* feat(usage): improve custom template with variables display and explicit type detection

Combine two feature improvements:
1. Display supported variables ({{baseUrl}}, {{apiKey}}) with actual values in custom template mode
2. Add explicit templateType field for accurate template mode detection

## Changes

### Frontend
- Display template variables with actual values extracted from provider settings
- Add templateType field to UsageScript for explicit mode detection
- Support template mode persistence across sessions

### Backend
- Add template_type field to UsageScript struct
- Improve validation logic based on explicit template type
- Maintain backward compatibility with type inference

### I18n
- Add "Supported Variables" section translation (zh/en/ja)

### Benefits
- More accurate template mode detection (no more guessing)
- Better user experience with variable hints
- Clearer validation rules per template type

* fix(usage): resolve custom template cache and validation issues

Combine three bug fixes to make custom template mode work correctly:

1. **Update cache after test**: Testing usage script successfully now updates the main list cache immediately
2. **Fix same-origin check**: Custom template mode can now access different domains (SSRF protection still active)
3. **Fix field naming**: Unified to use autoQueryInterval consistently between frontend and backend

## Problems Solved

- Main provider list showing "Query failed" after successful test
- Custom templates blocked by overly strict same-origin validation
- Auto-query intervals not saved correctly due to inconsistent naming

## Changes

### Frontend (UsageScriptModal)
- Import useQueryClient and update cache after successful test
- Invalidate usage cache when saving script configuration
- Use standardized autoQueryInterval field name

### Backend (usage_script.rs)
- Allow custom template mode to bypass same-origin checks
- Maintain SSRF protection for all modes

### Hooks (useProviderActions)
- Invalidate usage query cache when saving script

## Impact

Users can now use custom templates freely while security validations remain intact for general templates.

* fix(usage): correct provider credential field names

- Claude: support both ANTHROPIC_API_KEY and ANTHROPIC_AUTH_TOKEN
- Gemini: use GEMINI_API_KEY instead of GOOGLE_GEMINI_API_KEY
- Codex: use OPENAI_API_KEY and parse base_url from TOML config string

Addresses review feedback from PR #628

* style: format code

---------

Co-authored-by: Jason <farion1231@gmail.com>
2026-01-14 15:42:05 +08:00

118 lines
2.7 KiB
TypeScript

import { invoke } from "@tauri-apps/api/core";
import type {
UsageSummary,
DailyStats,
ProviderStats,
ModelStats,
RequestLog,
LogFilters,
ModelPricing,
ProviderLimitStatus,
PaginatedLogs,
} from "@/types/usage";
import type { UsageResult } from "@/types";
import type { AppId } from "./types";
export const usageApi = {
// Provider usage script methods
query: async (providerId: string, appId: AppId): Promise<UsageResult> => {
return invoke("queryProviderUsage", { providerId, app: appId });
},
testScript: async (
providerId: string,
appId: AppId,
scriptCode: string,
timeout?: number,
apiKey?: string,
baseUrl?: string,
accessToken?: string,
userId?: string,
templateType?: "custom" | "general" | "newapi",
): Promise<UsageResult> => {
return invoke("testUsageScript", {
providerId,
app: appId,
scriptCode,
timeout,
apiKey,
baseUrl,
accessToken,
userId,
templateType,
});
},
// Proxy usage statistics methods
getUsageSummary: async (
startDate?: number,
endDate?: number,
): Promise<UsageSummary> => {
return invoke("get_usage_summary", { startDate, endDate });
},
getUsageTrends: async (
startDate?: number,
endDate?: number,
): Promise<DailyStats[]> => {
return invoke("get_usage_trends", { startDate, endDate });
},
getProviderStats: async (): Promise<ProviderStats[]> => {
return invoke("get_provider_stats");
},
getModelStats: async (): Promise<ModelStats[]> => {
return invoke("get_model_stats");
},
getRequestLogs: async (
filters: LogFilters,
page: number = 0,
pageSize: number = 20,
): Promise<PaginatedLogs> => {
return invoke("get_request_logs", {
filters,
page,
pageSize,
});
},
getRequestDetail: async (requestId: string): Promise<RequestLog | null> => {
return invoke("get_request_detail", { requestId });
},
getModelPricing: async (): Promise<ModelPricing[]> => {
return invoke("get_model_pricing");
},
updateModelPricing: async (
modelId: string,
displayName: string,
inputCost: string,
outputCost: string,
cacheReadCost: string,
cacheCreationCost: string,
): Promise<void> => {
return invoke("update_model_pricing", {
modelId,
displayName,
inputCost,
outputCost,
cacheReadCost,
cacheCreationCost,
});
},
deleteModelPricing: async (modelId: string): Promise<void> => {
return invoke("delete_model_pricing", { modelId });
},
checkProviderLimits: async (
providerId: string,
appType: string,
): Promise<ProviderLimitStatus> => {
return invoke("check_provider_limits", { providerId, appType });
},
};