@longzai-intelligence-model-gateway/core 0.0.1
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 +685 -0
- package/dist/index.js +1 -0
- package/package.json +44 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,685 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { DomainError } from "@longzai-intelligence/error";
|
|
3
|
+
import { ApplicationMapper, DomainEvent, Entity, OrmMapper, Result } from "@longzai-intelligence/shared-kernel";
|
|
4
|
+
|
|
5
|
+
//#region src/types/error.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* 统一错误类型定义
|
|
8
|
+
* 包含错误分类、错误码、重试建议和降级建议
|
|
9
|
+
*/
|
|
10
|
+
/** 错误分类 */
|
|
11
|
+
type ErrorCategory = 'client' | 'server' | 'provider';
|
|
12
|
+
/** 错误码 */
|
|
13
|
+
declare enum ErrorCode {
|
|
14
|
+
INVALID_REQUEST = "invalid_request",
|
|
15
|
+
AUTHENTICATION_FAILED = "authentication_failed",
|
|
16
|
+
PERMISSION_DENIED = "permission_denied",
|
|
17
|
+
MODEL_NOT_FOUND = "model_not_found",
|
|
18
|
+
BUDGET_EXCEEDED = "budget_exceeded",
|
|
19
|
+
RATE_LIMIT_EXCEEDED = "rate_limit_exceeded",
|
|
20
|
+
INVALID_API_KEY = "invalid_api_key",
|
|
21
|
+
INTERNAL_ERROR = "internal_error",
|
|
22
|
+
ROUTING_ERROR = "routing_error",
|
|
23
|
+
DATABASE_ERROR = "database_error",
|
|
24
|
+
CACHE_ERROR = "cache_error",
|
|
25
|
+
PROVIDER_UNAVAILABLE = "provider_unavailable",
|
|
26
|
+
PROVIDER_RATE_LIMITED = "provider_rate_limited",
|
|
27
|
+
PROVIDER_TIMEOUT = "provider_timeout",
|
|
28
|
+
PROVIDER_ERROR = "provider_error",
|
|
29
|
+
MODEL_OVERLOADED = "model_overloaded",
|
|
30
|
+
CONTEXT_LENGTH_EXCEEDED = "context_length_exceeded"
|
|
31
|
+
}
|
|
32
|
+
/** 重试建议 */
|
|
33
|
+
type RetrySuggestion = {
|
|
34
|
+
/** 是否可重试 */retryable: boolean; /** 建议重试次数 */
|
|
35
|
+
maxRetries: number; /** 建议重试间隔(毫秒) */
|
|
36
|
+
retryAfter: number; /** 可重试的错误码 */
|
|
37
|
+
retryableCodes: ErrorCode[];
|
|
38
|
+
};
|
|
39
|
+
/** 降级建议 */
|
|
40
|
+
type FallbackSuggestion = {
|
|
41
|
+
/** 是否可降级 */fallbackable: boolean; /** 备用模型 */
|
|
42
|
+
fallbackModel?: string; /** 备用供应商 */
|
|
43
|
+
fallbackProvider?: string; /** 是否可返回缓存 */
|
|
44
|
+
cacheAvailable: boolean;
|
|
45
|
+
};
|
|
46
|
+
/** 网关错误详情 */
|
|
47
|
+
type GatewayErrorDetail = {
|
|
48
|
+
/** 错误码 */code: ErrorCode; /** 错误分类 */
|
|
49
|
+
category: ErrorCategory; /** 错误消息 */
|
|
50
|
+
message: string; /** 详细错误信息 */
|
|
51
|
+
detail?: string; /** 重试建议 */
|
|
52
|
+
retry: RetrySuggestion; /** 降级建议 */
|
|
53
|
+
fallback: FallbackSuggestion; /** 供应商原始错误 */
|
|
54
|
+
providerError?: {
|
|
55
|
+
provider: string;
|
|
56
|
+
code?: string;
|
|
57
|
+
message?: string;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
/** 网关错误(兼容 OpenAI 错误格式) */
|
|
61
|
+
type GatewayError = {
|
|
62
|
+
error: {
|
|
63
|
+
message: string;
|
|
64
|
+
type: string;
|
|
65
|
+
code: ErrorCode;
|
|
66
|
+
param?: string; /** 网关扩展字段 */
|
|
67
|
+
gateway?: GatewayErrorDetail;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
/** HTTP 状态码映射 */
|
|
71
|
+
declare const ERROR_STATUS_MAP: Record<ErrorCategory, number>;
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/types/request.d.ts
|
|
74
|
+
/**
|
|
75
|
+
* 统一请求类型定义
|
|
76
|
+
* 完全兼容 OpenAI API 格式,并扩展路由策略、优先级、预算限制等参数
|
|
77
|
+
*/
|
|
78
|
+
/** 消息角色 */
|
|
79
|
+
type MessageRole = 'system' | 'user' | 'assistant' | 'tool';
|
|
80
|
+
/** 消息内容类型 */
|
|
81
|
+
type MessageContentType = 'text' | 'image_url';
|
|
82
|
+
/** 消息内容项 */
|
|
83
|
+
type MessageContentPart = {
|
|
84
|
+
type: MessageContentType;
|
|
85
|
+
text?: string;
|
|
86
|
+
image_url?: {
|
|
87
|
+
url: string;
|
|
88
|
+
detail?: 'auto' | 'low' | 'high';
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
/** 工具调用函数 */
|
|
92
|
+
type ToolCallFunction = {
|
|
93
|
+
/** 调用名称 */name: string; /** 调用参数(JSON字符串) */
|
|
94
|
+
arguments: string;
|
|
95
|
+
};
|
|
96
|
+
/** 工具调用 */
|
|
97
|
+
type ToolCall = {
|
|
98
|
+
/** 工具调用ID */id: string; /** 调用类型,固定为 function */
|
|
99
|
+
type: 'function'; /** 调用的函数 */
|
|
100
|
+
function: ToolCallFunction;
|
|
101
|
+
};
|
|
102
|
+
/** 聊天消息 */
|
|
103
|
+
type ChatMessage = {
|
|
104
|
+
/** 消息角色 */role: MessageRole; /** 消息文本内容(与content二选一) */
|
|
105
|
+
content?: string | MessageContentPart[]; /** 工具调用列表(assistant角色) */
|
|
106
|
+
tool_calls?: ToolCall[]; /** 工具调用ID(tool角色) */
|
|
107
|
+
tool_call_id?: string; /** 消息名称 */
|
|
108
|
+
name?: string;
|
|
109
|
+
};
|
|
110
|
+
/** 函数定义 */
|
|
111
|
+
type FunctionDefinition = {
|
|
112
|
+
/** 函数名称 */name: string; /** 函数描述 */
|
|
113
|
+
description?: string; /** 函数参数 JSON Schema */
|
|
114
|
+
parameters?: Record<string, unknown>;
|
|
115
|
+
};
|
|
116
|
+
/** 工具定义 */
|
|
117
|
+
type ToolDefinition = {
|
|
118
|
+
/** 工具类型 */type: 'function'; /** 函数定义 */
|
|
119
|
+
function: FunctionDefinition;
|
|
120
|
+
};
|
|
121
|
+
/** 响应格式 */
|
|
122
|
+
type ResponseFormat = {
|
|
123
|
+
type: 'text' | 'json_object' | 'json_schema';
|
|
124
|
+
json_schema?: Record<string, unknown>;
|
|
125
|
+
};
|
|
126
|
+
/** 路由策略扩展参数 */
|
|
127
|
+
type RoutingExtension = {
|
|
128
|
+
/** 路由策略 */routingStrategy?: 'model-name' | 'cost-first' | 'performance-first' | 'quality-first'; /** 请求优先级 */
|
|
129
|
+
priority?: 'low' | 'normal' | 'high'; /** 预算限制(美元) */
|
|
130
|
+
budgetLimit?: number; /** 请求超时时间(毫秒) */
|
|
131
|
+
timeout?: number; /** 是否禁用缓存 */
|
|
132
|
+
noCache?: boolean; /** 调用者标签(用于成本归因) */
|
|
133
|
+
tags?: Record<string, string>;
|
|
134
|
+
};
|
|
135
|
+
/** 聊天补全请求(兼容 OpenAI ChatCompletion) */
|
|
136
|
+
type ChatCompletionRequest = RoutingExtension & {
|
|
137
|
+
/** 模型名称或别名 */model: string; /** 消息列表 */
|
|
138
|
+
messages: ChatMessage[]; /** 生成温度 (0-2) */
|
|
139
|
+
temperature?: number; /** 核采样概率 */
|
|
140
|
+
top_p?: number; /** 生成数量 */
|
|
141
|
+
n?: number; /** 是否流式输出 */
|
|
142
|
+
stream?: boolean; /** 停止词 */
|
|
143
|
+
stop?: string | string[]; /** 最大输出 Token 数 */
|
|
144
|
+
max_tokens?: number; /** 存在惩罚 (-2 到 2) */
|
|
145
|
+
presence_penalty?: number; /** 频率惩罚 (-2 到 2) */
|
|
146
|
+
frequency_penalty?: number; /** 随机种子 */
|
|
147
|
+
seed?: number; /** 工具定义列表 */
|
|
148
|
+
tools?: ToolDefinition[]; /** 工具选择策略 */
|
|
149
|
+
tool_choice?: 'none' | 'auto' | 'required' | {
|
|
150
|
+
type: 'function';
|
|
151
|
+
function: {
|
|
152
|
+
name: string;
|
|
153
|
+
};
|
|
154
|
+
}; /** 响应格式 */
|
|
155
|
+
response_format?: ResponseFormat; /** 用户标识 */
|
|
156
|
+
user?: string;
|
|
157
|
+
};
|
|
158
|
+
/** 文本补全请求(兼容 OpenAI Completion) */
|
|
159
|
+
type CompletionRequest = RoutingExtension & {
|
|
160
|
+
model: string;
|
|
161
|
+
prompt: string | string[];
|
|
162
|
+
max_tokens?: number;
|
|
163
|
+
temperature?: number;
|
|
164
|
+
top_p?: number;
|
|
165
|
+
n?: number;
|
|
166
|
+
stream?: boolean;
|
|
167
|
+
stop?: string | string[];
|
|
168
|
+
presence_penalty?: number;
|
|
169
|
+
frequency_penalty?: number;
|
|
170
|
+
seed?: number;
|
|
171
|
+
user?: string;
|
|
172
|
+
};
|
|
173
|
+
/** 嵌入请求(兼容 OpenAI Embedding) */
|
|
174
|
+
type EmbeddingRequest = RoutingExtension & {
|
|
175
|
+
model: string;
|
|
176
|
+
input: string | string[];
|
|
177
|
+
encoding_format?: 'float' | 'base64';
|
|
178
|
+
dimensions?: number;
|
|
179
|
+
user?: string;
|
|
180
|
+
};
|
|
181
|
+
//#endregion
|
|
182
|
+
//#region src/types/response.d.ts
|
|
183
|
+
/** 响应消息 */
|
|
184
|
+
type ResponseMessage = {
|
|
185
|
+
role: 'assistant';
|
|
186
|
+
content: string | null;
|
|
187
|
+
tool_calls?: ToolCall[];
|
|
188
|
+
};
|
|
189
|
+
/** 补全选择项 */
|
|
190
|
+
type ChatChoice = {
|
|
191
|
+
/** 选择项索引 */index: number; /** 消息内容 */
|
|
192
|
+
message: ResponseMessage; /** 结束原因 */
|
|
193
|
+
finish_reason: 'stop' | 'length' | 'tool_calls' | 'content_filter' | null;
|
|
194
|
+
};
|
|
195
|
+
/** 流式补全增量 */
|
|
196
|
+
type ChatChunkDelta = {
|
|
197
|
+
role?: 'assistant';
|
|
198
|
+
content?: string | null;
|
|
199
|
+
tool_calls?: Array<{
|
|
200
|
+
index: number;
|
|
201
|
+
id?: string;
|
|
202
|
+
type?: 'function';
|
|
203
|
+
function?: {
|
|
204
|
+
name?: string;
|
|
205
|
+
arguments?: string;
|
|
206
|
+
};
|
|
207
|
+
}>;
|
|
208
|
+
};
|
|
209
|
+
/** 流式选择项 */
|
|
210
|
+
type ChatStreamChoice = {
|
|
211
|
+
index: number;
|
|
212
|
+
delta: ChatChunkDelta;
|
|
213
|
+
finish_reason: 'stop' | 'length' | 'tool_calls' | 'content_filter' | null;
|
|
214
|
+
};
|
|
215
|
+
/** Token 使用量 */
|
|
216
|
+
type TokenUsage = {
|
|
217
|
+
prompt_tokens: number;
|
|
218
|
+
completion_tokens: number;
|
|
219
|
+
total_tokens: number;
|
|
220
|
+
};
|
|
221
|
+
/** 网关扩展响应字段 */
|
|
222
|
+
type GatewayExtension = {
|
|
223
|
+
/** 实际使用的模型ID */gateway_model?: string; /** 实际使用的供应商 */
|
|
224
|
+
gateway_provider?: string; /** 请求延迟(毫秒) */
|
|
225
|
+
gateway_latency_ms?: number; /** 请求成本(美元) */
|
|
226
|
+
gateway_cost?: number; /** 是否命中缓存 */
|
|
227
|
+
gateway_cache_hit?: boolean; /** 路由决策信息 */
|
|
228
|
+
gateway_routing?: {
|
|
229
|
+
strategy: string;
|
|
230
|
+
original_model?: string;
|
|
231
|
+
routed_model: string;
|
|
232
|
+
routed_provider: string;
|
|
233
|
+
};
|
|
234
|
+
};
|
|
235
|
+
/** 聊天补全响应(兼容 OpenAI ChatCompletion) */
|
|
236
|
+
type ChatCompletionResponse = GatewayExtension & {
|
|
237
|
+
id: string;
|
|
238
|
+
object: 'chat.completion';
|
|
239
|
+
created: number;
|
|
240
|
+
model: string;
|
|
241
|
+
choices: ChatChoice[];
|
|
242
|
+
usage: TokenUsage;
|
|
243
|
+
system_fingerprint?: string;
|
|
244
|
+
};
|
|
245
|
+
/** 流式聊天补全块 */
|
|
246
|
+
type ChatCompletionChunk = GatewayExtension & {
|
|
247
|
+
id: string;
|
|
248
|
+
object: 'chat.completion.chunk';
|
|
249
|
+
created: number;
|
|
250
|
+
model: string;
|
|
251
|
+
choices: ChatStreamChoice[];
|
|
252
|
+
};
|
|
253
|
+
/** 文本补全选择项 */
|
|
254
|
+
type CompletionChoice = {
|
|
255
|
+
index: number;
|
|
256
|
+
text: string;
|
|
257
|
+
finish_reason: 'stop' | 'length' | 'tool_calls' | 'content_filter' | null;
|
|
258
|
+
};
|
|
259
|
+
/** 文本补全响应(兼容 OpenAI Completion) */
|
|
260
|
+
type CompletionResponse = GatewayExtension & {
|
|
261
|
+
id: string;
|
|
262
|
+
object: 'text_completion';
|
|
263
|
+
created: number;
|
|
264
|
+
model: string;
|
|
265
|
+
choices: CompletionChoice[];
|
|
266
|
+
usage: TokenUsage;
|
|
267
|
+
};
|
|
268
|
+
/** 嵌入数据项 */
|
|
269
|
+
type EmbeddingData = {
|
|
270
|
+
object: 'embedding';
|
|
271
|
+
index: number;
|
|
272
|
+
embedding: number[] | string;
|
|
273
|
+
};
|
|
274
|
+
/** 嵌入响应(兼容 OpenAI Embedding) */
|
|
275
|
+
type EmbeddingResponse = GatewayExtension & {
|
|
276
|
+
id: string;
|
|
277
|
+
object: 'list';
|
|
278
|
+
created: number;
|
|
279
|
+
model: string;
|
|
280
|
+
data: EmbeddingData[];
|
|
281
|
+
usage: TokenUsage;
|
|
282
|
+
};
|
|
283
|
+
/** 模型信息(兼容 OpenAI Model) */
|
|
284
|
+
type ModelInfo = {
|
|
285
|
+
id: string;
|
|
286
|
+
object: 'model';
|
|
287
|
+
created: number;
|
|
288
|
+
owned_by: string;
|
|
289
|
+
};
|
|
290
|
+
/** 模型列表响应 */
|
|
291
|
+
type ModelListResponse = {
|
|
292
|
+
object: 'list';
|
|
293
|
+
data: ModelInfo[];
|
|
294
|
+
};
|
|
295
|
+
//#endregion
|
|
296
|
+
//#region src/types/strategy.d.ts
|
|
297
|
+
/**
|
|
298
|
+
* 执行策略类型定义
|
|
299
|
+
* 包含重试策略、超时策略、降级策略
|
|
300
|
+
*/
|
|
301
|
+
/** 重试策略 */
|
|
302
|
+
type RetryStrategy = {
|
|
303
|
+
/** 最大重试次数(默认3次) */maxRetries: number; /** 初始重试间隔(毫秒,默认1000) */
|
|
304
|
+
initialInterval: number; /** 最大重试间隔(毫秒,默认30000) */
|
|
305
|
+
maxInterval: number; /** 退避乘数(默认2) */
|
|
306
|
+
multiplier: number; /** 可重试的HTTP状态码 */
|
|
307
|
+
retryableStatusCodes: number[]; /** 可重试的错误码 */
|
|
308
|
+
retryableErrorCodes: string[];
|
|
309
|
+
};
|
|
310
|
+
/** 超时策略 */
|
|
311
|
+
type TimeoutStrategy = {
|
|
312
|
+
/** 连接超时(毫秒,默认10000) */connectTimeout: number; /** 读取超时(毫秒,默认60000) */
|
|
313
|
+
readTimeout: number; /** 写入超时(毫秒,默认10000) */
|
|
314
|
+
writeTimeout: number; /** 总请求超时(毫秒,默认120000) */
|
|
315
|
+
requestTimeout: number;
|
|
316
|
+
};
|
|
317
|
+
/** 降级动作类型 */
|
|
318
|
+
type FallbackAction = 'fallback_model' | 'cache_result' | 'default_response' | 'reject';
|
|
319
|
+
/** 降级策略 */
|
|
320
|
+
type FallbackStrategy = {
|
|
321
|
+
/** 降级动作列表(按优先级排序) */actions: FallbackAction[]; /** 备用模型列表 */
|
|
322
|
+
fallbackModels: string[]; /** 是否允许返回缓存 */
|
|
323
|
+
allowCache: boolean; /** 默认响应内容 */
|
|
324
|
+
defaultResponse?: string; /** 最大降级次数 */
|
|
325
|
+
maxFallbacks: number;
|
|
326
|
+
};
|
|
327
|
+
/** 执行策略(组合重试、超时、降级) */
|
|
328
|
+
type ExecutionStrategy = {
|
|
329
|
+
/** 重试策略 */retry: RetryStrategy; /** 超时策略 */
|
|
330
|
+
timeout: TimeoutStrategy; /** 降级策略 */
|
|
331
|
+
fallback: FallbackStrategy;
|
|
332
|
+
};
|
|
333
|
+
/** 默认重试策略 */
|
|
334
|
+
declare const DEFAULT_RETRY_STRATEGY: RetryStrategy;
|
|
335
|
+
/** 默认超时策略 */
|
|
336
|
+
declare const DEFAULT_TIMEOUT_STRATEGY: TimeoutStrategy;
|
|
337
|
+
/** 默认降级策略 */
|
|
338
|
+
declare const DEFAULT_FALLBACK_STRATEGY: FallbackStrategy;
|
|
339
|
+
/** 默认执行策略 */
|
|
340
|
+
declare const DEFAULT_EXECUTION_STRATEGY: ExecutionStrategy;
|
|
341
|
+
//#endregion
|
|
342
|
+
//#region src/utils/cost.d.ts
|
|
343
|
+
/**
|
|
344
|
+
* 成本计算工具函数
|
|
345
|
+
*/
|
|
346
|
+
/** 模型定价信息 */
|
|
347
|
+
type ModelPricing = {
|
|
348
|
+
/** 输入 Token 价格(美元/千Token) */inputPrice: number; /** 输出 Token 价格(美元/千Token) */
|
|
349
|
+
outputPrice: number;
|
|
350
|
+
};
|
|
351
|
+
/** 计算单次请求成本 */
|
|
352
|
+
declare function calculateCost(pricing: ModelPricing, inputTokens: number, outputTokens: number): number;
|
|
353
|
+
/** 格式化成本显示 */
|
|
354
|
+
declare function formatCost(cost: number): string;
|
|
355
|
+
/** 计算预算使用百分比 */
|
|
356
|
+
declare function budgetUsagePercent(used: number, limit: number): number;
|
|
357
|
+
//#endregion
|
|
358
|
+
//#region src/utils/crypto.d.ts
|
|
359
|
+
/**
|
|
360
|
+
* 加密解密工具函数
|
|
361
|
+
* 使用 AES-256-GCM 算法加密 API 密钥等敏感数据
|
|
362
|
+
*/
|
|
363
|
+
/** 加密文本 */
|
|
364
|
+
declare function encrypt(plaintext: string, secret: string): Promise<string>;
|
|
365
|
+
/** 解密文本 */
|
|
366
|
+
declare function decrypt(ciphertext: string, secret: string): Promise<string>;
|
|
367
|
+
//#endregion
|
|
368
|
+
//#region src/utils/token.d.ts
|
|
369
|
+
/**
|
|
370
|
+
* Token 计数工具函数
|
|
371
|
+
* 提供基于字符数的粗略 Token 估算
|
|
372
|
+
*/
|
|
373
|
+
/** 粗略估算文本的 Token 数(中文约1.5字/Token,英文约4字符/Token) */
|
|
374
|
+
declare function estimateTokens(text: string): number;
|
|
375
|
+
/** 估算消息列表的 Token 数 */
|
|
376
|
+
declare function estimateMessagesTokens(messages: Array<{
|
|
377
|
+
role: string;
|
|
378
|
+
content?: string | unknown[];
|
|
379
|
+
}>): number;
|
|
380
|
+
//#endregion
|
|
381
|
+
//#region src/cache/cache.dto.d.ts
|
|
382
|
+
/** 缓存条目响应 DTO */
|
|
383
|
+
type CacheEntryResponseDTO = {
|
|
384
|
+
id: string;
|
|
385
|
+
requestHash: string;
|
|
386
|
+
requestVector: string | null;
|
|
387
|
+
responseData: string;
|
|
388
|
+
modelId: string;
|
|
389
|
+
similarityThreshold: number;
|
|
390
|
+
hitCount: number;
|
|
391
|
+
expiresAt: string;
|
|
392
|
+
createdAt: string;
|
|
393
|
+
};
|
|
394
|
+
/** 创建缓存条目请求 DTO */
|
|
395
|
+
type CreateCacheEntryRequestDTO = {
|
|
396
|
+
requestHash: string;
|
|
397
|
+
requestVector?: string | null;
|
|
398
|
+
responseData: string;
|
|
399
|
+
modelId: string;
|
|
400
|
+
similarityThreshold?: number;
|
|
401
|
+
ttlSeconds?: number;
|
|
402
|
+
};
|
|
403
|
+
//#endregion
|
|
404
|
+
//#region src/cache/cache.port.d.ts
|
|
405
|
+
/** 缓存端口接口 */
|
|
406
|
+
type CachePort = {
|
|
407
|
+
/** 根据请求哈希获取缓存条目 */getByHash(requestHash: string): Promise<Result<CacheEntryResponseDTO | null, DomainError>>; /** 创建缓存条目 */
|
|
408
|
+
create(input: CreateCacheEntryRequestDTO): Promise<Result<CacheEntryResponseDTO, DomainError>>; /** 记录缓存命中 */
|
|
409
|
+
recordHit(id: string): Promise<Result<CacheEntryResponseDTO, DomainError>>; /** 删除缓存条目 */
|
|
410
|
+
delete(id: string): Promise<Result<boolean, DomainError>>; /** 清理过期缓存 */
|
|
411
|
+
deleteExpired(): Promise<Result<number, DomainError>>;
|
|
412
|
+
};
|
|
413
|
+
/** 缓存端口令牌 */
|
|
414
|
+
declare const CACHE_PORT_TOKEN: unique symbol;
|
|
415
|
+
//#endregion
|
|
416
|
+
//#region src/cache/cache.schema.d.ts
|
|
417
|
+
/** 创建缓存条目的校验 Schema */
|
|
418
|
+
declare const createCacheEntrySchema: z.ZodObject<{
|
|
419
|
+
requestHash: z.ZodString;
|
|
420
|
+
requestVector: z.ZodOptional<z.ZodString>;
|
|
421
|
+
responseData: z.ZodString;
|
|
422
|
+
modelId: z.ZodString;
|
|
423
|
+
similarityThreshold: z.ZodOptional<z.ZodNumber>;
|
|
424
|
+
ttlSeconds: z.ZodOptional<z.ZodNumber>;
|
|
425
|
+
}, z.core.$strip>;
|
|
426
|
+
/** 创建缓存条目的输入类型 */
|
|
427
|
+
type CreateCacheEntryInput = z.infer<typeof createCacheEntrySchema>;
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/cache/cache.types.d.ts
|
|
430
|
+
/** 缓存策略配置 */
|
|
431
|
+
type CachePolicy = {
|
|
432
|
+
enabled: boolean;
|
|
433
|
+
ttlSeconds: number;
|
|
434
|
+
similarityThreshold: number;
|
|
435
|
+
};
|
|
436
|
+
//#endregion
|
|
437
|
+
//#region src/cache/cache.error.d.ts
|
|
438
|
+
/** 缓存领域错误 */
|
|
439
|
+
declare class CacheError extends DomainError {
|
|
440
|
+
constructor(message: string);
|
|
441
|
+
}
|
|
442
|
+
//#endregion
|
|
443
|
+
//#region src/cache/cache.event.d.ts
|
|
444
|
+
/** 缓存命中事件 */
|
|
445
|
+
declare class CacheHitEvent extends DomainEvent {
|
|
446
|
+
readonly cacheEntryId: string;
|
|
447
|
+
readonly modelId: string;
|
|
448
|
+
static readonly TYPE = "cache:hit";
|
|
449
|
+
readonly type = "cache:hit";
|
|
450
|
+
constructor(eventId: string, cacheEntryId: string, modelId: string);
|
|
451
|
+
}
|
|
452
|
+
//#endregion
|
|
453
|
+
//#region src/cache/cache-entry.entity.d.ts
|
|
454
|
+
type CacheEntryProps = {
|
|
455
|
+
requestHash: string;
|
|
456
|
+
requestVector: string | null;
|
|
457
|
+
responseData: string;
|
|
458
|
+
modelId: string;
|
|
459
|
+
similarityThreshold: number;
|
|
460
|
+
hitCount: number;
|
|
461
|
+
expiresAt: string;
|
|
462
|
+
createdAt: string;
|
|
463
|
+
};
|
|
464
|
+
/**
|
|
465
|
+
* 缓存条目实体
|
|
466
|
+
*/
|
|
467
|
+
declare class CacheEntryEntity extends Entity<CacheEntryProps> {
|
|
468
|
+
get requestHash(): string;
|
|
469
|
+
get requestVector(): string | null;
|
|
470
|
+
get responseData(): string;
|
|
471
|
+
get modelId(): string;
|
|
472
|
+
get similarityThreshold(): number;
|
|
473
|
+
get hitCount(): number;
|
|
474
|
+
get expiresAt(): string;
|
|
475
|
+
get createdAt(): string;
|
|
476
|
+
private constructor();
|
|
477
|
+
static create(id: string, props: Omit<CacheEntryProps, 'hitCount' | 'createdAt'> & {
|
|
478
|
+
ttlSeconds?: number;
|
|
479
|
+
}): CacheEntryEntity;
|
|
480
|
+
static reconstitute(id: string, props: CacheEntryProps): CacheEntryEntity;
|
|
481
|
+
/** 记录缓存命中 */
|
|
482
|
+
recordHit(): void;
|
|
483
|
+
/** 检查是否过期 */
|
|
484
|
+
isExpired(): boolean;
|
|
485
|
+
}
|
|
486
|
+
//#endregion
|
|
487
|
+
//#region src/cache/cache-entry.mapper.d.ts
|
|
488
|
+
/**
|
|
489
|
+
* 缓存条目应用层映射器
|
|
490
|
+
*/
|
|
491
|
+
declare const CacheEntryMapper: ApplicationMapper<CacheEntryEntity, CacheEntryResponseDTO>;
|
|
492
|
+
//#endregion
|
|
493
|
+
//#region src/cache/cache.repository.d.ts
|
|
494
|
+
/**
|
|
495
|
+
* 缓存条目仓储接口
|
|
496
|
+
*/
|
|
497
|
+
type CacheRepository = {
|
|
498
|
+
/** 根据请求哈希获取缓存条目 */getByHash(requestHash: string): Promise<Result<CacheEntryEntity | null, DomainError>>; /** 创建缓存条目 */
|
|
499
|
+
create(entity: CacheEntryEntity): Promise<Result<CacheEntryEntity, DomainError>>; /** 记录缓存命中 */
|
|
500
|
+
recordHit(id: string): Promise<Result<CacheEntryEntity, DomainError>>; /** 删除缓存条目 */
|
|
501
|
+
delete(id: string): Promise<Result<boolean, DomainError>>; /** 清理过期缓存 */
|
|
502
|
+
deleteExpired(): Promise<Result<number, DomainError>>;
|
|
503
|
+
};
|
|
504
|
+
//#endregion
|
|
505
|
+
//#region src/cache/cache.orm-entity.d.ts
|
|
506
|
+
/**
|
|
507
|
+
* 缓存条目数据库行类型
|
|
508
|
+
*/
|
|
509
|
+
type CacheEntryRow = {
|
|
510
|
+
id: string;
|
|
511
|
+
requestHash: string;
|
|
512
|
+
requestVector: string | null;
|
|
513
|
+
responseData: string;
|
|
514
|
+
modelId: string;
|
|
515
|
+
similarityThreshold: number;
|
|
516
|
+
hitCount: number;
|
|
517
|
+
expiresAt: string;
|
|
518
|
+
createdAt: string;
|
|
519
|
+
};
|
|
520
|
+
//#endregion
|
|
521
|
+
//#region src/cache/cache.orm-mapper.d.ts
|
|
522
|
+
/**
|
|
523
|
+
* 缓存条目 ORM 映射器
|
|
524
|
+
*/
|
|
525
|
+
declare const CacheEntryOrmMapper: OrmMapper<CacheEntryEntity, CacheEntryRow>;
|
|
526
|
+
//#endregion
|
|
527
|
+
//#region src/cache/cache.orm-repository.d.ts
|
|
528
|
+
/**
|
|
529
|
+
* 基于 Drizzle 的缓存条目仓储实现
|
|
530
|
+
*/
|
|
531
|
+
declare class DrizzleCacheRepository implements CacheRepository {
|
|
532
|
+
private readonly db;
|
|
533
|
+
private readonly schema;
|
|
534
|
+
constructor(db: any, schema: any);
|
|
535
|
+
/** 根据请求哈希获取缓存条目 */
|
|
536
|
+
getByHash(requestHash: string): Promise<Result<CacheEntryEntity | null, DomainError>>;
|
|
537
|
+
/** 创建缓存条目 */
|
|
538
|
+
create(entity: CacheEntryEntity): Promise<Result<CacheEntryEntity, DomainError>>;
|
|
539
|
+
/** 记录缓存命中 */
|
|
540
|
+
recordHit(id: string): Promise<Result<CacheEntryEntity, DomainError>>;
|
|
541
|
+
/** 删除缓存条目 */
|
|
542
|
+
delete(id: string): Promise<Result<boolean, DomainError>>;
|
|
543
|
+
/** 清理过期缓存 */
|
|
544
|
+
deleteExpired(): Promise<Result<number, DomainError>>;
|
|
545
|
+
}
|
|
546
|
+
//#endregion
|
|
547
|
+
//#region src/cache/usecases/get-cache-entry.usecase.d.ts
|
|
548
|
+
/**
|
|
549
|
+
* 获取缓存条目用例
|
|
550
|
+
*
|
|
551
|
+
* 根据请求哈希查询缓存条目,若条目已过期则自动删除并返回 null,
|
|
552
|
+
* 若条目有效则记录命中并返回实体
|
|
553
|
+
*/
|
|
554
|
+
declare class GetCacheEntryUseCase {
|
|
555
|
+
private readonly repository;
|
|
556
|
+
constructor(repository: CacheRepository);
|
|
557
|
+
execute(requestHash: string): Promise<Result<CacheEntryEntity | null, DomainError>>;
|
|
558
|
+
}
|
|
559
|
+
//#endregion
|
|
560
|
+
//#region src/cache/usecases/create-cache-entry.usecase.d.ts
|
|
561
|
+
/**
|
|
562
|
+
* 创建缓存条目用例
|
|
563
|
+
*
|
|
564
|
+
* 接收创建请求 DTO,构造实体并持久化到仓储
|
|
565
|
+
*/
|
|
566
|
+
declare class CreateCacheEntryUseCase {
|
|
567
|
+
private readonly repository;
|
|
568
|
+
constructor(repository: CacheRepository);
|
|
569
|
+
execute(input: CreateCacheEntryRequestDTO): Promise<Result<CacheEntryEntity, DomainError>>;
|
|
570
|
+
}
|
|
571
|
+
//#endregion
|
|
572
|
+
//#region src/cache/usecases/record-cache-hit.usecase.d.ts
|
|
573
|
+
/**
|
|
574
|
+
* 记录缓存命中用例
|
|
575
|
+
*
|
|
576
|
+
* 对指定缓存条目增加命中计数
|
|
577
|
+
*/
|
|
578
|
+
declare class RecordCacheHitUseCase {
|
|
579
|
+
private readonly repository;
|
|
580
|
+
constructor(repository: CacheRepository);
|
|
581
|
+
execute(id: string): Promise<Result<CacheEntryEntity, DomainError>>;
|
|
582
|
+
}
|
|
583
|
+
//#endregion
|
|
584
|
+
//#region src/cache/usecases/delete-cache-entry.usecase.d.ts
|
|
585
|
+
/**
|
|
586
|
+
* 删除缓存条目用例
|
|
587
|
+
*
|
|
588
|
+
* 根据条目 ID 从仓储中删除指定缓存条目
|
|
589
|
+
*/
|
|
590
|
+
declare class DeleteCacheEntryUseCase {
|
|
591
|
+
private readonly repository;
|
|
592
|
+
constructor(repository: CacheRepository);
|
|
593
|
+
execute(id: string): Promise<Result<boolean, DomainError>>;
|
|
594
|
+
}
|
|
595
|
+
//#endregion
|
|
596
|
+
//#region src/cache/usecases/cleanup-cache-entries.usecase.d.ts
|
|
597
|
+
/**
|
|
598
|
+
* 清理过期缓存条目用例
|
|
599
|
+
*
|
|
600
|
+
* 删除仓储中所有已过期的缓存条目,返回清理数量
|
|
601
|
+
*/
|
|
602
|
+
declare class CleanupCacheEntriesUseCase {
|
|
603
|
+
private readonly repository;
|
|
604
|
+
constructor(repository: CacheRepository);
|
|
605
|
+
execute(): Promise<Result<number, DomainError>>;
|
|
606
|
+
}
|
|
607
|
+
//#endregion
|
|
608
|
+
//#region src/cache/cache.memory-adapter.d.ts
|
|
609
|
+
/**
|
|
610
|
+
* 内存缓存适配器(Strategy M)
|
|
611
|
+
*
|
|
612
|
+
* 使用 Map 存储缓存条目,无外部依赖,适用于轻量级场景
|
|
613
|
+
*/
|
|
614
|
+
declare class CacheMemoryAdapter implements CachePort {
|
|
615
|
+
/** 内存存储 */
|
|
616
|
+
private readonly store;
|
|
617
|
+
/** 构造函数 */
|
|
618
|
+
constructor();
|
|
619
|
+
/** 根据请求哈希获取缓存条目 */
|
|
620
|
+
getByHash(requestHash: string): Promise<Result<CacheEntryResponseDTO | null, DomainError>>;
|
|
621
|
+
/** 创建缓存条目 */
|
|
622
|
+
create(input: CreateCacheEntryRequestDTO): Promise<Result<CacheEntryResponseDTO, DomainError>>;
|
|
623
|
+
/** 记录缓存命中 */
|
|
624
|
+
recordHit(id: string): Promise<Result<CacheEntryResponseDTO, DomainError>>;
|
|
625
|
+
/** 删除缓存条目 */
|
|
626
|
+
delete(id: string): Promise<Result<boolean, DomainError>>;
|
|
627
|
+
/** 清理过期缓存 */
|
|
628
|
+
deleteExpired(): Promise<Result<number, DomainError>>;
|
|
629
|
+
}
|
|
630
|
+
//#endregion
|
|
631
|
+
//#region src/cache/cache.sqlite-adapter.d.ts
|
|
632
|
+
/**
|
|
633
|
+
* 创建 SQLite 缓存端口适配器(Strategy L)
|
|
634
|
+
*
|
|
635
|
+
* 封装 DrizzleCacheRepository → UseCase 组合 → CachePortAdapter 链路
|
|
636
|
+
*
|
|
637
|
+
* @param db - Drizzle 数据库实例
|
|
638
|
+
* @param schema - 数据库 Schema 对象(需包含 cacheEntries 表)
|
|
639
|
+
* @returns CachePort 实例
|
|
640
|
+
*/
|
|
641
|
+
declare function createCacheSqliteAdapter(db: any, schema: any): CachePort;
|
|
642
|
+
//#endregion
|
|
643
|
+
//#region src/ports/event-publisher.port.d.ts
|
|
644
|
+
/**
|
|
645
|
+
* 事件订阅者类型
|
|
646
|
+
*
|
|
647
|
+
* 接收领域事件的回调函数。
|
|
648
|
+
*
|
|
649
|
+
* @param event - 领域事件
|
|
650
|
+
*/
|
|
651
|
+
type EventSubscriber = (event: DomainEvent) => void;
|
|
652
|
+
/**
|
|
653
|
+
* 事件发布端口接口
|
|
654
|
+
*
|
|
655
|
+
* 所有领域事件发布的统一入口,
|
|
656
|
+
* 支持发布/订阅/取消订阅操作。
|
|
657
|
+
*/
|
|
658
|
+
type EventPublisherPort = {
|
|
659
|
+
/**
|
|
660
|
+
* 发布领域事件
|
|
661
|
+
*
|
|
662
|
+
* @param event - 要发布的领域事件
|
|
663
|
+
*/
|
|
664
|
+
publish(event: DomainEvent): void;
|
|
665
|
+
/**
|
|
666
|
+
* 订阅领域事件
|
|
667
|
+
*
|
|
668
|
+
* @param eventType - 事件类型标识
|
|
669
|
+
* @param subscriber - 事件订阅者回调
|
|
670
|
+
*/
|
|
671
|
+
subscribe(eventType: string, subscriber: EventSubscriber): void;
|
|
672
|
+
/**
|
|
673
|
+
* 取消订阅领域事件
|
|
674
|
+
*
|
|
675
|
+
* @param eventType - 事件类型标识
|
|
676
|
+
* @param subscriber - 要移除的订阅者回调
|
|
677
|
+
*/
|
|
678
|
+
unsubscribe(eventType: string, subscriber: EventSubscriber): void;
|
|
679
|
+
};
|
|
680
|
+
/**
|
|
681
|
+
* 事件发布端口 DI 令牌
|
|
682
|
+
*/
|
|
683
|
+
declare const EVENT_PUBLISHER_PORT_TOKEN: unique symbol;
|
|
684
|
+
//#endregion
|
|
685
|
+
export { CACHE_PORT_TOKEN, CacheEntryEntity, CacheEntryMapper, CacheEntryOrmMapper, type CacheEntryResponseDTO, type CacheEntryRow, CacheError, CacheHitEvent, CacheMemoryAdapter, type CachePolicy, type CachePort, type CacheRepository, type ChatChoice, type ChatChunkDelta, type ChatCompletionChunk, type ChatCompletionRequest, type ChatCompletionResponse, type ChatMessage, type ChatStreamChoice, CleanupCacheEntriesUseCase, type CompletionChoice, type CompletionRequest, type CompletionResponse, type CreateCacheEntryInput, type CreateCacheEntryRequestDTO, CreateCacheEntryUseCase, DEFAULT_EXECUTION_STRATEGY, DEFAULT_FALLBACK_STRATEGY, DEFAULT_RETRY_STRATEGY, DEFAULT_TIMEOUT_STRATEGY, DeleteCacheEntryUseCase, DrizzleCacheRepository, ERROR_STATUS_MAP, EVENT_PUBLISHER_PORT_TOKEN, type EmbeddingData, type EmbeddingRequest, type EmbeddingResponse, type ErrorCategory, ErrorCode, type EventPublisherPort, type EventSubscriber, type ExecutionStrategy, type FallbackAction, type FallbackStrategy, type FunctionDefinition, type GatewayError, type GatewayErrorDetail, type GatewayExtension, GetCacheEntryUseCase, type MessageContentPart, type MessageContentType, type MessageRole, type ModelInfo, type ModelListResponse, type ModelPricing, RecordCacheHitUseCase, type ResponseFormat, type ResponseMessage, type RetryStrategy, type RoutingExtension, type TimeoutStrategy, type TokenUsage, type ToolCall, type ToolCallFunction, type ToolDefinition, budgetUsagePercent, calculateCost, createCacheEntrySchema, createCacheSqliteAdapter, decrypt, encrypt, estimateMessagesTokens, estimateTokens, formatCost };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{z as e}from"zod";import{DomainError as t}from"@longzai-intelligence/error";import{DomainEvent as n,Entity as r,failure as i,success as a}from"@longzai-intelligence/shared-kernel";import{eq as o,lt as s}from"drizzle-orm";let c=function(e){return e.INVALID_REQUEST=`invalid_request`,e.AUTHENTICATION_FAILED=`authentication_failed`,e.PERMISSION_DENIED=`permission_denied`,e.MODEL_NOT_FOUND=`model_not_found`,e.BUDGET_EXCEEDED=`budget_exceeded`,e.RATE_LIMIT_EXCEEDED=`rate_limit_exceeded`,e.INVALID_API_KEY=`invalid_api_key`,e.INTERNAL_ERROR=`internal_error`,e.ROUTING_ERROR=`routing_error`,e.DATABASE_ERROR=`database_error`,e.CACHE_ERROR=`cache_error`,e.PROVIDER_UNAVAILABLE=`provider_unavailable`,e.PROVIDER_RATE_LIMITED=`provider_rate_limited`,e.PROVIDER_TIMEOUT=`provider_timeout`,e.PROVIDER_ERROR=`provider_error`,e.MODEL_OVERLOADED=`model_overloaded`,e.CONTEXT_LENGTH_EXCEEDED=`context_length_exceeded`,e}({});const l={client:400,server:500,provider:502},u={maxRetries:3,initialInterval:1e3,maxInterval:3e4,multiplier:2,retryableStatusCodes:[429,500,502,503,504],retryableErrorCodes:[`provider_timeout`,`provider_unavailable`,`model_overloaded`]},d={connectTimeout:1e4,readTimeout:6e4,writeTimeout:1e4,requestTimeout:12e4},f={actions:[`fallback_model`,`cache_result`,`reject`],fallbackModels:[],allowCache:!0,maxFallbacks:2},p={retry:u,timeout:d,fallback:f};function m(e,t,n){let r=t/1e3*e.inputPrice,i=n/1e3*e.outputPrice;return Number((r+i).toFixed(8))}function h(e){return e<.01?`$${e.toFixed(6)}`:e<1?`$${e.toFixed(4)}`:`$${e.toFixed(2)}`}function g(e,t){return t<=0?0:Math.min(100,Number((e/t*100).toFixed(2)))}const _=`AES-GCM`;function v(e){let t=``;for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}function y(e){let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}async function b(e){let t=new TextEncoder,n=await crypto.subtle.importKey(`raw`,t.encode(e),{name:`PBKDF2`},!1,[`deriveKey`]);return crypto.subtle.deriveKey({name:`PBKDF2`,salt:t.encode(`model-gateway-salt`),iterations:1e5,hash:`SHA-256`},n,{name:_,length:256},!1,[`encrypt`,`decrypt`])}async function x(e,t){let n=await b(t),r=new TextEncoder,i=crypto.getRandomValues(new Uint8Array(12)),a=await crypto.subtle.encrypt({name:_,iv:i,tagLength:128},n,r.encode(e)),o=new Uint8Array(i.length+new Uint8Array(a).length);return o.set(i),o.set(new Uint8Array(a),i.length),v(o)}async function S(e,t){let n=await b(t),r=y(e),i=r.slice(0,12),a=r.slice(12),o=await crypto.subtle.decrypt({name:_,iv:i,tagLength:128},n,a);return new TextDecoder().decode(o)}function C(e){if(!e)return 0;let t=0,n=0;for(let r of e)/[\u4e00-\u9fff\u3400-\u4dbf]/.test(r)?t++:n++;return Math.ceil(t/1.5+n/4)}function w(e){let t=0;for(let n of e)if(t+=4,typeof n.content==`string`)t+=C(n.content);else if(Array.isArray(n.content))for(let e of n.content)e&&typeof e==`object`&&`text`in e&&typeof e.text==`string`&&(t+=C(e.text));return t}const T=Symbol(`CachePort`),E=e.object({requestHash:e.string().min(1),requestVector:e.string().optional(),responseData:e.string().min(1),modelId:e.string().min(1),similarityThreshold:e.number().min(0).max(1).optional(),ttlSeconds:e.number().min(0).optional()});var D=class extends t{constructor(e){super(e,`CACHE_ERROR`),this.name=`CacheError`}},O=class e extends n{cacheEntryId;modelId;static TYPE=`cache:hit`;type=e.TYPE;constructor(e,t,n){super(e),this.cacheEntryId=t,this.modelId=n}},k=class e extends r{get requestHash(){return this._props.requestHash}get requestVector(){return this._props.requestVector}get responseData(){return this._props.responseData}get modelId(){return this._props.modelId}get similarityThreshold(){return this._props.similarityThreshold}get hitCount(){return this._props.hitCount}get expiresAt(){return this._props.expiresAt}get createdAt(){return this._props.createdAt}constructor(e,t){super(e,t)}static create(t,n){let r=new Date,i=(n.ttlSeconds??3600)*1e3,a=n.expiresAt??new Date(r.getTime()+i).toISOString();return new e(t,{requestHash:n.requestHash,requestVector:n.requestVector,responseData:n.responseData,modelId:n.modelId,similarityThreshold:n.similarityThreshold,hitCount:0,expiresAt:a,createdAt:r.toISOString()})}static reconstitute(t,n){return new e(t,n)}recordHit(){this.updateProps(`hitCount`,this._props.hitCount+1)}isExpired(){return new Date(this._props.expiresAt)<new Date}};const A={toDTO(e){return{id:e.id,requestHash:e.requestHash,requestVector:e.requestVector,responseData:e.responseData,modelId:e.modelId,similarityThreshold:e.similarityThreshold,hitCount:e.hitCount,expiresAt:e.expiresAt,createdAt:e.createdAt}},toDTOList(e){return e.map(e=>this.toDTO(e))}},j={toDomain(e){return k.reconstitute(e.id,{requestHash:e.requestHash,requestVector:e.requestVector,responseData:e.responseData,modelId:e.modelId,similarityThreshold:e.similarityThreshold,hitCount:e.hitCount,expiresAt:e.expiresAt,createdAt:e.createdAt})},toOrm(e){return{id:e.id,requestHash:e.requestHash,requestVector:e.requestVector,responseData:e.responseData,modelId:e.modelId,similarityThreshold:e.similarityThreshold,hitCount:e.hitCount,expiresAt:e.expiresAt,createdAt:e.createdAt}}};var M=class{db;schema;constructor(e,t){this.db=e,this.schema=t}async getByHash(e){try{let t=(await this.db.select().from(this.schema.cacheEntries).where(o(this.schema.cacheEntries.requestHash,e)))[0]??null;return a(t?j.toDomain(t):null)}catch(e){return i(new D(`查询缓存条目失败: ${e.message}`))}}async create(e){try{let t=j.toOrm(e);return await this.db.insert(this.schema.cacheEntries).values(t),a(e)}catch(e){return i(new D(`创建缓存条目失败: ${e.message}`))}}async recordHit(e){try{let t=(await this.db.select().from(this.schema.cacheEntries).where(o(this.schema.cacheEntries.id,e)))[0];if(!t)return i(new D(`缓存条目不存在: ${e}`));let n=j.toDomain(t);return n.recordHit(),await this.db.update(this.schema.cacheEntries).set({hitCount:n.hitCount}).where(o(this.schema.cacheEntries.id,e)),a(n)}catch(e){return i(new D(`记录缓存命中失败: ${e.message}`))}}async delete(e){try{return await this.db.delete(this.schema.cacheEntries).where(o(this.schema.cacheEntries.id,e)),a(!0)}catch(e){return i(new D(`删除缓存条目失败: ${e.message}`))}}async deleteExpired(){try{let e=new Date().toISOString();return a((await this.db.delete(this.schema.cacheEntries).where(s(this.schema.cacheEntries.expiresAt,e)))?.changes??0)}catch(e){return i(new D(`清理过期缓存失败: ${e.message}`))}}},N=class{repository;constructor(e){this.repository=e}async execute(e){let t=await this.repository.getByHash(e);if(t.isFailure)return t;let n=t.value;if(!n)return a(null);if(n.isExpired())return await this.repository.delete(n.id),a(null);let r=await this.repository.recordHit(n.id);return r.isFailure?r:a(r.value)}},P=class{repository;constructor(e){this.repository=e}async execute(e){try{let t=`cache_${Date.now()}_${Math.random().toString(36).substring(2,9)}`,n=k.create(t,{requestHash:e.requestHash,requestVector:e.requestVector??null,responseData:e.responseData,modelId:e.modelId,similarityThreshold:e.similarityThreshold??.95,ttlSeconds:e.ttlSeconds,expiresAt:new Date(Date.now()+(e.ttlSeconds??3600)*1e3).toISOString()});return this.repository.create(n)}catch(e){return i(new D(`创建缓存条目失败: ${e.message}`))}}},F=class{repository;constructor(e){this.repository=e}async execute(e){return this.repository.recordHit(e)}},I=class{repository;constructor(e){this.repository=e}async execute(e){return this.repository.delete(e)}},L=class{repository;constructor(e){this.repository=e}async execute(){return this.repository.deleteExpired()}},R=class{store=new Map;constructor(){}async getByHash(e){try{for(let t of this.store.values())if(t.requestHash===e)return t.isExpired()?(this.store.delete(t.id),a(null)):(t.recordHit(),a(A.toDTO(t)));return a(null)}catch(e){return i(new D(`内存缓存查询失败: ${e.message}`))}}async create(e){try{let t=`cache_${Date.now()}_${Math.random().toString(36).substring(2,9)}`,n=k.create(t,{requestHash:e.requestHash,requestVector:e.requestVector??null,responseData:e.responseData,modelId:e.modelId,similarityThreshold:e.similarityThreshold??.95,ttlSeconds:e.ttlSeconds,expiresAt:new Date(Date.now()+(e.ttlSeconds??3600)*1e3).toISOString()});return this.store.set(t,n),a(A.toDTO(n))}catch(e){return i(new D(`内存缓存创建失败: ${e.message}`))}}async recordHit(e){try{let t=this.store.get(e);return t?(t.recordHit(),a(A.toDTO(t))):i(new D(`缓存条目不存在: ${e}`))}catch(e){return i(new D(`内存缓存命中记录失败: ${e.message}`))}}async delete(e){try{return a(this.store.delete(e))}catch(e){return i(new D(`内存缓存删除失败: ${e.message}`))}}async deleteExpired(){try{let e=0;for(let[t,n]of this.store.entries())n.isExpired()&&(this.store.delete(t),e++);return a(e)}catch(e){return i(new D(`内存缓存清理失败: ${e.message}`))}}},z=class{getCacheEntry;createCacheEntry;recordCacheHit;deleteCacheEntry;cleanupCacheEntries;constructor(e){this.getCacheEntry=new N(e),this.createCacheEntry=new P(e),this.recordCacheHit=new F(e),this.deleteCacheEntry=new I(e),this.cleanupCacheEntries=new L(e)}async getByHash(e){let t=await this.getCacheEntry.execute(e);if(t.isFailure)return t;let n=t.value;return a(n?A.toDTO(n):null)}async create(e){let t=await this.createCacheEntry.execute(e);return t.isFailure?t:a(A.toDTO(t.value))}async recordHit(e){let t=await this.recordCacheHit.execute(e);return t.isFailure?t:a(A.toDTO(t.value))}async delete(e){return this.deleteCacheEntry.execute(e)}async deleteExpired(){return this.cleanupCacheEntries.execute()}};function B(e,t){return new z(new M(e,t))}const V=Symbol(`EVENT_PUBLISHER_PORT_TOKEN`);export{T as CACHE_PORT_TOKEN,k as CacheEntryEntity,A as CacheEntryMapper,j as CacheEntryOrmMapper,D as CacheError,O as CacheHitEvent,R as CacheMemoryAdapter,L as CleanupCacheEntriesUseCase,P as CreateCacheEntryUseCase,p as DEFAULT_EXECUTION_STRATEGY,f as DEFAULT_FALLBACK_STRATEGY,u as DEFAULT_RETRY_STRATEGY,d as DEFAULT_TIMEOUT_STRATEGY,I as DeleteCacheEntryUseCase,M as DrizzleCacheRepository,l as ERROR_STATUS_MAP,V as EVENT_PUBLISHER_PORT_TOKEN,c as ErrorCode,N as GetCacheEntryUseCase,F as RecordCacheHitUseCase,g as budgetUsagePercent,m as calculateCost,E as createCacheEntrySchema,B as createCacheSqliteAdapter,S as decrypt,x as encrypt,w as estimateMessagesTokens,C as estimateTokens,h as formatCost};
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@longzai-intelligence-model-gateway/core",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Core types and utilities for Model Gateway - AI model routing, rate limiting, and observability",
|
|
5
|
+
"private": false,
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"main": "./dist/index.mjs",
|
|
12
|
+
"types": "./dist/index.d.mts",
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"access": "public"
|
|
15
|
+
},
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.mts",
|
|
19
|
+
"import": "./dist/index.mjs"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsgo --build tsconfig/build.json && resolve-aliases -p tsconfig/build.json",
|
|
24
|
+
"build:prod": "NODE_ENV=production tsdown",
|
|
25
|
+
"prepublishOnly": "bun run build:prod",
|
|
26
|
+
"typecheck": "bun run typecheck:app && bun run typecheck:node && bun run typecheck:test",
|
|
27
|
+
"typecheck:app": "tsgo --noEmit -p tsconfig/app.json",
|
|
28
|
+
"typecheck:node": "tsgo --noEmit -p tsconfig/node.json",
|
|
29
|
+
"typecheck:test": "tsgo --noEmit -p tsconfig/test.json",
|
|
30
|
+
"lint": "oxlint && oxfmt --check",
|
|
31
|
+
"lint:fix": "oxlint --fix && oxfmt",
|
|
32
|
+
"test": "bun test",
|
|
33
|
+
"test:watch": "bun test --watch",
|
|
34
|
+
"test:coverage": "bun test --coverage",
|
|
35
|
+
"clean": "rm -rf dist"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@longzai-intelligence/shared-kernel": "^0.1.4",
|
|
39
|
+
"@longzai-intelligence/error": "^0.0.5",
|
|
40
|
+
"drizzle-orm": "^0.38.0",
|
|
41
|
+
"zod": "^4.4.3"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {}
|
|
44
|
+
}
|