@zhin.js/agent 0.0.1 → 0.0.3
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/CHANGELOG.md +17 -0
- package/lib/agent.d.ts +4 -129
- package/lib/agent.d.ts.map +1 -1
- package/lib/agent.js +3 -733
- package/lib/agent.js.map +1 -1
- package/lib/compaction.d.ts +3 -129
- package/lib/compaction.d.ts.map +1 -1
- package/lib/compaction.js +2 -367
- package/lib/compaction.js.map +1 -1
- package/lib/context-manager.d.ts +3 -210
- package/lib/context-manager.d.ts.map +1 -1
- package/lib/context-manager.js +2 -310
- package/lib/context-manager.js.map +1 -1
- package/lib/conversation-memory.d.ts +3 -189
- package/lib/conversation-memory.d.ts.map +1 -1
- package/lib/conversation-memory.js +2 -616
- package/lib/conversation-memory.js.map +1 -1
- package/lib/init/create-zhin-agent.d.ts.map +1 -1
- package/lib/init/create-zhin-agent.js +1 -3
- package/lib/init/create-zhin-agent.js.map +1 -1
- package/lib/init/register-management-tools.js +3 -3
- package/lib/output.d.ts +3 -90
- package/lib/output.d.ts.map +1 -1
- package/lib/output.js +2 -173
- package/lib/output.js.map +1 -1
- package/lib/rate-limiter.d.ts +3 -35
- package/lib/rate-limiter.d.ts.map +1 -1
- package/lib/rate-limiter.js +2 -83
- package/lib/rate-limiter.js.map +1 -1
- package/lib/session.d.ts +3 -190
- package/lib/session.d.ts.map +1 -1
- package/lib/session.js +2 -462
- package/lib/session.js.map +1 -1
- package/lib/storage.d.ts +3 -65
- package/lib/storage.d.ts.map +1 -1
- package/lib/storage.js +2 -102
- package/lib/storage.js.map +1 -1
- package/lib/tone-detector.d.ts +3 -16
- package/lib/tone-detector.d.ts.map +1 -1
- package/lib/tone-detector.js +2 -69
- package/lib/tone-detector.js.map +1 -1
- package/package.json +3 -2
- package/src/agent.ts +4 -852
- package/src/compaction.ts +27 -528
- package/src/context-manager.ts +14 -439
- package/src/conversation-memory.ts +3 -814
- package/src/init/create-zhin-agent.ts +1 -3
- package/src/init/register-management-tools.ts +3 -3
- package/src/output.ts +14 -260
- package/src/rate-limiter.ts +3 -127
- package/src/session.ts +12 -565
- package/src/storage.ts +8 -134
- package/src/tone-detector.ts +3 -87
- package/tests/ai/setup.ts +20 -84
- package/tests/ai/agent.test.ts +0 -565
- package/tests/ai/context-manager.test.ts +0 -413
- package/tests/ai/conversation-memory.test.ts +0 -128
- package/tests/ai/output.test.ts +0 -128
- package/tests/ai/rate-limiter.test.ts +0 -108
- package/tests/ai/session.test.ts +0 -334
- package/tests/ai/tone-detector.test.ts +0 -80
|
@@ -88,7 +88,7 @@ export function createZhinAgentContext(refs) {
|
|
|
88
88
|
cronEngine.load();
|
|
89
89
|
setCronManager({ cronFeature, engine: cronEngine });
|
|
90
90
|
}
|
|
91
|
-
// Unified scheduler (at/every/cron
|
|
91
|
+
// Unified scheduler (at/every/cron)
|
|
92
92
|
const dataDir = path.join(process.cwd(), 'data');
|
|
93
93
|
const scheduler = new Scheduler({
|
|
94
94
|
storePath: path.join(dataDir, 'scheduler-jobs.json'),
|
|
@@ -102,8 +102,6 @@ export function createZhinAgentContext(refs) {
|
|
|
102
102
|
sceneId: 'scheduler',
|
|
103
103
|
});
|
|
104
104
|
},
|
|
105
|
-
heartbeatEnabled: true,
|
|
106
|
-
heartbeatIntervalMs: 30 * 60 * 1000,
|
|
107
105
|
});
|
|
108
106
|
setScheduler(scheduler);
|
|
109
107
|
scheduler.start().catch((e) => logger.warn('Scheduler start failed: ' + e.message));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-zhin-agent.js","sourceRoot":"","sources":["../../src/init/create-zhin-agent.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"create-zhin-agent.js","sourceRoot":"","sources":["../../src/init/create-zhin-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ export function registerManagementTools() {
|
|
|
10
10
|
useContext('ai', 'tool', (ai, toolService) => {
|
|
11
11
|
if (!ai || !toolService)
|
|
12
12
|
return;
|
|
13
|
-
const listModelsTool = new ZhinTool('
|
|
13
|
+
const listModelsTool = new ZhinTool('ai_models')
|
|
14
14
|
.desc('列出所有可用的 AI 模型')
|
|
15
15
|
.keyword('模型', '可用模型', 'ai模型', 'model', 'models')
|
|
16
16
|
.tag('ai', 'management')
|
|
@@ -28,7 +28,7 @@ export function registerManagementTools() {
|
|
|
28
28
|
}
|
|
29
29
|
return r;
|
|
30
30
|
});
|
|
31
|
-
const clearSessionTool = new ZhinTool('
|
|
31
|
+
const clearSessionTool = new ZhinTool('ai_clear')
|
|
32
32
|
.desc('清除当前对话的历史记录')
|
|
33
33
|
.keyword('清除', '清空', '重置', 'clear', 'reset')
|
|
34
34
|
.tag('ai', 'session')
|
|
@@ -45,7 +45,7 @@ export function registerManagementTools() {
|
|
|
45
45
|
await ai.sessions.reset(sid);
|
|
46
46
|
return '✅ 对话历史已清除';
|
|
47
47
|
});
|
|
48
|
-
const healthCheckTool = new ZhinTool('
|
|
48
|
+
const healthCheckTool = new ZhinTool('ai_health')
|
|
49
49
|
.desc('检查 AI 服务的健康状态')
|
|
50
50
|
.keyword('健康', '状态', '检查', 'health', 'status')
|
|
51
51
|
.tag('ai', 'management')
|
package/lib/output.d.ts
CHANGED
|
@@ -1,93 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @zhin.js/ai
|
|
3
|
-
*
|
|
4
|
-
* 统一输出类型系统:AI 回复 → OutputElement[] → Adapter 渲染
|
|
5
|
-
*
|
|
6
|
-
* 支持的输出类型:
|
|
7
|
-
* - text: 纯文本 / markdown
|
|
8
|
-
* - image: 图片 URL 或 base64
|
|
9
|
-
* - audio: 音频 URL 或 base64
|
|
10
|
-
* - video: 视频 URL
|
|
11
|
-
* - card: 结构化卡片 (标题 + 正文 + 字段 + 按钮)
|
|
12
|
-
* - file: 文件附件
|
|
2
|
+
* Re-export from @zhin.js/ai for backward compatibility.
|
|
13
3
|
*/
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
content: string;
|
|
17
|
-
/** markdown / plain */
|
|
18
|
-
format?: 'markdown' | 'plain';
|
|
19
|
-
}
|
|
20
|
-
export interface ImageElement {
|
|
21
|
-
type: 'image';
|
|
22
|
-
url: string;
|
|
23
|
-
/** base64 数据 (url 不可用时的后备) */
|
|
24
|
-
base64?: string;
|
|
25
|
-
alt?: string;
|
|
26
|
-
width?: number;
|
|
27
|
-
height?: number;
|
|
28
|
-
}
|
|
29
|
-
export interface AudioElement {
|
|
30
|
-
type: 'audio';
|
|
31
|
-
url: string;
|
|
32
|
-
base64?: string;
|
|
33
|
-
duration?: number;
|
|
34
|
-
/** 语音转文字的后备文本 */
|
|
35
|
-
fallbackText?: string;
|
|
36
|
-
}
|
|
37
|
-
export interface VideoElement {
|
|
38
|
-
type: 'video';
|
|
39
|
-
url: string;
|
|
40
|
-
coverUrl?: string;
|
|
41
|
-
duration?: number;
|
|
42
|
-
fallbackText?: string;
|
|
43
|
-
}
|
|
44
|
-
export interface CardField {
|
|
45
|
-
label: string;
|
|
46
|
-
value: string;
|
|
47
|
-
inline?: boolean;
|
|
48
|
-
}
|
|
49
|
-
export interface CardButton {
|
|
50
|
-
text: string;
|
|
51
|
-
/** 点击后发送的命令 */
|
|
52
|
-
command?: string;
|
|
53
|
-
/** 点击后打开的 URL */
|
|
54
|
-
url?: string;
|
|
55
|
-
}
|
|
56
|
-
export interface CardElement {
|
|
57
|
-
type: 'card';
|
|
58
|
-
title: string;
|
|
59
|
-
description?: string;
|
|
60
|
-
fields?: CardField[];
|
|
61
|
-
imageUrl?: string;
|
|
62
|
-
buttons?: CardButton[];
|
|
63
|
-
color?: string;
|
|
64
|
-
}
|
|
65
|
-
export interface FileElement {
|
|
66
|
-
type: 'file';
|
|
67
|
-
url: string;
|
|
68
|
-
name: string;
|
|
69
|
-
size?: number;
|
|
70
|
-
mimeType?: string;
|
|
71
|
-
}
|
|
72
|
-
export type OutputElement = TextElement | ImageElement | AudioElement | VideoElement | CardElement | FileElement;
|
|
73
|
-
/**
|
|
74
|
-
* 从 AI 回复文本中解析出结构化的 OutputElement[]
|
|
75
|
-
*
|
|
76
|
-
* 识别规则:
|
|
77
|
-
* -  → ImageElement
|
|
78
|
-
* - [audio](url) → AudioElement
|
|
79
|
-
* - [video](url) → VideoElement
|
|
80
|
-
* - ```card ... ``` → CardElement (JSON)
|
|
81
|
-
* - [file:name](url) → FileElement
|
|
82
|
-
* - 其余文本 → TextElement
|
|
83
|
-
*/
|
|
84
|
-
export declare function parseOutput(raw: string): OutputElement[];
|
|
85
|
-
/**
|
|
86
|
-
* 将 OutputElement[] 降级为纯文本(用于不支持富媒体的平台)
|
|
87
|
-
*/
|
|
88
|
-
export declare function renderToPlainText(elements: OutputElement[]): string;
|
|
89
|
-
/**
|
|
90
|
-
* 将 OutputElement[] 渲染为 Satori 兼容的 HTML 片段
|
|
91
|
-
*/
|
|
92
|
-
export declare function renderToSatori(elements: OutputElement[]): string;
|
|
4
|
+
export { parseOutput, renderToPlainText, renderToSatori } from '@zhin.js/ai';
|
|
5
|
+
export type { TextElement, ImageElement, AudioElement, VideoElement, CardField, CardButton, CardElement, FileElement, OutputElement, } from '@zhin.js/ai';
|
|
93
6
|
//# sourceMappingURL=output.d.ts.map
|
package/lib/output.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7E,YAAY,EACV,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,UAAU,EACV,WAAW,EACX,WAAW,EACX,aAAa,GACd,MAAM,aAAa,CAAC"}
|
package/lib/output.js
CHANGED
|
@@ -1,176 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @zhin.js/ai
|
|
3
|
-
*
|
|
4
|
-
* 统一输出类型系统:AI 回复 → OutputElement[] → Adapter 渲染
|
|
5
|
-
*
|
|
6
|
-
* 支持的输出类型:
|
|
7
|
-
* - text: 纯文本 / markdown
|
|
8
|
-
* - image: 图片 URL 或 base64
|
|
9
|
-
* - audio: 音频 URL 或 base64
|
|
10
|
-
* - video: 视频 URL
|
|
11
|
-
* - card: 结构化卡片 (标题 + 正文 + 字段 + 按钮)
|
|
12
|
-
* - file: 文件附件
|
|
2
|
+
* Re-export from @zhin.js/ai for backward compatibility.
|
|
13
3
|
*/
|
|
14
|
-
|
|
15
|
-
// 输出解析器 — 将 AI 原始回复转换为 OutputElement[]
|
|
16
|
-
// ============================================================================
|
|
17
|
-
/**
|
|
18
|
-
* 从 AI 回复文本中解析出结构化的 OutputElement[]
|
|
19
|
-
*
|
|
20
|
-
* 识别规则:
|
|
21
|
-
* -  → ImageElement
|
|
22
|
-
* - [audio](url) → AudioElement
|
|
23
|
-
* - [video](url) → VideoElement
|
|
24
|
-
* - ```card ... ``` → CardElement (JSON)
|
|
25
|
-
* - [file:name](url) → FileElement
|
|
26
|
-
* - 其余文本 → TextElement
|
|
27
|
-
*/
|
|
28
|
-
export function parseOutput(raw) {
|
|
29
|
-
if (!raw || !raw.trim())
|
|
30
|
-
return [{ type: 'text', content: '', format: 'plain' }];
|
|
31
|
-
const elements = [];
|
|
32
|
-
let remaining = raw;
|
|
33
|
-
// eslint-disable-next-line no-constant-condition
|
|
34
|
-
while (remaining.length > 0) {
|
|
35
|
-
// ── 尝试匹配 card 代码块 ──
|
|
36
|
-
const cardMatch = remaining.match(/^([\s\S]*?)```card\s*\n([\s\S]*?)```/);
|
|
37
|
-
if (cardMatch) {
|
|
38
|
-
// 前缀文本
|
|
39
|
-
if (cardMatch[1].trim()) {
|
|
40
|
-
elements.push({ type: 'text', content: cardMatch[1].trim(), format: 'markdown' });
|
|
41
|
-
}
|
|
42
|
-
// 解析卡片 JSON
|
|
43
|
-
try {
|
|
44
|
-
const cardData = JSON.parse(cardMatch[2]);
|
|
45
|
-
elements.push({ ...cardData, type: 'card' });
|
|
46
|
-
}
|
|
47
|
-
catch {
|
|
48
|
-
elements.push({ type: 'text', content: cardMatch[2], format: 'plain' });
|
|
49
|
-
}
|
|
50
|
-
remaining = remaining.slice(cardMatch[0].length);
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
// ── 尝试匹配 image:  ──
|
|
54
|
-
const imgMatch = remaining.match(/^([\s\S]*?)!\[([^\]]*)\]\(([^)]+)\)/);
|
|
55
|
-
if (imgMatch && imgMatch[1].length < 500) {
|
|
56
|
-
if (imgMatch[1].trim()) {
|
|
57
|
-
elements.push({ type: 'text', content: imgMatch[1].trim(), format: 'markdown' });
|
|
58
|
-
}
|
|
59
|
-
elements.push({ type: 'image', url: imgMatch[3], alt: imgMatch[2] || undefined });
|
|
60
|
-
remaining = remaining.slice(imgMatch[0].length);
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
// ── 尝试匹配 audio: [audio](url) ──
|
|
64
|
-
const audioMatch = remaining.match(/^([\s\S]*?)\[audio\]\(([^)]+)\)/i);
|
|
65
|
-
if (audioMatch && audioMatch[1].length < 500) {
|
|
66
|
-
if (audioMatch[1].trim()) {
|
|
67
|
-
elements.push({ type: 'text', content: audioMatch[1].trim(), format: 'markdown' });
|
|
68
|
-
}
|
|
69
|
-
elements.push({ type: 'audio', url: audioMatch[2] });
|
|
70
|
-
remaining = remaining.slice(audioMatch[0].length);
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
// ── 尝试匹配 video: [video](url) ──
|
|
74
|
-
const videoMatch = remaining.match(/^([\s\S]*?)\[video\]\(([^)]+)\)/i);
|
|
75
|
-
if (videoMatch && videoMatch[1].length < 500) {
|
|
76
|
-
if (videoMatch[1].trim()) {
|
|
77
|
-
elements.push({ type: 'text', content: videoMatch[1].trim(), format: 'markdown' });
|
|
78
|
-
}
|
|
79
|
-
elements.push({ type: 'video', url: videoMatch[2] });
|
|
80
|
-
remaining = remaining.slice(videoMatch[0].length);
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
// ── 尝试匹配 file: [file:name](url) ──
|
|
84
|
-
const fileMatch = remaining.match(/^([\s\S]*?)\[file:([^\]]+)\]\(([^)]+)\)/i);
|
|
85
|
-
if (fileMatch && fileMatch[1].length < 500) {
|
|
86
|
-
if (fileMatch[1].trim()) {
|
|
87
|
-
elements.push({ type: 'text', content: fileMatch[1].trim(), format: 'markdown' });
|
|
88
|
-
}
|
|
89
|
-
elements.push({ type: 'file', url: fileMatch[3], name: fileMatch[2] });
|
|
90
|
-
remaining = remaining.slice(fileMatch[0].length);
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
// ── 无匹配 → 全部作为文本 ──
|
|
94
|
-
elements.push({ type: 'text', content: remaining.trim(), format: 'markdown' });
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
return elements.length > 0 ? elements : [{ type: 'text', content: raw, format: 'plain' }];
|
|
98
|
-
}
|
|
99
|
-
// ============================================================================
|
|
100
|
-
// OutputElement 渲染工具
|
|
101
|
-
// ============================================================================
|
|
102
|
-
/**
|
|
103
|
-
* 将 OutputElement[] 降级为纯文本(用于不支持富媒体的平台)
|
|
104
|
-
*/
|
|
105
|
-
export function renderToPlainText(elements) {
|
|
106
|
-
return elements.map(el => {
|
|
107
|
-
switch (el.type) {
|
|
108
|
-
case 'text':
|
|
109
|
-
return el.content;
|
|
110
|
-
case 'image':
|
|
111
|
-
return el.alt ? `[图片: ${el.alt}]` : `[图片: ${el.url}]`;
|
|
112
|
-
case 'audio':
|
|
113
|
-
return el.fallbackText || `[音频: ${el.url}]`;
|
|
114
|
-
case 'video':
|
|
115
|
-
return el.fallbackText || `[视频: ${el.url}]`;
|
|
116
|
-
case 'card': {
|
|
117
|
-
const parts = [el.title];
|
|
118
|
-
if (el.description)
|
|
119
|
-
parts.push(el.description);
|
|
120
|
-
if (el.fields?.length) {
|
|
121
|
-
for (const f of el.fields)
|
|
122
|
-
parts.push(`${f.label}: ${f.value}`);
|
|
123
|
-
}
|
|
124
|
-
return parts.join('\n');
|
|
125
|
-
}
|
|
126
|
-
case 'file':
|
|
127
|
-
return `[文件: ${el.name}] ${el.url}`;
|
|
128
|
-
default:
|
|
129
|
-
return '';
|
|
130
|
-
}
|
|
131
|
-
}).filter(Boolean).join('\n');
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* 将 OutputElement[] 渲染为 Satori 兼容的 HTML 片段
|
|
135
|
-
*/
|
|
136
|
-
export function renderToSatori(elements) {
|
|
137
|
-
return elements.map(el => {
|
|
138
|
-
switch (el.type) {
|
|
139
|
-
case 'text':
|
|
140
|
-
return `<p>${escapeHtml(el.content)}</p>`;
|
|
141
|
-
case 'image':
|
|
142
|
-
return `<img src="${escapeHtml(el.url)}"${el.alt ? ` alt="${escapeHtml(el.alt)}"` : ''}/>`;
|
|
143
|
-
case 'audio':
|
|
144
|
-
return el.fallbackText
|
|
145
|
-
? `<p>${escapeHtml(el.fallbackText)}</p>`
|
|
146
|
-
: `<audio src="${escapeHtml(el.url)}"/>`;
|
|
147
|
-
case 'video':
|
|
148
|
-
return el.fallbackText
|
|
149
|
-
? `<p>${escapeHtml(el.fallbackText)}</p>`
|
|
150
|
-
: `<video src="${escapeHtml(el.url)}"/>`;
|
|
151
|
-
case 'card': {
|
|
152
|
-
let html = `<div class="card">`;
|
|
153
|
-
html += `<h3>${escapeHtml(el.title)}</h3>`;
|
|
154
|
-
if (el.description)
|
|
155
|
-
html += `<p>${escapeHtml(el.description)}</p>`;
|
|
156
|
-
if (el.imageUrl)
|
|
157
|
-
html += `<img src="${escapeHtml(el.imageUrl)}"/>`;
|
|
158
|
-
if (el.fields?.length) {
|
|
159
|
-
for (const f of el.fields) {
|
|
160
|
-
html += `<p><b>${escapeHtml(f.label)}</b>: ${escapeHtml(f.value)}</p>`;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
html += `</div>`;
|
|
164
|
-
return html;
|
|
165
|
-
}
|
|
166
|
-
case 'file':
|
|
167
|
-
return `<a href="${escapeHtml(el.url)}">${escapeHtml(el.name)}</a>`;
|
|
168
|
-
default:
|
|
169
|
-
return '';
|
|
170
|
-
}
|
|
171
|
-
}).filter(Boolean).join('\n');
|
|
172
|
-
}
|
|
173
|
-
function escapeHtml(s) {
|
|
174
|
-
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
175
|
-
}
|
|
4
|
+
export { parseOutput, renderToPlainText, renderToSatori } from '@zhin.js/ai';
|
|
176
5
|
//# sourceMappingURL=output.js.map
|
package/lib/output.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
package/lib/rate-limiter.d.ts
CHANGED
|
@@ -1,38 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* 防止单用户过度消耗 GPU/API 资源。
|
|
5
|
-
*
|
|
6
|
-
* 策略:
|
|
7
|
-
* 1. 滑动窗口速率限制 — 每分钟 N 次请求
|
|
8
|
-
* 2. 优雅降级 — 超限时返回友好提示而非静默丢弃
|
|
2
|
+
* Re-export from @zhin.js/ai for backward compatibility.
|
|
9
3
|
*/
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
maxRequestsPerMinute?: number;
|
|
13
|
-
/** 冷却时间(秒),超限后需等待(默认 10) */
|
|
14
|
-
cooldownSeconds?: number;
|
|
15
|
-
}
|
|
16
|
-
export interface RateLimitResult {
|
|
17
|
-
allowed: boolean;
|
|
18
|
-
/** 如果被拒绝,返回友好提示 */
|
|
19
|
-
message?: string;
|
|
20
|
-
/** 需等待的秒数 */
|
|
21
|
-
retryAfterSeconds?: number;
|
|
22
|
-
}
|
|
23
|
-
export declare class RateLimiter {
|
|
24
|
-
private config;
|
|
25
|
-
private buckets;
|
|
26
|
-
private cleanupTimer?;
|
|
27
|
-
constructor(config?: RateLimitConfig);
|
|
28
|
-
/**
|
|
29
|
-
* 检查请求是否被允许
|
|
30
|
-
*/
|
|
31
|
-
check(userId: string): RateLimitResult;
|
|
32
|
-
/**
|
|
33
|
-
* 清理长期不活跃的 bucket
|
|
34
|
-
*/
|
|
35
|
-
private cleanup;
|
|
36
|
-
dispose(): void;
|
|
37
|
-
}
|
|
4
|
+
export { RateLimiter } from '@zhin.js/ai';
|
|
5
|
+
export type { RateLimitConfig, RateLimitResult } from '@zhin.js/ai';
|
|
38
6
|
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
package/lib/rate-limiter.js
CHANGED
|
@@ -1,86 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* 防止单用户过度消耗 GPU/API 资源。
|
|
5
|
-
*
|
|
6
|
-
* 策略:
|
|
7
|
-
* 1. 滑动窗口速率限制 — 每分钟 N 次请求
|
|
8
|
-
* 2. 优雅降级 — 超限时返回友好提示而非静默丢弃
|
|
2
|
+
* Re-export from @zhin.js/ai for backward compatibility.
|
|
9
3
|
*/
|
|
10
|
-
|
|
11
|
-
const logger = new Logger(null, 'RateLimiter');
|
|
12
|
-
const DEFAULTS = {
|
|
13
|
-
maxRequestsPerMinute: 20,
|
|
14
|
-
cooldownSeconds: 10,
|
|
15
|
-
};
|
|
16
|
-
// ============================================================================
|
|
17
|
-
// RateLimiter
|
|
18
|
-
// ============================================================================
|
|
19
|
-
export class RateLimiter {
|
|
20
|
-
config;
|
|
21
|
-
buckets = new Map();
|
|
22
|
-
cleanupTimer;
|
|
23
|
-
constructor(config) {
|
|
24
|
-
this.config = { ...DEFAULTS, ...config };
|
|
25
|
-
// 定期清理过期的 bucket(每 5 分钟)
|
|
26
|
-
this.cleanupTimer = setInterval(() => this.cleanup(), 5 * 60 * 1000);
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* 检查请求是否被允许
|
|
30
|
-
*/
|
|
31
|
-
check(userId) {
|
|
32
|
-
const now = Date.now();
|
|
33
|
-
let bucket = this.buckets.get(userId);
|
|
34
|
-
if (!bucket) {
|
|
35
|
-
bucket = { timestamps: [], cooldownUntil: 0 };
|
|
36
|
-
this.buckets.set(userId, bucket);
|
|
37
|
-
}
|
|
38
|
-
// 1. 检查冷却期
|
|
39
|
-
if (bucket.cooldownUntil > now) {
|
|
40
|
-
const waitSec = Math.ceil((bucket.cooldownUntil - now) / 1000);
|
|
41
|
-
return {
|
|
42
|
-
allowed: false,
|
|
43
|
-
message: `请稍等 ${waitSec} 秒后再发消息哦~消息太频繁啦 😊`,
|
|
44
|
-
retryAfterSeconds: waitSec,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
// 2. 滑动窗口:清理 1 分钟前的时间戳
|
|
48
|
-
const windowStart = now - 60_000;
|
|
49
|
-
bucket.timestamps = bucket.timestamps.filter(t => t > windowStart);
|
|
50
|
-
// 3. 检查速率
|
|
51
|
-
if (bucket.timestamps.length >= this.config.maxRequestsPerMinute) {
|
|
52
|
-
bucket.cooldownUntil = now + this.config.cooldownSeconds * 1000;
|
|
53
|
-
const waitSec = this.config.cooldownSeconds;
|
|
54
|
-
logger.warn(`User ${userId} rate limited: ${bucket.timestamps.length} requests in 1 min`);
|
|
55
|
-
return {
|
|
56
|
-
allowed: false,
|
|
57
|
-
message: `你发消息太快啦,请等 ${waitSec} 秒后再试~`,
|
|
58
|
-
retryAfterSeconds: waitSec,
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
// 4. 记录这次请求
|
|
62
|
-
bucket.timestamps.push(now);
|
|
63
|
-
return { allowed: true };
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* 清理长期不活跃的 bucket
|
|
67
|
-
*/
|
|
68
|
-
cleanup() {
|
|
69
|
-
const now = Date.now();
|
|
70
|
-
const staleThreshold = 10 * 60 * 1000; // 10 分钟
|
|
71
|
-
for (const [userId, bucket] of this.buckets) {
|
|
72
|
-
const latest = bucket.timestamps[bucket.timestamps.length - 1] ?? 0;
|
|
73
|
-
if (now - latest > staleThreshold && bucket.cooldownUntil < now) {
|
|
74
|
-
this.buckets.delete(userId);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
dispose() {
|
|
79
|
-
if (this.cleanupTimer) {
|
|
80
|
-
clearInterval(this.cleanupTimer);
|
|
81
|
-
this.cleanupTimer = undefined;
|
|
82
|
-
}
|
|
83
|
-
this.buckets.clear();
|
|
84
|
-
}
|
|
85
|
-
}
|
|
4
|
+
export { RateLimiter } from '@zhin.js/ai';
|
|
86
5
|
//# sourceMappingURL=rate-limiter.js.map
|
package/lib/rate-limiter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
|