@spacex110/core 0.1.11
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/index.d.ts +620 -0
- package/dist/index.js +6401 -0
- package/dist/index.js.map +1 -0
- package/dist/index.umd.js +16 -0
- package/dist/index.umd.js.map +1 -0
- package/package.json +41 -0
- package/src/api.ts +158 -0
- package/src/channel-manager.ts +790 -0
- package/src/config.ts +104 -0
- package/src/i18n.ts +66 -0
- package/src/index.ts +97 -0
- package/src/models.ts +202 -0
- package/src/providers.ts +249 -0
- package/src/storage.ts +135 -0
- package/src/strategies.ts +469 -0
- package/src/styles.css +246 -0
- package/src/types.ts +163 -0
package/src/styles.css
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
@layer components {
|
|
6
|
+
|
|
7
|
+
/* Scoped Preflight / Reset for apmsu-root */
|
|
8
|
+
.apmsu-root {
|
|
9
|
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
10
|
+
line-height: 1.5;
|
|
11
|
+
-webkit-text-size-adjust: 100%;
|
|
12
|
+
-moz-tab-size: 4;
|
|
13
|
+
tab-size: 4;
|
|
14
|
+
@apply mx-auto box-border;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* 按钮 */
|
|
18
|
+
.apmsu-btn {
|
|
19
|
+
@apply inline-flex items-center justify-center rounded-md text-xs font-medium transition-all duration-200 h-10 px-4 py-2 shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.apmsu-btn-primary {
|
|
23
|
+
@apply bg-zinc-900 text-zinc-50 hover:bg-zinc-900/90 dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-50/90;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.apmsu-btn-success {
|
|
27
|
+
@apply bg-green-600 text-white hover:bg-green-700;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.apmsu-btn-ghost {
|
|
31
|
+
@apply bg-transparent hover:bg-gray-100 dark:hover:bg-zinc-800 text-gray-700 dark:text-gray-300;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* 输入框 */
|
|
35
|
+
.apmsu-input {
|
|
36
|
+
@apply flex h-11 w-full rounded-lg border bg-gray-100/30 dark:bg-zinc-800/50 px-4 py-2.5 text-sm shadow-sm placeholder:text-gray-400 dark:placeholder:text-zinc-500 focus:outline-none transition-colors;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.apmsu-input-default {
|
|
40
|
+
@apply border-gray-200 dark:border-zinc-700 focus:border-zinc-500 dark:focus:border-zinc-500 hover:border-gray-300 dark:hover:border-zinc-600;
|
|
41
|
+
border-width: 1px;
|
|
42
|
+
/* Ensure border width as preflight is disabled */
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.apmsu-input-error {
|
|
46
|
+
@apply border-red-500 dark:border-red-500/50 focus-visible:ring-red-500 dark:bg-red-500/5;
|
|
47
|
+
border-width: 1px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.apmsu-input-success {
|
|
51
|
+
@apply border-green-500 dark:border-green-500/50 focus-visible:ring-green-500 dark:bg-green-500/5;
|
|
52
|
+
border-width: 1px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* 下拉框 */
|
|
56
|
+
.apmsu-select-trigger {
|
|
57
|
+
@apply flex h-11 w-full min-w-0 items-center justify-between whitespace-nowrap rounded-lg border border-gray-200 dark:border-zinc-700 bg-gray-100/20 dark:bg-zinc-800/50 px-4 py-2.5 text-sm shadow-sm focus:outline-none focus:border-zinc-500 dark:focus:border-zinc-500 hover:border-gray-300 dark:hover:border-zinc-600 transition-colors;
|
|
58
|
+
border-width: 1px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.apmsu-dropdown {
|
|
62
|
+
@apply absolute z-50 mt-1 w-full overflow-hidden rounded-md border border-gray-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 shadow-xl;
|
|
63
|
+
border-width: 1px;
|
|
64
|
+
/* Hack to fix rendering glitch where dropdown content is white/hidden until scroll */
|
|
65
|
+
transform: translateZ(0);
|
|
66
|
+
|
|
67
|
+
/* 动画初始状态 */
|
|
68
|
+
max-height: 0;
|
|
69
|
+
opacity: 0;
|
|
70
|
+
transform-origin: top;
|
|
71
|
+
transform: translateY(-8px) scale(0.98);
|
|
72
|
+
pointer-events: none;
|
|
73
|
+
visibility: hidden;
|
|
74
|
+
|
|
75
|
+
/* 过渡效果 */
|
|
76
|
+
transition:
|
|
77
|
+
max-height 0.4s cubic-bezier(0.2, 0.8, 0.2, 1),
|
|
78
|
+
opacity 0.3s cubic-bezier(0.2, 0.8, 0.2, 1),
|
|
79
|
+
transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1),
|
|
80
|
+
visibility 0s linear 0.4s;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.apmsu-dropdown-open {
|
|
84
|
+
max-height: 480px;
|
|
85
|
+
/* 足够大的高度以容纳内容 */
|
|
86
|
+
opacity: 1;
|
|
87
|
+
transform: translateY(0) scale(1);
|
|
88
|
+
pointer-events: auto;
|
|
89
|
+
visibility: visible;
|
|
90
|
+
transition-delay: 0s;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.apmsu-dropdown-item {
|
|
94
|
+
@apply w-full flex items-center gap-2 px-3 py-2 text-sm hover:bg-gray-100 dark:hover:bg-zinc-800 transition-all cursor-pointer active:scale-[0.98];
|
|
95
|
+
background: transparent;
|
|
96
|
+
border: none;
|
|
97
|
+
text-align: left;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.apmsu-dropdown-item-active {
|
|
101
|
+
@apply bg-zinc-100 dark:bg-zinc-800;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* 标签 */
|
|
105
|
+
.apmsu-label {
|
|
106
|
+
@apply text-xs font-medium leading-none block mb-2 uppercase tracking-wider text-gray-500 dark:text-zinc-500;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* 文本 */
|
|
110
|
+
.apmsu-error-text {
|
|
111
|
+
@apply text-xs text-red-500 dark:text-red-400;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.apmsu-hint-text {
|
|
115
|
+
@apply text-xs text-gray-400 dark:text-zinc-500;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.apmsu-success-text {
|
|
119
|
+
@apply text-xs text-green-600 dark:text-green-400;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* 卡片 */
|
|
123
|
+
.apmsu-card {
|
|
124
|
+
@apply bg-white dark:bg-zinc-900 rounded-xl border border-gray-200 dark:border-zinc-800 shadow-sm p-6 space-y-5;
|
|
125
|
+
border-width: 1px;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* 图标 */
|
|
129
|
+
.apmsu-icon-spin {
|
|
130
|
+
@apply w-4 h-4 animate-spin text-gray-400;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.apmsu-icon-success {
|
|
134
|
+
@apply w-4 h-4 text-green-500;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.apmsu-icon-error {
|
|
138
|
+
@apply w-4 h-4 text-red-500;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* Provider 图标 - dark mode 反转 */
|
|
142
|
+
.apmsu-provider-icon {
|
|
143
|
+
@apply w-4 h-4 flex-shrink-0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* 下拉箭头 */
|
|
147
|
+
.apmsu-chevron {
|
|
148
|
+
@apply w-4 h-4 opacity-50 flex-shrink-0 transition-transform duration-200;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* Placeholder 文本 */
|
|
152
|
+
.apmsu-placeholder {
|
|
153
|
+
@apply text-gray-400 dark:text-zinc-500;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* 表单字段容器 */
|
|
157
|
+
.apmsu-field {
|
|
158
|
+
@apply space-y-2;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/* 分割线 */
|
|
162
|
+
.apmsu-divider {
|
|
163
|
+
@apply border-b border-gray-100 dark:border-zinc-800;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* Dark mode 下 provider 图标反转颜色 */
|
|
168
|
+
.dark .apmsu-provider-icon {
|
|
169
|
+
filter: invert(1) hue-rotate(180deg);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/* 自定义滚动条 */
|
|
173
|
+
.apmsu-root ::-webkit-scrollbar {
|
|
174
|
+
width: 8px;
|
|
175
|
+
height: 8px;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.apmsu-root ::-webkit-scrollbar-track {
|
|
179
|
+
background: transparent;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.apmsu-root ::-webkit-scrollbar-thumb {
|
|
183
|
+
background: rgba(156, 163, 175, 0.5);
|
|
184
|
+
border-radius: 4px;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.apmsu-root ::-webkit-scrollbar-thumb:hover {
|
|
188
|
+
background: rgba(156, 163, 175, 0.7);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.apmsu-root.dark ::-webkit-scrollbar-thumb {
|
|
192
|
+
background: rgba(82, 82, 91, 0.6);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.apmsu-root.dark ::-webkit-scrollbar-thumb:hover {
|
|
196
|
+
background: rgba(82, 82, 91, 0.8);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* 下拉框滚动条 */
|
|
200
|
+
.apmsu-dropdown::-webkit-scrollbar,
|
|
201
|
+
.apmsu-dropdown *::-webkit-scrollbar {
|
|
202
|
+
width: 6px;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.apmsu-dropdown::-webkit-scrollbar-thumb,
|
|
206
|
+
.apmsu-dropdown *::-webkit-scrollbar-thumb {
|
|
207
|
+
background: rgba(156, 163, 175, 0.4);
|
|
208
|
+
border-radius: 3px;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.apmsu-dropdown::-webkit-scrollbar-track,
|
|
212
|
+
.apmsu-dropdown *::-webkit-scrollbar-track {
|
|
213
|
+
background: transparent;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.dark .apmsu-dropdown::-webkit-scrollbar-thumb,
|
|
217
|
+
.dark .apmsu-dropdown *::-webkit-scrollbar-thumb {
|
|
218
|
+
background: rgba(82, 82, 91, 0.5);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
@keyframes apmsu-fade-in {
|
|
222
|
+
from {
|
|
223
|
+
opacity: 0;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
to {
|
|
227
|
+
opacity: 1;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.apmsu-fade-in {
|
|
232
|
+
animation: apmsu-fade-in 0.2s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* Vue Transition Classes */
|
|
236
|
+
.apmsu-fade-enter-active {
|
|
237
|
+
transition: opacity 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.apmsu-fade-enter-from {
|
|
241
|
+
opacity: 0;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.apmsu-fade-leave-active {
|
|
245
|
+
display: none;
|
|
246
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Provider Selector - Core Types
|
|
3
|
+
* Framework-agnostic type definitions
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// ============ Provider Types ============
|
|
7
|
+
|
|
8
|
+
// export type AuthType = 'bearer' | 'x-api-key' | 'query-param' | 'none'; // REMOVED
|
|
9
|
+
export type ApiFormat = 'openai' | 'anthropic' | 'gemini' | 'cohere';
|
|
10
|
+
|
|
11
|
+
// ============ Model Fetcher Types ============
|
|
12
|
+
|
|
13
|
+
export type FetcherActionType = 'fetchModels' | 'checkConnection';
|
|
14
|
+
|
|
15
|
+
export interface FetcherParams {
|
|
16
|
+
type: FetcherActionType;
|
|
17
|
+
providerId: string;
|
|
18
|
+
baseUrl: string;
|
|
19
|
+
apiKey?: string;
|
|
20
|
+
modelId?: string; // only for checkConnection
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Custom fetcher for retrieving models and checking connection.
|
|
25
|
+
* If provided, this will bypass internal fetch logic.
|
|
26
|
+
*
|
|
27
|
+
* - type='fetchModels': returns Promise<Model[]>
|
|
28
|
+
* - type='checkConnection': returns Promise<{ success: boolean; latency?: number; message?: string }>
|
|
29
|
+
*/
|
|
30
|
+
export type ModelFetcher = (params: FetcherParams) => Promise<any>;
|
|
31
|
+
|
|
32
|
+
export interface Provider {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
baseUrl: string;
|
|
36
|
+
needsApiKey: boolean;
|
|
37
|
+
apiFormat: ApiFormat;
|
|
38
|
+
supportsModelsApi: boolean;
|
|
39
|
+
icon?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ...
|
|
43
|
+
|
|
44
|
+
/** 自定义 Provider 定义 */
|
|
45
|
+
export interface CustomProviderDefinition {
|
|
46
|
+
name: string;
|
|
47
|
+
baseUrl: string;
|
|
48
|
+
needsApiKey: boolean;
|
|
49
|
+
apiFormat: ApiFormat;
|
|
50
|
+
supportsModelsApi?: boolean;
|
|
51
|
+
icon?: string;
|
|
52
|
+
/** 静态模型列表(当不支持 /models API 时使用) */
|
|
53
|
+
models?: Model[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** 模型能力类型 */
|
|
57
|
+
export type ModelCapability = 'text' | 'vision' | 'audio' | 'video' | 'embedding' | 'reasoning';
|
|
58
|
+
|
|
59
|
+
/** 能力标签配置 */
|
|
60
|
+
export interface ModelCapabilityMeta {
|
|
61
|
+
type: ModelCapability;
|
|
62
|
+
label: string;
|
|
63
|
+
labelZh: string;
|
|
64
|
+
icon: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const MODEL_CAPABILITIES: Record<ModelCapability, ModelCapabilityMeta> = {
|
|
68
|
+
text: { type: 'text', label: 'Text', labelZh: '文本', icon: '💬' },
|
|
69
|
+
vision: { type: 'vision', label: 'Vision', labelZh: '视觉', icon: '🖼️' },
|
|
70
|
+
audio: { type: 'audio', label: 'Audio', labelZh: '音频', icon: '🎤' },
|
|
71
|
+
video: { type: 'video', label: 'Video', labelZh: '视频', icon: '🎬' },
|
|
72
|
+
embedding: { type: 'embedding', label: 'Embedding', labelZh: '嵌入', icon: '📐' },
|
|
73
|
+
reasoning: { type: 'reasoning', label: 'Reasoning', labelZh: '推理', icon: '🧠' },
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export interface Model {
|
|
77
|
+
id: string;
|
|
78
|
+
name: string;
|
|
79
|
+
/** 模型能力列表(如 text, vision, audio) */
|
|
80
|
+
capabilities?: ModelCapability[];
|
|
81
|
+
/** 上下文窗口大小 */
|
|
82
|
+
contextLength?: number;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ============ Config Types ============
|
|
86
|
+
|
|
87
|
+
export interface AIConfig {
|
|
88
|
+
providerId: string;
|
|
89
|
+
apiKey: string;
|
|
90
|
+
model: string;
|
|
91
|
+
modelName?: string;
|
|
92
|
+
baseUrl?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ============ API Types ============
|
|
96
|
+
|
|
97
|
+
export interface TestConnectionOptions {
|
|
98
|
+
provider: Provider;
|
|
99
|
+
apiKey: string;
|
|
100
|
+
model?: string;
|
|
101
|
+
baseUrl?: string;
|
|
102
|
+
proxyUrl?: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface TestConnectionResult {
|
|
106
|
+
success: boolean;
|
|
107
|
+
latencyMs?: number;
|
|
108
|
+
message?: string;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface FetchModelsOptions {
|
|
112
|
+
provider: Provider;
|
|
113
|
+
apiKey?: string;
|
|
114
|
+
baseUrl?: string;
|
|
115
|
+
proxyUrl?: string;
|
|
116
|
+
fallbackToStatic?: boolean;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ============ Storage Types ============
|
|
120
|
+
|
|
121
|
+
export interface StorageAdapter {
|
|
122
|
+
get(key: string): string | null;
|
|
123
|
+
set(key: string, value: string): void;
|
|
124
|
+
remove(key: string): void;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ============ Provider Config Types ============
|
|
128
|
+
|
|
129
|
+
/** Provider 配置 JSON */
|
|
130
|
+
export interface ProviderConfig {
|
|
131
|
+
/** 模式:default=内置+自定义,customOnly=只用自定义 */
|
|
132
|
+
mode: 'default' | 'customOnly';
|
|
133
|
+
/** 白名单:只显示这些内置 provider(仅 mode=default) */
|
|
134
|
+
include?: string[];
|
|
135
|
+
/** 黑名单:隐藏这些内置 provider(仅 mode=default) */
|
|
136
|
+
exclude?: string[];
|
|
137
|
+
/** 自定义 Providers */
|
|
138
|
+
custom?: Record<string, CustomProviderDefinition>;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** AIConfigForm 组件的 Props */
|
|
142
|
+
export interface AIConfigFormProps {
|
|
143
|
+
/**
|
|
144
|
+
* 自定义请求处理器
|
|
145
|
+
* 用于接管获取模型列表和连通性测试的请求
|
|
146
|
+
* 如果提供此函数,proxyUrl 在这两种操作中将被忽略
|
|
147
|
+
*/
|
|
148
|
+
modelFetcher?: ModelFetcher;
|
|
149
|
+
/** 后端代理地址(必需,除非提供了 modelFetcher) */
|
|
150
|
+
proxyUrl?: string; // Now optional if modelFetcher is used
|
|
151
|
+
/** Provider 配置(可选,默认使用全部内置 Providers) */
|
|
152
|
+
config?: ProviderConfig;
|
|
153
|
+
/** 初始配置(可选,用于编辑已有配置) */
|
|
154
|
+
initialConfig?: Partial<AIConfig>;
|
|
155
|
+
/** 表单标题 */
|
|
156
|
+
title?: string;
|
|
157
|
+
/** 是否显示配置预览区域 */
|
|
158
|
+
showPreview?: boolean;
|
|
159
|
+
/** 保存按钮文本 */
|
|
160
|
+
saveButtonText?: string;
|
|
161
|
+
/** 是否禁用整个表单 */
|
|
162
|
+
disabled?: boolean;
|
|
163
|
+
}
|