@zhin.js/core 1.0.25 → 1.0.26
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 +10 -0
- package/README.md +84 -342
- package/lib/adapter.d.ts +17 -0
- package/lib/adapter.d.ts.map +1 -1
- package/lib/adapter.js +84 -2
- package/lib/adapter.js.map +1 -1
- package/lib/ai/agent.d.ts +126 -0
- package/lib/ai/agent.d.ts.map +1 -0
- package/lib/ai/agent.js +645 -0
- package/lib/ai/agent.js.map +1 -0
- package/lib/ai/context-manager.d.ts +213 -0
- package/lib/ai/context-manager.d.ts.map +1 -0
- package/lib/ai/context-manager.js +313 -0
- package/lib/ai/context-manager.js.map +1 -0
- package/lib/ai/conversation-memory.d.ts +181 -0
- package/lib/ai/conversation-memory.d.ts.map +1 -0
- package/lib/ai/conversation-memory.js +581 -0
- package/lib/ai/conversation-memory.js.map +1 -0
- package/lib/ai/follow-up.d.ts +131 -0
- package/lib/ai/follow-up.d.ts.map +1 -0
- package/lib/ai/follow-up.js +265 -0
- package/lib/ai/follow-up.js.map +1 -0
- package/lib/ai/index.d.ts +29 -0
- package/lib/ai/index.d.ts.map +1 -0
- package/lib/ai/index.js +34 -0
- package/lib/ai/index.js.map +1 -0
- package/lib/ai/init.d.ts +30 -0
- package/lib/ai/init.d.ts.map +1 -0
- package/lib/ai/init.js +424 -0
- package/lib/ai/init.js.map +1 -0
- package/lib/ai/output.d.ts +93 -0
- package/lib/ai/output.d.ts.map +1 -0
- package/lib/ai/output.js +176 -0
- package/lib/ai/output.js.map +1 -0
- package/lib/ai/providers/anthropic.d.ts +23 -0
- package/lib/ai/providers/anthropic.d.ts.map +1 -0
- package/lib/ai/providers/anthropic.js +322 -0
- package/lib/ai/providers/anthropic.js.map +1 -0
- package/lib/ai/providers/base.d.ts +43 -0
- package/lib/ai/providers/base.d.ts.map +1 -0
- package/lib/ai/providers/base.js +135 -0
- package/lib/ai/providers/base.js.map +1 -0
- package/lib/ai/providers/index.d.ts +12 -0
- package/lib/ai/providers/index.d.ts.map +1 -0
- package/lib/ai/providers/index.js +9 -0
- package/lib/ai/providers/index.js.map +1 -0
- package/lib/ai/providers/ollama.d.ts +25 -0
- package/lib/ai/providers/ollama.d.ts.map +1 -0
- package/lib/ai/providers/ollama.js +243 -0
- package/lib/ai/providers/ollama.js.map +1 -0
- package/lib/ai/providers/openai.d.ts +46 -0
- package/lib/ai/providers/openai.d.ts.map +1 -0
- package/lib/ai/providers/openai.js +132 -0
- package/lib/ai/providers/openai.js.map +1 -0
- package/lib/ai/rate-limiter.d.ts +38 -0
- package/lib/ai/rate-limiter.d.ts.map +1 -0
- package/lib/ai/rate-limiter.js +86 -0
- package/lib/ai/rate-limiter.js.map +1 -0
- package/lib/ai/service.d.ts +81 -0
- package/lib/ai/service.d.ts.map +1 -0
- package/lib/ai/service.js +274 -0
- package/lib/ai/service.js.map +1 -0
- package/lib/ai/session.d.ts +186 -0
- package/lib/ai/session.d.ts.map +1 -0
- package/lib/ai/session.js +443 -0
- package/lib/ai/session.js.map +1 -0
- package/lib/ai/tone-detector.d.ts +19 -0
- package/lib/ai/tone-detector.d.ts.map +1 -0
- package/lib/ai/tone-detector.js +72 -0
- package/lib/ai/tone-detector.js.map +1 -0
- package/lib/ai/tools.d.ts +45 -0
- package/lib/ai/tools.d.ts.map +1 -0
- package/lib/ai/tools.js +206 -0
- package/lib/ai/tools.js.map +1 -0
- package/lib/ai/types.d.ts +264 -0
- package/lib/ai/types.d.ts.map +1 -0
- package/lib/ai/types.js +6 -0
- package/lib/ai/types.js.map +1 -0
- package/lib/ai/user-profile.d.ts +56 -0
- package/lib/ai/user-profile.d.ts.map +1 -0
- package/lib/ai/user-profile.js +130 -0
- package/lib/ai/user-profile.js.map +1 -0
- package/lib/ai/zhin-agent.d.ts +165 -0
- package/lib/ai/zhin-agent.d.ts.map +1 -0
- package/lib/ai/zhin-agent.js +707 -0
- package/lib/ai/zhin-agent.js.map +1 -0
- package/lib/built/ai-trigger.d.ts.map +1 -1
- package/lib/built/ai-trigger.js +7 -3
- package/lib/built/ai-trigger.js.map +1 -1
- package/lib/built/command.d.ts +33 -17
- package/lib/built/command.d.ts.map +1 -1
- package/lib/built/command.js +71 -44
- package/lib/built/command.js.map +1 -1
- package/lib/built/component.d.ts +42 -15
- package/lib/built/component.d.ts.map +1 -1
- package/lib/built/component.js +84 -52
- package/lib/built/component.js.map +1 -1
- package/lib/built/config.d.ts +54 -5
- package/lib/built/config.d.ts.map +1 -1
- package/lib/built/config.js +76 -10
- package/lib/built/config.js.map +1 -1
- package/lib/built/cron.d.ts +41 -18
- package/lib/built/cron.d.ts.map +1 -1
- package/lib/built/cron.js +106 -63
- package/lib/built/cron.js.map +1 -1
- package/lib/built/database.d.ts +55 -6
- package/lib/built/database.d.ts.map +1 -1
- package/lib/built/database.js +93 -22
- package/lib/built/database.js.map +1 -1
- package/lib/built/dispatcher.d.ts +118 -0
- package/lib/built/dispatcher.d.ts.map +1 -0
- package/lib/built/dispatcher.js +196 -0
- package/lib/built/dispatcher.js.map +1 -0
- package/lib/built/permission.d.ts +45 -5
- package/lib/built/permission.d.ts.map +1 -1
- package/lib/built/permission.js +56 -11
- package/lib/built/permission.js.map +1 -1
- package/lib/built/skill.d.ts +117 -0
- package/lib/built/skill.d.ts.map +1 -0
- package/lib/built/skill.js +191 -0
- package/lib/built/skill.js.map +1 -0
- package/lib/built/tool.d.ts +71 -164
- package/lib/built/tool.d.ts.map +1 -1
- package/lib/built/tool.js +212 -297
- package/lib/built/tool.js.map +1 -1
- package/lib/feature.d.ts +75 -0
- package/lib/feature.d.ts.map +1 -0
- package/lib/feature.js +69 -0
- package/lib/feature.js.map +1 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +7 -0
- package/lib/index.js.map +1 -1
- package/lib/plugin.d.ts +25 -17
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +180 -20
- package/lib/plugin.js.map +1 -1
- package/lib/types.d.ts +4 -9
- package/lib/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/adapter.ts +101 -2
- package/src/ai/agent.ts +772 -0
- package/src/ai/context-manager.ts +440 -0
- package/src/ai/conversation-memory.ts +774 -0
- package/src/ai/follow-up.ts +357 -0
- package/src/ai/index.ts +128 -0
- package/src/ai/init.ts +502 -0
- package/src/ai/output.ts +261 -0
- package/src/ai/providers/anthropic.ts +375 -0
- package/src/ai/providers/base.ts +173 -0
- package/src/ai/providers/index.ts +13 -0
- package/src/ai/providers/ollama.ts +292 -0
- package/src/ai/providers/openai.ts +167 -0
- package/src/ai/rate-limiter.ts +129 -0
- package/src/ai/service.ts +319 -0
- package/src/ai/session.ts +544 -0
- package/src/ai/tone-detector.ts +89 -0
- package/src/ai/tools.ts +218 -0
- package/src/ai/types.ts +296 -0
- package/src/ai/user-profile.ts +181 -0
- package/src/ai/zhin-agent.ts +845 -0
- package/src/built/ai-trigger.ts +6 -3
- package/src/built/command.ts +75 -69
- package/src/built/component.ts +94 -76
- package/src/built/config.ts +238 -128
- package/src/built/cron.ts +117 -101
- package/src/built/database.ts +128 -33
- package/src/built/dispatcher.ts +332 -0
- package/src/built/permission.ts +146 -54
- package/src/built/skill.ts +280 -0
- package/src/built/tool.ts +245 -366
- package/src/feature.ts +113 -0
- package/src/index.ts +7 -0
- package/src/plugin.ts +198 -33
- package/src/types.ts +6 -10
- package/tests/adapter.test.ts +153 -1
- package/tests/ai/agent.test.ts +614 -0
- package/tests/ai/ai-trigger.test.ts +368 -0
- package/tests/ai/context-manager.test.ts +413 -0
- package/tests/ai/conversation-memory.test.ts +128 -0
- package/tests/ai/follow-up.test.ts +175 -0
- package/tests/ai/integration.test.ts +584 -0
- package/tests/ai/output.test.ts +128 -0
- package/tests/ai/providers.integration.test.ts +227 -0
- package/tests/ai/rate-limiter.test.ts +108 -0
- package/tests/ai/session.test.ts +375 -0
- package/tests/ai/setup.ts +308 -0
- package/tests/ai/tone-detector.test.ts +80 -0
- package/tests/ai/tool.test.ts +800 -0
- package/tests/ai/tools-builtin.test.ts +346 -0
- package/tests/ai/user-profile.test.ts +73 -0
- package/tests/ai/zhin-agent.test.ts +177 -0
- package/tests/config.test.ts +46 -0
- package/tests/cron.test.ts +94 -5
- package/tests/dispatcher.test.ts +146 -0
- package/tests/feature.test.ts +145 -0
- package/tests/features-builtin.test.ts +191 -0
- package/tests/plugin.test.ts +88 -14
- package/tests/skill-feature.test.ts +179 -0
- package/tests/tool-feature.test.ts +254 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UserProfileStore — 用户画像存储
|
|
3
|
+
*
|
|
4
|
+
* 持久化存储用户偏好和特征,让 AI 跨会话记住用户的个性化信息。
|
|
5
|
+
*
|
|
6
|
+
* ai_user_profiles 表:
|
|
7
|
+
* ┌──────────────────────────────────────────────────────────┐
|
|
8
|
+
* │ user_id | key | value | updated_at │
|
|
9
|
+
* │ u1 | name | 小明 | 1700000000 │
|
|
10
|
+
* │ u1 | style | 简洁正式 | 1700000001 │
|
|
11
|
+
* │ u1 | interests | 编程,天气 | 1700000010 │
|
|
12
|
+
* └──────────────────────────────────────────────────────────┘
|
|
13
|
+
*/
|
|
14
|
+
export declare const AI_USER_PROFILE_MODEL: {
|
|
15
|
+
user_id: {
|
|
16
|
+
type: "text";
|
|
17
|
+
nullable: boolean;
|
|
18
|
+
};
|
|
19
|
+
key: {
|
|
20
|
+
type: "text";
|
|
21
|
+
nullable: boolean;
|
|
22
|
+
};
|
|
23
|
+
value: {
|
|
24
|
+
type: "text";
|
|
25
|
+
nullable: boolean;
|
|
26
|
+
};
|
|
27
|
+
updated_at: {
|
|
28
|
+
type: "integer";
|
|
29
|
+
default: number;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* 数据库模型接口(与 RelatedModel 的链式查询 API 对齐)
|
|
34
|
+
*/
|
|
35
|
+
interface DbModel {
|
|
36
|
+
select(...fields: string[]): any;
|
|
37
|
+
create(data: Record<string, any>): Promise<any>;
|
|
38
|
+
update(data: Partial<any>): any;
|
|
39
|
+
delete(condition: Record<string, any>): any;
|
|
40
|
+
}
|
|
41
|
+
export declare class UserProfileStore {
|
|
42
|
+
private store;
|
|
43
|
+
constructor();
|
|
44
|
+
upgradeToDatabase(model: DbModel): void;
|
|
45
|
+
get(userId: string, key: string): Promise<string | null>;
|
|
46
|
+
getAll(userId: string): Promise<Record<string, string>>;
|
|
47
|
+
set(userId: string, key: string, value: string): Promise<void>;
|
|
48
|
+
delete(userId: string, key: string): Promise<boolean>;
|
|
49
|
+
/**
|
|
50
|
+
* 构建用户画像摘要,注入 system prompt
|
|
51
|
+
*/
|
|
52
|
+
buildProfileSummary(userId: string): Promise<string>;
|
|
53
|
+
dispose(): void;
|
|
54
|
+
}
|
|
55
|
+
export {};
|
|
56
|
+
//# sourceMappingURL=user-profile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-profile.d.ts","sourceRoot":"","sources":["../../src/ai/user-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAUH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;CAKjC,CAAC;AAcF;;GAEG;AACH,UAAU,OAAO;IACf,MAAM,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;IACjC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IAChC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC;CAC7C;AAsFD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAgB;;IAM7B,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAOjC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIxD,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAIvD,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3D;;OAEG;IACG,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAS1D,OAAO,IAAI,IAAI;CAGhB"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UserProfileStore — 用户画像存储
|
|
3
|
+
*
|
|
4
|
+
* 持久化存储用户偏好和特征,让 AI 跨会话记住用户的个性化信息。
|
|
5
|
+
*
|
|
6
|
+
* ai_user_profiles 表:
|
|
7
|
+
* ┌──────────────────────────────────────────────────────────┐
|
|
8
|
+
* │ user_id | key | value | updated_at │
|
|
9
|
+
* │ u1 | name | 小明 | 1700000000 │
|
|
10
|
+
* │ u1 | style | 简洁正式 | 1700000001 │
|
|
11
|
+
* │ u1 | interests | 编程,天气 | 1700000010 │
|
|
12
|
+
* └──────────────────────────────────────────────────────────┘
|
|
13
|
+
*/
|
|
14
|
+
import { Logger } from '@zhin.js/logger';
|
|
15
|
+
const logger = new Logger(null, 'UserProfile');
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// 数据库模型
|
|
18
|
+
// ============================================================================
|
|
19
|
+
export const AI_USER_PROFILE_MODEL = {
|
|
20
|
+
user_id: { type: 'text', nullable: false },
|
|
21
|
+
key: { type: 'text', nullable: false },
|
|
22
|
+
value: { type: 'text', nullable: false },
|
|
23
|
+
updated_at: { type: 'integer', default: 0 },
|
|
24
|
+
};
|
|
25
|
+
// ============================================================================
|
|
26
|
+
// 内存实现
|
|
27
|
+
// ============================================================================
|
|
28
|
+
class MemoryProfileStore {
|
|
29
|
+
data = new Map();
|
|
30
|
+
async get(userId, key) {
|
|
31
|
+
return this.data.get(userId)?.get(key) ?? null;
|
|
32
|
+
}
|
|
33
|
+
async getAll(userId) {
|
|
34
|
+
const map = this.data.get(userId);
|
|
35
|
+
if (!map)
|
|
36
|
+
return {};
|
|
37
|
+
return Object.fromEntries(map);
|
|
38
|
+
}
|
|
39
|
+
async set(userId, key, value) {
|
|
40
|
+
let map = this.data.get(userId);
|
|
41
|
+
if (!map) {
|
|
42
|
+
map = new Map();
|
|
43
|
+
this.data.set(userId, map);
|
|
44
|
+
}
|
|
45
|
+
map.set(key, value);
|
|
46
|
+
}
|
|
47
|
+
async delete(userId, key) {
|
|
48
|
+
return this.data.get(userId)?.delete(key) ?? false;
|
|
49
|
+
}
|
|
50
|
+
dispose() { this.data.clear(); }
|
|
51
|
+
}
|
|
52
|
+
// ============================================================================
|
|
53
|
+
// 数据库实现
|
|
54
|
+
// ============================================================================
|
|
55
|
+
class DatabaseProfileStore {
|
|
56
|
+
model;
|
|
57
|
+
constructor(model) {
|
|
58
|
+
this.model = model;
|
|
59
|
+
}
|
|
60
|
+
async get(userId, key) {
|
|
61
|
+
const records = await this.model.select().where({ user_id: userId, key });
|
|
62
|
+
return records.length > 0 ? records[0].value : null;
|
|
63
|
+
}
|
|
64
|
+
async getAll(userId) {
|
|
65
|
+
const records = await this.model.select().where({ user_id: userId });
|
|
66
|
+
const result = {};
|
|
67
|
+
for (const r of records)
|
|
68
|
+
result[r.key] = r.value;
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
async set(userId, key, value) {
|
|
72
|
+
const existing = await this.model.select().where({ user_id: userId, key });
|
|
73
|
+
if (existing.length > 0) {
|
|
74
|
+
await this.model.update({ value, updated_at: Date.now() }).where({ user_id: userId, key });
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
await this.model.create({ user_id: userId, key, value, updated_at: Date.now() });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async delete(userId, key) {
|
|
81
|
+
const existing = await this.model.select().where({ user_id: userId, key });
|
|
82
|
+
if (existing.length === 0)
|
|
83
|
+
return false;
|
|
84
|
+
await this.model.delete({ user_id: userId, key });
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
dispose() { }
|
|
88
|
+
}
|
|
89
|
+
// ============================================================================
|
|
90
|
+
// UserProfileStore
|
|
91
|
+
// ============================================================================
|
|
92
|
+
export class UserProfileStore {
|
|
93
|
+
store;
|
|
94
|
+
constructor() {
|
|
95
|
+
this.store = new MemoryProfileStore();
|
|
96
|
+
}
|
|
97
|
+
upgradeToDatabase(model) {
|
|
98
|
+
const old = this.store;
|
|
99
|
+
this.store = new DatabaseProfileStore(model);
|
|
100
|
+
old.dispose();
|
|
101
|
+
logger.debug('UserProfileStore: upgraded to database storage');
|
|
102
|
+
}
|
|
103
|
+
async get(userId, key) {
|
|
104
|
+
return this.store.get(userId, key);
|
|
105
|
+
}
|
|
106
|
+
async getAll(userId) {
|
|
107
|
+
return this.store.getAll(userId);
|
|
108
|
+
}
|
|
109
|
+
async set(userId, key, value) {
|
|
110
|
+
return this.store.set(userId, key, value);
|
|
111
|
+
}
|
|
112
|
+
async delete(userId, key) {
|
|
113
|
+
return this.store.delete(userId, key);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* 构建用户画像摘要,注入 system prompt
|
|
117
|
+
*/
|
|
118
|
+
async buildProfileSummary(userId) {
|
|
119
|
+
const profile = await this.store.getAll(userId);
|
|
120
|
+
const entries = Object.entries(profile);
|
|
121
|
+
if (entries.length === 0)
|
|
122
|
+
return '';
|
|
123
|
+
const lines = entries.map(([k, v]) => `- ${k}: ${v}`).join('\n');
|
|
124
|
+
return `[用户画像]\n${lines}`;
|
|
125
|
+
}
|
|
126
|
+
dispose() {
|
|
127
|
+
this.store.dispose();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=user-profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-profile.js","sourceRoot":"","sources":["../../src/ai/user-profile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZhinAgent — 全局持久 AI 大脑
|
|
3
|
+
*
|
|
4
|
+
* 取代旧的 AIService.process() 临时创建 Agent 的方式。
|
|
5
|
+
*
|
|
6
|
+
* 核心能力:
|
|
7
|
+
* 1. 全局单例,应用生命周期内常驻
|
|
8
|
+
* 2. Skill 感知:两级过滤 Skill → Tool
|
|
9
|
+
* 3. 双层记忆:per-scene(对话上下文)+ per-user(长期偏好)
|
|
10
|
+
* 4. 任务规划:复杂请求自动分解为子步骤
|
|
11
|
+
* 5. 多模态输出:结构化 OutputElement[]
|
|
12
|
+
* 6. 智能路径选择:纯闲聊走轻量路径,工具请求走完整路径
|
|
13
|
+
* 7. 用户画像:跨会话个性化记忆
|
|
14
|
+
* 8. 速率限制:防止单用户过度消耗资源
|
|
15
|
+
* 9. 流式输出:onChunk 回调实时推送部分文本
|
|
16
|
+
* 10. 情绪感知:根据用户语气调整回复风格
|
|
17
|
+
* 11. 主动跟进:schedule_followup 定时回查
|
|
18
|
+
* 12. 多模态输入:图片/音频直接传给视觉模型
|
|
19
|
+
*/
|
|
20
|
+
import type { Tool, ToolContext } from '../types.js';
|
|
21
|
+
import type { SkillFeature } from '../built/skill.js';
|
|
22
|
+
import type { AIProvider, AgentTool, ContentPart } from './types.js';
|
|
23
|
+
import { SessionManager } from './session.js';
|
|
24
|
+
import type { ContextManager } from './context-manager.js';
|
|
25
|
+
import type { OutputElement } from './output.js';
|
|
26
|
+
import { UserProfileStore } from './user-profile.js';
|
|
27
|
+
import { type RateLimitConfig } from './rate-limiter.js';
|
|
28
|
+
import { type FollowUpSender } from './follow-up.js';
|
|
29
|
+
export interface ZhinAgentConfig {
|
|
30
|
+
/** 默认系统人格 */
|
|
31
|
+
persona?: string;
|
|
32
|
+
/** 最大工具调用轮数 */
|
|
33
|
+
maxIterations?: number;
|
|
34
|
+
/** 单次请求超时 (ms) */
|
|
35
|
+
timeout?: number;
|
|
36
|
+
/** 预执行超时 (ms) */
|
|
37
|
+
preExecTimeout?: number;
|
|
38
|
+
/** Skill 选择最大数量 */
|
|
39
|
+
maxSkills?: number;
|
|
40
|
+
/** Tool 选择最大数量 */
|
|
41
|
+
maxTools?: number;
|
|
42
|
+
/** 一个话题至少持续多少轮才触发摘要(默认 5) */
|
|
43
|
+
minTopicRounds?: number;
|
|
44
|
+
/** 滑动窗口大小:最近 N 轮消息(默认 5) */
|
|
45
|
+
slidingWindowSize?: number;
|
|
46
|
+
/** 话题切换检测阈值(0-1,值越低越敏感,默认 0.15) */
|
|
47
|
+
topicChangeThreshold?: number;
|
|
48
|
+
/** 速率限制配置 */
|
|
49
|
+
rateLimit?: RateLimitConfig;
|
|
50
|
+
/** 是否启用情绪感知(默认 true) */
|
|
51
|
+
toneAwareness?: boolean;
|
|
52
|
+
/** 视觉模型名称(如 llava, bakllava),留空则不启用视觉 */
|
|
53
|
+
visionModel?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 流式输出回调 — 适配器可通过此回调实时更新消息
|
|
57
|
+
*
|
|
58
|
+
* @param chunk 增量文本片段
|
|
59
|
+
* @param full 到目前为止的完整文本
|
|
60
|
+
*/
|
|
61
|
+
export type OnChunkCallback = (chunk: string, full: string) => void;
|
|
62
|
+
export declare class ZhinAgent {
|
|
63
|
+
private provider;
|
|
64
|
+
private config;
|
|
65
|
+
private skillRegistry;
|
|
66
|
+
private sessions;
|
|
67
|
+
private contextManager;
|
|
68
|
+
private memory;
|
|
69
|
+
private externalTools;
|
|
70
|
+
private userProfiles;
|
|
71
|
+
private rateLimiter;
|
|
72
|
+
private followUps;
|
|
73
|
+
constructor(provider: AIProvider, config?: ZhinAgentConfig);
|
|
74
|
+
setSkillRegistry(registry: SkillFeature): void;
|
|
75
|
+
setSessionManager(manager: SessionManager): void;
|
|
76
|
+
setContextManager(manager: ContextManager): void;
|
|
77
|
+
/** 将 ConversationMemory 升级为数据库存储 */
|
|
78
|
+
upgradeMemoryToDatabase(msgModel: any, sumModel: any): void;
|
|
79
|
+
/** 将 UserProfileStore 升级为数据库存储 */
|
|
80
|
+
upgradeProfilesToDatabase(model: any): void;
|
|
81
|
+
/** 将 FollowUpManager 升级为数据库存储 */
|
|
82
|
+
upgradeFollowUpsToDatabase(model: any): void;
|
|
83
|
+
/** 注入提醒消息发送回调(由 init.ts 在适配器就绪后调用) */
|
|
84
|
+
setFollowUpSender(sender: FollowUpSender): void;
|
|
85
|
+
/**
|
|
86
|
+
* 从数据库恢复未完成的跟进任务(启动时调用)
|
|
87
|
+
* @returns 恢复的任务数量
|
|
88
|
+
*/
|
|
89
|
+
restoreFollowUps(): Promise<number>;
|
|
90
|
+
/** 获取 UserProfileStore(用于外部注册) */
|
|
91
|
+
getUserProfiles(): UserProfileStore;
|
|
92
|
+
registerTool(tool: AgentTool): () => void;
|
|
93
|
+
/**
|
|
94
|
+
* 处理用户消息 — 唯一的公开入口
|
|
95
|
+
*
|
|
96
|
+
* @param content 用户消息文本
|
|
97
|
+
* @param context 工具上下文(平台、发送者、权限等)
|
|
98
|
+
* @param externalTools 外部传入的工具列表
|
|
99
|
+
* @param onChunk 流式输出回调(可选,适配器支持时传入)
|
|
100
|
+
*
|
|
101
|
+
* 路径选择策略(按开销从低到高):
|
|
102
|
+
*
|
|
103
|
+
* ┌─ 闲聊路径(最快)────────────────────────────────────────────┐
|
|
104
|
+
* │ 工具过滤 = 0 → 仅 persona prompt → 流式 1 次 LLM 调用 │
|
|
105
|
+
* └──────────────────────────────────────────────────────────────┘
|
|
106
|
+
* ┌─ 快速路径(1 轮 LLM)───────────────────────────────────────┐
|
|
107
|
+
* │ 全部命中无参数工具 → 预执行 → 数据注入 prompt → 1 次 LLM │
|
|
108
|
+
* └──────────────────────────────────────────────────────────────┘
|
|
109
|
+
* ┌─ Agent 路径(多轮 LLM)─────────────────────────────────────┐
|
|
110
|
+
* │ 存在需参数工具 → Agent tool-calling → 多轮 LLM │
|
|
111
|
+
* └──────────────────────────────────────────────────────────────┘
|
|
112
|
+
*/
|
|
113
|
+
process(content: string, context: ToolContext, externalTools?: Tool[], onChunk?: OnChunkCallback): Promise<OutputElement[]>;
|
|
114
|
+
/**
|
|
115
|
+
* 处理多模态消息(图片+文字)
|
|
116
|
+
*
|
|
117
|
+
* 当用户发送图片时,走视觉模型路径。
|
|
118
|
+
*/
|
|
119
|
+
processMultimodal(parts: ContentPart[], context: ToolContext, onChunk?: OnChunkCallback): Promise<OutputElement[]>;
|
|
120
|
+
private buildEnhancedPersona;
|
|
121
|
+
/**
|
|
122
|
+
* 构建上下文提示 — 告诉 AI 当前身份和场景,帮助工具参数填充
|
|
123
|
+
*/
|
|
124
|
+
private buildContextHint;
|
|
125
|
+
private collectTools;
|
|
126
|
+
/**
|
|
127
|
+
* 将 Tool 转为 AgentTool,注入 ToolContext 以确保执行时鉴权生效
|
|
128
|
+
*/
|
|
129
|
+
private toAgentTool;
|
|
130
|
+
/**
|
|
131
|
+
* 构建 Skill 增强的 system prompt(仅在工具路径使用,闲聊不走这里)
|
|
132
|
+
*/
|
|
133
|
+
private buildRichSystemPrompt;
|
|
134
|
+
/**
|
|
135
|
+
* 创建 chat_history 工具 — 让 AI 能主动搜索历史聊天记录
|
|
136
|
+
*/
|
|
137
|
+
private createChatHistoryTool;
|
|
138
|
+
/**
|
|
139
|
+
* 创建 user_profile 工具 — 让 AI 读写用户画像
|
|
140
|
+
*/
|
|
141
|
+
private createUserProfileTool;
|
|
142
|
+
/**
|
|
143
|
+
* 创建 schedule_followup 工具 — 让 AI 主动安排跟进
|
|
144
|
+
*
|
|
145
|
+
* 任务持久化到数据库,机器人重启后自动恢复。
|
|
146
|
+
* 同一会话创建新提醒时,旧的 pending 提醒会被自动取消。
|
|
147
|
+
*/
|
|
148
|
+
private createScheduleFollowUpTool;
|
|
149
|
+
/**
|
|
150
|
+
* 从 ConversationMemory 构建上下文
|
|
151
|
+
*/
|
|
152
|
+
private buildHistoryMessages;
|
|
153
|
+
/**
|
|
154
|
+
* 流式聊天(带历史记忆) — 利用 chatStream 减少 TTFT
|
|
155
|
+
*
|
|
156
|
+
* 新增 onChunk 回调:每收到一个 token 立即通知调用方,
|
|
157
|
+
* 支持适配器(Telegram/Discord/Kook)实时编辑消息。
|
|
158
|
+
*/
|
|
159
|
+
private streamChatWithHistory;
|
|
160
|
+
private saveToSession;
|
|
161
|
+
private fallbackFormat;
|
|
162
|
+
isReady(): boolean;
|
|
163
|
+
dispose(): void;
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=zhin-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zhin-agent.d.ts","sourceRoot":"","sources":["../../src/ai/zhin-agent.ts"],"names":[],"mappings":"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"}
|