@aalis/plugin-user-relation 0.4.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.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/dist/actions.d.ts +13 -0
  3. package/dist/actions.d.ts.map +1 -0
  4. package/dist/actions.js +705 -0
  5. package/dist/actions.js.map +1 -0
  6. package/dist/commands.d.ts +46 -0
  7. package/dist/commands.d.ts.map +1 -0
  8. package/dist/commands.js +601 -0
  9. package/dist/commands.js.map +1 -0
  10. package/dist/consolidate-llm.d.ts +150 -0
  11. package/dist/consolidate-llm.d.ts.map +1 -0
  12. package/dist/consolidate-llm.js +373 -0
  13. package/dist/consolidate-llm.js.map +1 -0
  14. package/dist/extractor.d.ts +308 -0
  15. package/dist/extractor.d.ts.map +1 -0
  16. package/dist/extractor.js +1356 -0
  17. package/dist/extractor.js.map +1 -0
  18. package/dist/index.d.ts +33 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +626 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/middleware.d.ts +41 -0
  23. package/dist/middleware.d.ts.map +1 -0
  24. package/dist/middleware.js +281 -0
  25. package/dist/middleware.js.map +1 -0
  26. package/dist/rename-watcher.d.ts +16 -0
  27. package/dist/rename-watcher.d.ts.map +1 -0
  28. package/dist/rename-watcher.js +16 -0
  29. package/dist/rename-watcher.js.map +1 -0
  30. package/dist/service.d.ts +1108 -0
  31. package/dist/service.d.ts.map +1 -0
  32. package/dist/service.js +4462 -0
  33. package/dist/service.js.map +1 -0
  34. package/dist/store.d.ts +89 -0
  35. package/dist/store.d.ts.map +1 -0
  36. package/dist/store.js +207 -0
  37. package/dist/store.js.map +1 -0
  38. package/dist/tools.d.ts +48 -0
  39. package/dist/tools.d.ts.map +1 -0
  40. package/dist/tools.js +1630 -0
  41. package/dist/tools.js.map +1 -0
  42. package/dist/types.d.ts +432 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +94 -0
  45. package/dist/types.js.map +1 -0
  46. package/dist/utils.d.ts +419 -0
  47. package/dist/utils.d.ts.map +1 -0
  48. package/dist/utils.js +1630 -0
  49. package/dist/utils.js.map +1 -0
  50. package/package.json +57 -0
