@spacex110/core 0.1.12 → 0.1.13
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 +58 -0
- package/dist/index.js +1136 -1036
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +4 -4
- package/dist/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/channel-manager.ts +151 -0
package/package.json
CHANGED
package/src/channel-manager.ts
CHANGED
|
@@ -58,6 +58,8 @@ export interface ChannelManagerOptions {
|
|
|
58
58
|
storagePrefix?: string;
|
|
59
59
|
/** 当前激活通道的存储键 */
|
|
60
60
|
activeChannelKey?: string;
|
|
61
|
+
/** 能力默认通道的存储键 */
|
|
62
|
+
capabilityDefaultsKey?: string;
|
|
61
63
|
/** 后端代理地址(可选,用于解决 CORS 问题) */
|
|
62
64
|
proxyUrl?: string;
|
|
63
65
|
}
|
|
@@ -98,17 +100,21 @@ export class AIChannelManager {
|
|
|
98
100
|
private activeChannelId: string | null = null;
|
|
99
101
|
private storagePrefix: string;
|
|
100
102
|
private activeChannelKey: string;
|
|
103
|
+
private capabilityDefaultsKey: string;
|
|
104
|
+
private capabilityDefaults: Record<ModelCapability, string> = {} as Record<ModelCapability, string>;
|
|
101
105
|
private proxyUrl?: string;
|
|
102
106
|
private listeners: Map<ChannelEventType, Set<ChannelEventListener>> = new Map();
|
|
103
107
|
|
|
104
108
|
constructor(options: ChannelManagerOptions = {}) {
|
|
105
109
|
this.storagePrefix = options.storagePrefix || 'ai_channel';
|
|
106
110
|
this.activeChannelKey = options.activeChannelKey || 'ai_active_channel';
|
|
111
|
+
this.capabilityDefaultsKey = options.capabilityDefaultsKey || 'ai_capability_defaults';
|
|
107
112
|
this.proxyUrl = options.proxyUrl;
|
|
108
113
|
this.storageAdapter = options.storageAdapter || defaultStorageAdapter;
|
|
109
114
|
|
|
110
115
|
this.loadChannels();
|
|
111
116
|
this.loadActiveChannel();
|
|
117
|
+
this.loadCapabilityDefaults();
|
|
112
118
|
}
|
|
113
119
|
|
|
114
120
|
// ==================== 事件系统 ====================
|
|
@@ -190,6 +196,37 @@ export class AIChannelManager {
|
|
|
190
196
|
}
|
|
191
197
|
}
|
|
192
198
|
|
|
199
|
+
private loadCapabilityDefaults(): void {
|
|
200
|
+
try {
|
|
201
|
+
const raw = this.storageAdapter.get(this.capabilityDefaultsKey);
|
|
202
|
+
if (raw) {
|
|
203
|
+
const parsed = JSON.parse(raw);
|
|
204
|
+
this.capabilityDefaults = parsed as Record<ModelCapability, string>;
|
|
205
|
+
}
|
|
206
|
+
} catch (e) {
|
|
207
|
+
console.error('Failed to load capability defaults:', e);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
private saveCapabilityDefaults(): void {
|
|
212
|
+
try {
|
|
213
|
+
const keys = Object.keys(this.capabilityDefaults).filter(
|
|
214
|
+
k => this.capabilityDefaults[k as ModelCapability]
|
|
215
|
+
);
|
|
216
|
+
if (keys.length > 0) {
|
|
217
|
+
const obj: Record<string, string> = {};
|
|
218
|
+
for (const k of keys) {
|
|
219
|
+
obj[k] = this.capabilityDefaults[k as ModelCapability]!;
|
|
220
|
+
}
|
|
221
|
+
this.storageAdapter.set(this.capabilityDefaultsKey, JSON.stringify(obj));
|
|
222
|
+
} else {
|
|
223
|
+
this.storageAdapter.remove(this.capabilityDefaultsKey);
|
|
224
|
+
}
|
|
225
|
+
} catch (e) {
|
|
226
|
+
console.error('Failed to save capability defaults:', e);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
193
230
|
// ==================== 通道 CRUD ====================
|
|
194
231
|
|
|
195
232
|
/** 添加通道 */
|
|
@@ -388,6 +425,118 @@ export class AIChannelManager {
|
|
|
388
425
|
this.saveActiveChannel();
|
|
389
426
|
}
|
|
390
427
|
|
|
428
|
+
// ==================== 能力默认通道 ====================
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* 为指定能力类型设置默认通道
|
|
432
|
+
* 当调用 getChannelForCapability 时,优先返回此通道
|
|
433
|
+
*/
|
|
434
|
+
setDefaultForCapability(capability: ModelCapability, channelId: string): void {
|
|
435
|
+
if (!this.getChannel(channelId)) {
|
|
436
|
+
throw new Error(`Channel not found: ${channelId}`);
|
|
437
|
+
}
|
|
438
|
+
this.capabilityDefaults[capability] = channelId;
|
|
439
|
+
this.saveCapabilityDefaults();
|
|
440
|
+
this.emit('update', { type: 'capabilityDefault', capability, channelId });
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* 获取指定能力类型的默认通道 ID
|
|
445
|
+
* 返回 undefined 表示未设置
|
|
446
|
+
*/
|
|
447
|
+
getDefaultForCapability(capability: ModelCapability): string | undefined {
|
|
448
|
+
return this.capabilityDefaults[capability] || undefined;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* 清除指定能力类型的默认通道
|
|
453
|
+
*/
|
|
454
|
+
clearDefaultForCapability(capability: ModelCapability): void {
|
|
455
|
+
delete this.capabilityDefaults[capability];
|
|
456
|
+
this.saveCapabilityDefaults();
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* 获取所有能力类型的默认通道映射
|
|
461
|
+
* 返回 { capability: channelId } 的对象
|
|
462
|
+
*/
|
|
463
|
+
getAllCapabilityDefaults(): Record<string, string> {
|
|
464
|
+
return { ...this.capabilityDefaults };
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* 根据能力类型获取最适合的通道(带降级链)
|
|
469
|
+
*
|
|
470
|
+
* 降级链:
|
|
471
|
+
* 1. 该能力类型的显式默认通道
|
|
472
|
+
* 2. 具有该能力且最后使用时间最新的通道
|
|
473
|
+
* 3. 全局激活通道
|
|
474
|
+
* 4. 第一个可用通道
|
|
475
|
+
*/
|
|
476
|
+
getChannelForCapability(capability: ModelCapability): ChannelConfig | undefined {
|
|
477
|
+
// 1. 显式默认
|
|
478
|
+
const defaultId = this.capabilityDefaults[capability];
|
|
479
|
+
if (defaultId) {
|
|
480
|
+
const ch = this.getChannel(defaultId);
|
|
481
|
+
if (ch) return ch;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// 2. 该能力中最近使用的
|
|
485
|
+
const byCap = this.getChannelsByCapability(capability)
|
|
486
|
+
.filter(c => c.lastUsedAt)
|
|
487
|
+
.sort((a, b) => (b.lastUsedAt || 0) - (a.lastUsedAt || 0));
|
|
488
|
+
if (byCap.length > 0) return byCap[0];
|
|
489
|
+
|
|
490
|
+
// 3. 全局激活
|
|
491
|
+
const active = this.getActiveChannel();
|
|
492
|
+
if (active) return active;
|
|
493
|
+
|
|
494
|
+
// 4. 第一个可用
|
|
495
|
+
return this.channels[0];
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* 使用指定能力类型的默认通道发送聊天请求
|
|
500
|
+
* 自动选择合适的通道,无需手动指定 channelId
|
|
501
|
+
*/
|
|
502
|
+
async chatForCapability(
|
|
503
|
+
capability: ModelCapability,
|
|
504
|
+
message: string,
|
|
505
|
+
options?: {
|
|
506
|
+
messages?: Array<{ role: string; content: string }>;
|
|
507
|
+
maxTokens?: number;
|
|
508
|
+
}
|
|
509
|
+
): Promise<ChatResult> {
|
|
510
|
+
const channel = this.getChannelForCapability(capability);
|
|
511
|
+
if (!channel) {
|
|
512
|
+
throw new Error(`No available channel for capability: ${capability}`);
|
|
513
|
+
}
|
|
514
|
+
return this.chatWith(channel.id, message, options);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* 使用指定能力类型的默认通道发送流式聊天请求
|
|
519
|
+
*/
|
|
520
|
+
async chatStreamForCapability(
|
|
521
|
+
capability: ModelCapability,
|
|
522
|
+
message: string,
|
|
523
|
+
options?: {
|
|
524
|
+
messages?: Array<{ role: string; content: string }>;
|
|
525
|
+
maxTokens?: number;
|
|
526
|
+
signal?: AbortSignal;
|
|
527
|
+
onDelta?: (full: string) => void;
|
|
528
|
+
}
|
|
529
|
+
): Promise<ChatResult> {
|
|
530
|
+
const channel = this.getChannelForCapability(capability);
|
|
531
|
+
if (!channel) {
|
|
532
|
+
throw new Error(`No available channel for capability: ${capability}`);
|
|
533
|
+
}
|
|
534
|
+
return this.chatWithStream(channel.id, message, {
|
|
535
|
+
...options,
|
|
536
|
+
onDelta: options?.onDelta || ((_: string) => {}),
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
|
|
391
540
|
// ==================== 模型查询 ====================
|
|
392
541
|
|
|
393
542
|
/** 获取 Provider 的可用模型列表(动态获取 + 静态兜底) */
|
|
@@ -751,6 +900,8 @@ export class AIChannelManager {
|
|
|
751
900
|
this.channels = [];
|
|
752
901
|
this.activeChannelId = null;
|
|
753
902
|
this.saveActiveChannel();
|
|
903
|
+
this.capabilityDefaults = {} as Record<ModelCapability, string>;
|
|
904
|
+
this.saveCapabilityDefaults();
|
|
754
905
|
this.emit('clear', {});
|
|
755
906
|
}
|
|
756
907
|
|