aicodeswitch 1.5.0 → 1.6.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.
- package/dist/server/proxy-server.js +54 -1
- package/dist/ui/assets/index-Bw_1Ltv0.js +361 -0
- package/dist/ui/index.html +1 -1
- package/package.json +1 -1
- package/dist/ui/assets/index-DJ5R6Vso.js +0 -360
- package/src/server/auth.ts +0 -79
- package/src/server/database.ts +0 -809
- package/src/server/main.ts +0 -514
- package/src/server/proxy-server.ts +0 -1301
- package/src/server/transformers/chunk-collector.ts +0 -202
- package/src/server/transformers/claude-openai.ts +0 -261
- package/src/server/transformers/openai-responses.ts +0 -440
- package/src/server/transformers/streaming.ts +0 -775
- package/src/server/version-check.ts +0 -108
- package/src/types/index.ts +0 -217
- package/src/ui/App.tsx +0 -342
- package/src/ui/api/client.ts +0 -179
- package/src/ui/components/JSONViewer.tsx +0 -89
- package/src/ui/constants/index.ts +0 -4
- package/src/ui/docs/vendors-recommand.md +0 -13
- package/src/ui/main.tsx +0 -10
- package/src/ui/pages/LogsPage.tsx +0 -702
- package/src/ui/pages/RoutesPage.tsx +0 -552
- package/src/ui/pages/SettingsPage.tsx +0 -206
- package/src/ui/pages/StatisticsPage.tsx +0 -620
- package/src/ui/pages/UsagePage.tsx +0 -13
- package/src/ui/pages/VendorsPage.tsx +0 -490
- package/src/ui/pages/WriteConfigPage.tsx +0 -198
- package/src/ui/styles/App.css +0 -831
- package/src/ui/styles/index.css +0 -137
package/src/ui/api/client.ts
DELETED
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
import type { Vendor, APIService, Route, Rule, RequestLog, AccessLog, ErrorLog, AppConfig, AuthStatus, LoginResponse, Statistics } from '../../types';
|
|
2
|
-
|
|
3
|
-
interface BackendAPI {
|
|
4
|
-
// 鉴权相关
|
|
5
|
-
getAuthStatus: () => Promise<AuthStatus>;
|
|
6
|
-
login: (authCode: string) => Promise<LoginResponse>;
|
|
7
|
-
|
|
8
|
-
// 版本检查
|
|
9
|
-
checkVersion: () => Promise<{ hasUpdate: boolean; currentVersion: string | null; latestVersion: string | null }>;
|
|
10
|
-
|
|
11
|
-
getVendors: () => Promise<Vendor[]>;
|
|
12
|
-
createVendor: (vendor: Omit<Vendor, 'id' | 'createdAt' | 'updatedAt'>) => Promise<Vendor>;
|
|
13
|
-
updateVendor: (id: string, vendor: Partial<Vendor>) => Promise<boolean>;
|
|
14
|
-
deleteVendor: (id: string) => Promise<boolean>;
|
|
15
|
-
|
|
16
|
-
getAPIServices: (vendorId?: string) => Promise<APIService[]>;
|
|
17
|
-
createAPIService: (service: Omit<APIService, 'id' | 'createdAt' | 'updatedAt'>) => Promise<APIService>;
|
|
18
|
-
updateAPIService: (id: string, service: Partial<APIService>) => Promise<boolean>;
|
|
19
|
-
deleteAPIService: (id: string) => Promise<boolean>;
|
|
20
|
-
|
|
21
|
-
getRoutes: () => Promise<Route[]>;
|
|
22
|
-
createRoute: (group: Omit<Route, 'id' | 'createdAt' | 'updatedAt'>) => Promise<Route>;
|
|
23
|
-
updateRoute: (id: string, group: Partial<Route>) => Promise<boolean>;
|
|
24
|
-
deleteRoute: (id: string) => Promise<boolean>;
|
|
25
|
-
activateRoute: (id: string) => Promise<boolean>;
|
|
26
|
-
deactivateRoute: (id: string) => Promise<boolean>;
|
|
27
|
-
|
|
28
|
-
getRules: (routeId?: string) => Promise<Rule[]>;
|
|
29
|
-
createRule: (route: Omit<Rule, 'id' | 'createdAt' | 'updatedAt'>) => Promise<Rule>;
|
|
30
|
-
updateRule: (id: string, route: Partial<Rule>) => Promise<boolean>;
|
|
31
|
-
deleteRule: (id: string) => Promise<boolean>;
|
|
32
|
-
|
|
33
|
-
getLogs: (limit: number, offset: number) => Promise<RequestLog[]>;
|
|
34
|
-
clearLogs: () => Promise<boolean>;
|
|
35
|
-
|
|
36
|
-
getAccessLogs: (limit: number, offset: number) => Promise<AccessLog[]>;
|
|
37
|
-
clearAccessLogs: () => Promise<boolean>;
|
|
38
|
-
|
|
39
|
-
getErrorLogs: (limit: number, offset: number) => Promise<ErrorLog[]>;
|
|
40
|
-
clearErrorLogs: () => Promise<boolean>;
|
|
41
|
-
|
|
42
|
-
getConfig: () => Promise<AppConfig>;
|
|
43
|
-
updateConfig: (config: AppConfig) => Promise<boolean>;
|
|
44
|
-
|
|
45
|
-
exportData: (password: string) => Promise<string>;
|
|
46
|
-
importData: (encryptedData: string, password: string) => Promise<boolean>;
|
|
47
|
-
|
|
48
|
-
writeClaudeConfig: () => Promise<boolean>;
|
|
49
|
-
writeCodexConfig: () => Promise<boolean>;
|
|
50
|
-
restoreClaudeConfig: () => Promise<boolean>;
|
|
51
|
-
restoreCodexConfig: () => Promise<boolean>;
|
|
52
|
-
checkClaudeBackup: () => Promise<{ exists: boolean }>;
|
|
53
|
-
checkCodexBackup: () => Promise<{ exists: boolean }>;
|
|
54
|
-
|
|
55
|
-
getStatistics: (days?: number) => Promise<Statistics>;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const buildUrl = (
|
|
59
|
-
path: string,
|
|
60
|
-
query?: Record<string, string | number | undefined>
|
|
61
|
-
): string => {
|
|
62
|
-
if (!query) {
|
|
63
|
-
return path;
|
|
64
|
-
}
|
|
65
|
-
const params = new URLSearchParams();
|
|
66
|
-
Object.entries(query).forEach(([key, value]) => {
|
|
67
|
-
if (value !== undefined && value !== null && value !== '') {
|
|
68
|
-
params.set(key, String(value));
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
const queryString = params.toString();
|
|
72
|
-
return queryString ? `${path}?${queryString}` : path;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const requestJson = async <T>(path: string, options: RequestInit = {}): Promise<T> => {
|
|
76
|
-
// 从 localStorage 读取 token
|
|
77
|
-
const token = localStorage.getItem('auth_token');
|
|
78
|
-
|
|
79
|
-
const response = await fetch(path, {
|
|
80
|
-
...options,
|
|
81
|
-
headers: {
|
|
82
|
-
'Content-Type': 'application/json',
|
|
83
|
-
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
84
|
-
...(options.headers || {}),
|
|
85
|
-
},
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
if (!response.ok) {
|
|
89
|
-
// 如果是 401,清除本地 token 并抛出特殊错误
|
|
90
|
-
if (response.status === 401) {
|
|
91
|
-
localStorage.removeItem('auth_token');
|
|
92
|
-
const message = await response.text();
|
|
93
|
-
const error = new Error(message || response.statusText) as Error & { status: number };
|
|
94
|
-
error.status = 401;
|
|
95
|
-
throw error;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const message = await response.text();
|
|
99
|
-
throw new Error(message || response.statusText);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (response.status === 204) {
|
|
103
|
-
return undefined as T;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const contentType = response.headers.get('content-type') || '';
|
|
107
|
-
if (contentType.includes('application/json')) {
|
|
108
|
-
return response.json() as Promise<T>;
|
|
109
|
-
}
|
|
110
|
-
return response.text() as Promise<T>;
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
export const api: BackendAPI = {
|
|
114
|
-
// 鉴权相关
|
|
115
|
-
getAuthStatus: () => requestJson(buildUrl('/api/auth/status')),
|
|
116
|
-
login: (authCode) => requestJson(buildUrl('/api/auth/login'), {
|
|
117
|
-
method: 'POST',
|
|
118
|
-
body: JSON.stringify({ authCode })
|
|
119
|
-
}),
|
|
120
|
-
|
|
121
|
-
// 版本检查
|
|
122
|
-
checkVersion: () => requestJson(buildUrl('/api/version/check')),
|
|
123
|
-
|
|
124
|
-
getVendors: () => requestJson(buildUrl('/api/vendors')),
|
|
125
|
-
createVendor: (vendor) => requestJson(buildUrl('/api/vendors'), { method: 'POST', body: JSON.stringify(vendor) }),
|
|
126
|
-
updateVendor: (id, vendor) => requestJson(buildUrl(`/api/vendors/${id}`), { method: 'PUT', body: JSON.stringify(vendor) }),
|
|
127
|
-
deleteVendor: (id) => requestJson(buildUrl(`/api/vendors/${id}`), { method: 'DELETE' }),
|
|
128
|
-
|
|
129
|
-
getAPIServices: (vendorId) => requestJson(buildUrl('/api/services', vendorId ? { vendorId } : undefined)),
|
|
130
|
-
createAPIService: (service) => requestJson(buildUrl('/api/services'), { method: 'POST', body: JSON.stringify(service) }),
|
|
131
|
-
updateAPIService: (id, service) => requestJson(buildUrl(`/api/services/${id}`), { method: 'PUT', body: JSON.stringify(service) }),
|
|
132
|
-
deleteAPIService: (id) => requestJson(buildUrl(`/api/services/${id}`), { method: 'DELETE' }),
|
|
133
|
-
|
|
134
|
-
getRoutes: () => requestJson(buildUrl('/api/routes')),
|
|
135
|
-
createRoute: (group) => requestJson(buildUrl('/api/routes'), { method: 'POST', body: JSON.stringify(group) }),
|
|
136
|
-
updateRoute: (id, group) => requestJson(buildUrl(`/api/routes/${id}`), { method: 'PUT', body: JSON.stringify(group) }),
|
|
137
|
-
deleteRoute: (id) => requestJson(buildUrl(`/api/routes/${id}`), { method: 'DELETE' }),
|
|
138
|
-
activateRoute: (id) => requestJson(buildUrl(`/api/routes/${id}/activate`), { method: 'POST' }),
|
|
139
|
-
deactivateRoute: (id) => requestJson(buildUrl(`/api/routes/${id}/deactivate`), { method: 'POST' }),
|
|
140
|
-
|
|
141
|
-
getRules: (routeId) => requestJson(buildUrl('/api/rules', routeId ? { routeId } : undefined)),
|
|
142
|
-
createRule: (route) => requestJson(buildUrl('/api/rules'), { method: 'POST', body: JSON.stringify(route) }),
|
|
143
|
-
updateRule: (id, route) => requestJson(buildUrl(`/api/rules/${id}`), { method: 'PUT', body: JSON.stringify(route) }),
|
|
144
|
-
deleteRule: (id) => requestJson(buildUrl(`/api/rules/${id}`), { method: 'DELETE' }),
|
|
145
|
-
|
|
146
|
-
getLogs: (limit, offset) => requestJson(buildUrl('/api/logs', { limit, offset })),
|
|
147
|
-
clearLogs: () => requestJson(buildUrl('/api/logs'), { method: 'DELETE' }),
|
|
148
|
-
|
|
149
|
-
getAccessLogs: (limit, offset) => requestJson(buildUrl('/api/access-logs', { limit, offset })),
|
|
150
|
-
clearAccessLogs: () => requestJson(buildUrl('/api/access-logs'), { method: 'DELETE' }),
|
|
151
|
-
|
|
152
|
-
getErrorLogs: (limit, offset) => requestJson(buildUrl('/api/error-logs', { limit, offset })),
|
|
153
|
-
clearErrorLogs: () => requestJson(buildUrl('/api/error-logs'), { method: 'DELETE' }),
|
|
154
|
-
|
|
155
|
-
getConfig: () => requestJson(buildUrl('/api/config')),
|
|
156
|
-
updateConfig: (config) => requestJson(buildUrl('/api/config'), { method: 'PUT', body: JSON.stringify(config) }),
|
|
157
|
-
|
|
158
|
-
exportData: async (password) => {
|
|
159
|
-
const result = await requestJson<{ data: string }>(
|
|
160
|
-
buildUrl('/api/export'),
|
|
161
|
-
{ method: 'POST', body: JSON.stringify({ password }) }
|
|
162
|
-
);
|
|
163
|
-
return result.data;
|
|
164
|
-
},
|
|
165
|
-
|
|
166
|
-
importData: (encryptedData, password) => requestJson(buildUrl('/api/import'), {
|
|
167
|
-
method: 'POST',
|
|
168
|
-
body: JSON.stringify({ encryptedData, password }),
|
|
169
|
-
}),
|
|
170
|
-
|
|
171
|
-
writeClaudeConfig: () => requestJson(buildUrl('/api/write-config/claude'), { method: 'POST' }),
|
|
172
|
-
writeCodexConfig: () => requestJson(buildUrl('/api/write-config/codex'), { method: 'POST' }),
|
|
173
|
-
restoreClaudeConfig: () => requestJson(buildUrl('/api/restore-config/claude'), { method: 'POST' }),
|
|
174
|
-
restoreCodexConfig: () => requestJson(buildUrl('/api/restore-config/codex'), { method: 'POST' }),
|
|
175
|
-
checkClaudeBackup: () => requestJson(buildUrl('/api/check-backup/claude')),
|
|
176
|
-
checkCodexBackup: () => requestJson(buildUrl('/api/check-backup/codex')),
|
|
177
|
-
|
|
178
|
-
getStatistics: (days) => requestJson(buildUrl('/api/statistics', days ? { days } : undefined)),
|
|
179
|
-
};
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
2
|
-
|
|
3
|
-
interface JSONViewerProps {
|
|
4
|
-
data: string | Record<string, any> | any[];
|
|
5
|
-
title?: string;
|
|
6
|
-
collapsed?: boolean;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const JSONViewer: React.FC<JSONViewerProps> = ({ data, title, collapsed = false }) => {
|
|
10
|
-
const [isExpanded, setIsExpanded] = useState(!collapsed);
|
|
11
|
-
const [copySuccess, setCopySuccess] = useState(false);
|
|
12
|
-
|
|
13
|
-
// 格式化 JSON 数据
|
|
14
|
-
const formatJSON = (input: string | Record<string, any> | any[]): string => {
|
|
15
|
-
try {
|
|
16
|
-
let jsonData: any;
|
|
17
|
-
if (typeof input === 'string') {
|
|
18
|
-
jsonData = JSON.parse(input);
|
|
19
|
-
} else {
|
|
20
|
-
jsonData = input;
|
|
21
|
-
}
|
|
22
|
-
return JSON.stringify(jsonData, null, 2);
|
|
23
|
-
} catch (error) {
|
|
24
|
-
return typeof input === 'string' ? input : String(input);
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// 复制到剪贴板
|
|
29
|
-
const handleCopy = () => {
|
|
30
|
-
const formatted = formatJSON(data);
|
|
31
|
-
navigator.clipboard.writeText(formatted)
|
|
32
|
-
.then(() => {
|
|
33
|
-
setCopySuccess(true);
|
|
34
|
-
setTimeout(() => setCopySuccess(false), 2000);
|
|
35
|
-
})
|
|
36
|
-
.catch((error) => {
|
|
37
|
-
console.error('Failed to copy JSON:', error);
|
|
38
|
-
});
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const formattedJSON = formatJSON(data);
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<div className="json-viewer">
|
|
45
|
-
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '8px' }}>
|
|
46
|
-
{title && (
|
|
47
|
-
<h4 style={{ margin: 0, fontSize: '14px', color: 'var(--text-primary)' }}>
|
|
48
|
-
{title}
|
|
49
|
-
</h4>
|
|
50
|
-
)}
|
|
51
|
-
<div style={{ display: 'flex', gap: '8px' }}>
|
|
52
|
-
<button
|
|
53
|
-
onClick={() => setIsExpanded(!isExpanded)}
|
|
54
|
-
className="btn btn-sm btn-secondary"
|
|
55
|
-
style={{ fontSize: '12px', padding: '2px 8px' }}
|
|
56
|
-
>
|
|
57
|
-
{isExpanded ? '折叠' : '展开'}
|
|
58
|
-
</button>
|
|
59
|
-
<button
|
|
60
|
-
onClick={handleCopy}
|
|
61
|
-
className="btn btn-sm btn-primary"
|
|
62
|
-
style={{ fontSize: '12px', padding: '2px 8px' }}
|
|
63
|
-
>
|
|
64
|
-
{copySuccess ? '已复制' : '复制'}
|
|
65
|
-
</button>
|
|
66
|
-
</div>
|
|
67
|
-
</div>
|
|
68
|
-
{isExpanded && (
|
|
69
|
-
<pre style={{
|
|
70
|
-
background: 'var(--bg-code)',
|
|
71
|
-
border: '1px solid var(--border-primary)',
|
|
72
|
-
borderRadius: '8px',
|
|
73
|
-
padding: '12px',
|
|
74
|
-
overflowX: 'auto',
|
|
75
|
-
fontSize: '12px',
|
|
76
|
-
lineHeight: '1.4',
|
|
77
|
-
color: 'var(--text-primary)',
|
|
78
|
-
maxHeight: '400px',
|
|
79
|
-
overflowY: 'auto',
|
|
80
|
-
margin: 0
|
|
81
|
-
}}>
|
|
82
|
-
<code>{formattedJSON}</code>
|
|
83
|
-
</pre>
|
|
84
|
-
)}
|
|
85
|
-
</div>
|
|
86
|
-
);
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
export default JSONViewer;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
#### 🚀 智谱 GLM Coding Plan
|
|
2
|
-
|
|
3
|
-
> 价格便宜,国内速度快,支持多工具(Claude Code等 20+ 大编程工具),而且其中的GLM-4.7是目前国内最强编程模型。适合对模型有一定要求,同时又无法获取国外模型的朋友入手。
|
|
4
|
-
>
|
|
5
|
-
> 链接:[https://www.bigmodel.cn/glm-coding](https://www.bigmodel.cn/glm-coding?ic=5AH7ATEZSC)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
#### 🗿 AI Code With
|
|
9
|
-
|
|
10
|
-
> 支持Claude、GPT、Gemni三大系列模型,可接入Claude Code、Codex,经实测,非常稳定,速度快,但是没有包月套餐,只能使用tokens流量,适合追求稳定的朋友。
|
|
11
|
-
>
|
|
12
|
-
> 链接:[https://aicodewith.com/](https://aicodewith.com/login?tab=register&invitation=QCA74W)
|
|
13
|
-
|
package/src/ui/main.tsx
DELETED