@@ -0,0 +1,308 @@
1
+ /**
2
+ * RelationExtractor —— 监听对话归档事件,按"消息条数"触发 LLM 提取并写图。
3
+ *
4
+ * 触发模型(与 plugin-user-profile 思路一致,但 scope 为 sessionId 而非 user):
5
+ * - 监听 `inbound:message:archived`
6
+ * - 内存维护 per-sessionId 的累计计数
7
+ * - 累计到 `triggerEveryNMessages`(默认 20)触发一次
8
+ * - 提取时读取最近 `readWindowSize`(默认 30)条 → 窗口与触发步长有意 overlap,
9
+ * 让上一轮窗口尾部 ~10 条与本轮重合,形成"层叠上下文",缓解 LLM
10
+ * 对话题/关系单次识别不稳定的问题
11
+ * - per-sessionId 在飞中标记:同一 session 同时只跑一次提取,避免风暴
12
+ *
13
+ * "all-new" 模式:把读窗口放大到 `allNewMaxMessages`,一次性消化所有累积;
14
+ * 默认不启用(容易超 context window)。
15
+ *
16
+ * LLM 集成:用 `resolveLLMModel(ctx, cfg.extractionModel)` 拿模型 entry;
17
+ * cfg.extractionModel 为空时退化到默认 'llm' service。
18
+ */
19
+ import type { Context } from '@aalis/core';
20
+ import { type ModelRef } from '@aalis/plugin-llm-api';
21
+ import type { RelationService } from './service.js';
22
+ export type ExtractorReadScope = 'same-session' | 'same-platform' | 'cross-platform';
23
+ export interface ExtractorConfig {
24
+ triggerEveryNMessages: number;
25
+ readWindowSize: number;
26
+ mode: 'incremental' | 'all-new';
27
+ allNewMaxMessages: number;
28
+ /**
29
+ * 提取窗口的会话范围:
30
+ * - same-session(默认):仅当前 sessionId(同群聊 / 同私聊)。
31
+ * - same-platform:同 platform 下所有会话合并送 LLM(每条标注 [sid]),用于识别跨群共享事件。
32
+ * - cross-platform:跨所有平台聚合(同上)。
33
+ * 跨会话模式下,evidence.sessionId 按每条消息真实来源记录,event.sessionScope 仍由 LLM 输出(current=来源 session / global=显式跨会话)决定。
34
+ */
35
+ readScope?: ExtractorReadScope;
36
+ /** 跨会话拉取时仅取最近 N 分钟内的消息;0=不限。仅在 readScope!=same-session 时生效。默认 60。 */
37
+ crossSessionMaxAgeMinutes?: number;
38
+ /** 提取时把"最近 N 天的活跃事件"作为候选清单交给 LLM 复用 */
39
+ candidateEventDays: number;
40
+ candidateEventLimit: number;
41
+ /** 提取时,对窗口内每位已知发言人附带其 1 跳邻居子图(已关联的事件/实体/人际关系,按权重降序),上限条数。0=关闭 */
42
+ senderNeighborhoodEdgeLimit: number;
43
+ /** LLM model 引用;为空走默认 'llm' service */
44
+ extractionModel?: ModelRef;
45
+ /** 是否禁用思考模式(思考型模型上)。提取是结构化输出任务,默认禁用以避免 budget 被 reasoning 吃掉 */
46
+ disableThinking: boolean;
47
+ /** 严格自证:每条 person-* 边必须有 evidence 且 evidence.messageId.sender == fromPersonId */
48
+ strictSelfAssertion: boolean;
49
+ /** 自动老化:每次写入完成后扫一遍并按 quota 删除(profile 风格,不开调度器)。默认 true。 */
50
+ evictionEnabled: boolean;
51
+ /** 人物节点总数上限;超过则按 (age/mentionCount/PR) 排序删除老旧低活跃节点。0=不限。 */
52
+ maxPersons: number;
53
+ /** 事件节点总数上限;超过则按 (age/weight) 排序删除老旧低权重节点。0=不限。 */
54
+ maxEvents: number;
55
+ /** 实体节点总数上限。0=不限。 */
56
+ maxEntities: number;
57
+ /** 边总数上限(保留 weight 最高的)。0=不限。 */
58
+ maxEdges: number;
59
+ /** PageRank 阻尼系数,淘汰打分用。默认 0.85 */
60
+ pagerankDamping: number;
61
+ /** PageRank 最大迭代次数。默认 20(图较大时可调大) */
62
+ pagerankIterations: number;
63
+ /** PageRank 收敛阈值(L1 误差),达到即提前停止。默认 1e-4 */
64
+ pagerankEpsilon: number;
65
+ /** 淘汰滞回:count > quota·(1+pct) 才触发;用以避免每写一条都裁。默认 0.2 */
66
+ evictHysteresisPct: number;
67
+ /** 触发后裁到 floor(quota·pct)。默认 0.8,配合 hysteresis=0.2 → 单次清理 ~40% quota */
68
+ evictTargetPct: number;
69
+ /**
70
+ * Weight 时间衰减半衰期(天)。effW = raw × max(0.5^(days/halfLife), floor)。
71
+ * 用于"老高 weight 节点不再被反复强化时自动让出淘汰保护名额"。
72
+ * 0 或负值 = 关闭衰减(行为向后兼容)。默认 180 天。
73
+ */
74
+ weightDecayHalfLifeDays: number;
75
+ /** Weight 衰减下限因子,effW 不会低于 raw × floor。保留"老朋友"底色。默认 0.3 */
76
+ weightDecayFloor: number;
77
+ /**
78
+ * evictByQuota 之后顺手跑的社群发现算法。默认 'louvain'。
79
+ * - 'louvain' / 'leiden':硬划分,每个节点恰好属于一个社群(leiden 额外保证社群内部连通)
80
+ * - 'slpa':Speaker-Listener Label Propagation,原生重叠社区;跨群人物能获得多个社群隶属度
81
+ */
82
+ communityAlgorithm: 'louvain' | 'leiden' | 'slpa';
83
+ /**
84
+ * 淘汰完成后自动运行一次 consolidate(去重/整理/层级推断)。
85
+ * 仅在实际发生淘汰(deletedEvents/Entities/Edges > 0)时触发。默认 true。
86
+ */
87
+ consolidateAfterEviction: boolean;
88
+ /** consolidation 使用的 LLM 模型(可选;为空则退化为纯算法模式) */
89
+ consolidateLLMModelRef?: ModelRef;
90
+ /** consolidation LLM 是否禁用思考模式 */
91
+ consolidateLLMDisableThinking: boolean;
92
+ /** consolidation 是否自动建别名/层级边(对应 consolidate({ autoLink }) 参数) */
93
+ consolidateAutoLink: boolean;
94
+ /** F3:宽召回阶段双方低权 entity 是否跳过 LLM 核验 */
95
+ consolidateSkipLowScorePairs: boolean;
96
+ /** F3:低权阈值(compositeScore < 该值视为低权) */
97
+ consolidateLowScoreThreshold: number;
98
+ /** debug 日志 */
99
+ debug: boolean;
100
+ }
101
+ /**
102
+ * `ExtractorConfig` 的单一默认值真源。
103
+ *
104
+ * 用途:
105
+ * - 测试构造 extractor 时直接 spread,避免每次新增字段都要在多份 fixture 里手补默认值;
106
+ * - `index.ts` apply() 的 `numCfg(config.x, DEFAULT)` 默认值也应优先从此处取(人工同步即可,因为 apply 路径有 string→number 解析需求)。
107
+ *
108
+ * **约束**:必须包含 `ExtractorConfig` 所有必填字段。`satisfies` 在编译期保证遗漏即报错——
109
+ * 给 `ExtractorConfig` 加新必填字段时,TS 会直接拒绝编译,倒逼此处同步,根治"测试 / 运行时
110
+ * 默认值漂移"问题。
111
+ *
112
+ * 可选字段(`?:`)默认留空(运行时按需启用)。
113
+ */
114
+ export declare const EXTRACTOR_CONFIG_DEFAULTS: {
115
+ readonly triggerEveryNMessages: 20;
116
+ readonly readWindowSize: 30;
117
+ readonly mode: "incremental";
118
+ readonly allNewMaxMessages: 200;
119
+ readonly candidateEventDays: 7;
120
+ readonly candidateEventLimit: 20;
121
+ readonly senderNeighborhoodEdgeLimit: 8;
122
+ readonly disableThinking: true;
123
+ readonly strictSelfAssertion: true;
124
+ readonly evictionEnabled: true;
125
+ readonly maxPersons: 1500;
126
+ readonly maxEvents: 2500;
127
+ readonly maxEntities: 1500;
128
+ readonly maxEdges: 10000;
129
+ readonly pagerankDamping: 0.85;
130
+ readonly pagerankIterations: 20;
131
+ readonly pagerankEpsilon: 0.0001;
132
+ readonly evictHysteresisPct: 0.2;
133
+ readonly evictTargetPct: 0.8;
134
+ readonly weightDecayHalfLifeDays: 180;
135
+ readonly weightDecayFloor: 0.3;
136
+ readonly communityAlgorithm: "louvain";
137
+ readonly consolidateAfterEviction: true;
138
+ readonly consolidateLLMDisableThinking: true;
139
+ readonly consolidateAutoLink: false;
140
+ readonly consolidateSkipLowScorePairs: true;
141
+ readonly consolidateLowScoreThreshold: 0.2;
142
+ readonly debug: false;
143
+ };
144
+ interface LLMExtraction {
145
+ persons?: Array<{
146
+ platform: string;
147
+ userId: string;
148
+ displayName?: string;
149
+ }>;
150
+ events?: Array<{
151
+ refKey: string;
152
+ existingEventId?: string | null;
153
+ title: string;
154
+ summary?: string;
155
+ category?: string;
156
+ /** 'current' = 当前会话内事件(默认);'global' = 显式跨会话事件 */
157
+ scope?: string;
158
+ evidence?: {
159
+ messageIds?: string[];
160
+ quote?: string;
161
+ };
162
+ }>;
163
+ entities?: Array<{
164
+ refKey: string;
165
+ existingEntityId?: string | null;
166
+ name: string;
167
+ aliases?: string[];
168
+ summary?: string;
169
+ entityKind?: string;
170
+ evidence?: {
171
+ messageIds?: string[];
172
+ quote?: string;
173
+ };
174
+ }>;
175
+ personEventEdges?: Array<{
176
+ personPlatform: string;
177
+ personUserId: string;
178
+ eventRefKey: string;
179
+ role: string;
180
+ sentiment?: string;
181
+ description?: string;
182
+ evidence?: {
183
+ messageIds?: string[];
184
+ quote?: string;
185
+ };
186
+ }>;
187
+ personEntityEdges?: Array<{
188
+ personPlatform: string;
189
+ personUserId: string;
190
+ entityRefKey: string;
191
+ role: string;
192
+ sentiment?: string;
193
+ description?: string;
194
+ evidence?: {
195
+ messageIds?: string[];
196
+ quote?: string;
197
+ };
198
+ }>;
199
+ personPersonEdges?: Array<{
200
+ fromPlatform: string;
201
+ fromUserId: string;
202
+ toPlatform: string;
203
+ toUserId: string;
204
+ relationType: string;
205
+ directed?: boolean;
206
+ /** 从 from 视角看 to 的层级:superior=对方更高(对方是师/上级), peer, subordinate=对方更低, unknown */
207
+ hierarchy?: 'superior' | 'peer' | 'subordinate' | 'unknown';
208
+ description?: string;
209
+ evidence?: {
210
+ messageIds?: string[];
211
+ quote?: string;
212
+ };
213
+ }>;
214
+ eventEventEdges?: Array<{
215
+ fromEventRefKey: string;
216
+ toEventRefKey: string;
217
+ relationType: string;
218
+ directed?: boolean;
219
+ description?: string;
220
+ evidence?: {
221
+ messageIds?: string[];
222
+ quote?: string;
223
+ };
224
+ }>;
225
+ eventEntityEdges?: Array<{
226
+ eventRefKey: string;
227
+ entityRefKey: string;
228
+ relationType: string;
229
+ description?: string;
230
+ evidence?: {
231
+ messageIds?: string[];
232
+ quote?: string;
233
+ };
234
+ }>;
235
+ entityEntityEdges?: Array<{
236
+ fromEntityRefKey: string;
237
+ toEntityRefKey: string;
238
+ relationType: string;
239
+ directed?: boolean;
240
+ description?: string;
241
+ evidence?: {
242
+ messageIds?: string[];
243
+ quote?: string;
244
+ };
245
+ }>;
246
+ }
247
+ /** 取当前运行时已注册的平台名集合(小写)。无 adapter 时返回空集——调用方应
248
+ * 在传入 isPlaceholderSelfPersonId 时把「空集」视为 permissive。 */
249
+ export declare function getKnownPlatformsLower(ctx: Context): Set<string>;
250
+ export declare function isPlaceholderSelfPersonId(platform: string | undefined, userId: string | undefined, knownPlatforms?: Set<string>): boolean;
251
+ export declare class RelationExtractor {
252
+ private readonly ctx;
253
+ private readonly service;
254
+ private readonly cfg;
255
+ private readonly counts;
256
+ private readonly inFlight;
257
+ private disposeListener?;
258
+ constructor(ctx: Context, service: RelationService, cfg: ExtractorConfig);
259
+ start(): void;
260
+ stop(): void;
261
+ /** 手动触发某 session 的提取(用于 page-action 的"立即提取"按钮) */
262
+ triggerNow(sessionId: string, opts?: {
263
+ readScope?: ExtractorReadScope;
264
+ }): Promise<{
265
+ status: 'ok' | 'skipped' | 'error';
266
+ reason?: string;
267
+ }>;
268
+ private extractSession;
269
+ /**
270
+ * 拉取候选事件 / 实体清单(缩短 LLM 上下文,避免重复创建)。
271
+ *
272
+ * **事件**:近 N 天活跃 → 按 lastReinforcedAt desc 取前 `candidateEventLimit`。
273
+ *
274
+ * **实体**:在事件策略基础上再叠加一层"名字命中"召回,解决"窗口里又提了某个老实体(已过 7 天活跃窗口)
275
+ * 而 LLM 看不到候选 → 重新建一份同名 entity 导致重复"的问题:
276
+ * 1. 近 N 天活跃 entity(与原行为一致,按 lastReinforcedAt desc,取 `candidateEventLimit * 2`)
277
+ * 2. 在当前消息窗口文本里以子串方式出现 normalize 后 name 或 aliases 的全库 entity(O(n) 扫描,
278
+ * n ≤ maxEntities ≈ 250,可忽略)。只对 normalize 长度 ≥2 的名字/别名做匹配,避免单字撞名。
279
+ * 两路按 id 去重后总长度截断到 `candidateEventLimit * 4`,避免 token 爆掉。
280
+ * 注:名字命中路径**带 id 一起塞**,保证 LLM 能直接填 `existingEntityId` 复用。
281
+ */
282
+ private pickCandidates;
283
+ /**
284
+ * 对窗口内每个已知发言人,拿其 1 跳邻居子图(按 weight 降序,截断到 N 条)。
285
+ * 目的:让 LLM 在「加强已有 vs 新建」判断时手里有真证据,避免反复创建同一人 / 同一兴趣的重复节点。
286
+ * 若 senderNeighborhoodEdgeLimit=0 或某 sender 在图中尚未存在,则跳过该 sender。
287
+ */
288
+ private pickSenderNeighbors;
289
+ /** 把 LLM 输出落到关系图中 */
290
+ private applyExtraction;
291
+ }
292
+ export type ParseResult = {
293
+ kind: 'ok';
294
+ value: LLMExtraction;
295
+ } | {
296
+ kind: 'empty';
297
+ } | {
298
+ kind: 'parse-error';
299
+ };
300
+ /**
301
+ * 从 LLM 文本中解析提取结果。区分三种情况:
302
+ * - ok:成功解析出含内容的对象
303
+ * - empty:解析成功但表达为空(LLM 主动指出没什么可提取,属于正常路径)
304
+ * - parse-error:LLM 输出无法解析或不是对象(需 warn)
305
+ */
306
+ export declare function parseExtraction(text: string): ParseResult;
307
+ export {};
308
+ //# sourceMappingURL=extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../src/extractor.ts"],"names":[],"mappings":"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"}