@aalis/plugin-trigger-policy 0.13.0 → 0.14.0

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.js CHANGED
@@ -1,12 +1,14 @@
1
1
  import { flowControl } from '@aalis/api-flow-control';
2
- import { gateway, INBOUND_PHASE } from '@aalis/api-gateway';
2
+ import { extractTargetId, gateway, INBOUND_PHASE, isScopeEnabled, resolveEffectiveConfig } from '@aalis/api-gateway';
3
3
  import { hooks } from '@aalis/api-hooks';
4
4
  import { messageArchive } from '@aalis/api-message-archive';
5
5
  import { persona } from '@aalis/api-persona';
6
- import { config, definePlugin, defineService, logger, optional, provide } from '@aalis/core';
7
- import { selfInitiatedActor, WellKnownNoticeTypes } from '@aalis/schema-message';
8
- import { defaultTriggerPolicyConfig, isScopeEnabled, resolveEffectiveConfig, resolveTriggerPolicyConfig, } from './config.js';
9
- import { checkImmediateTrigger, checkMuteKeyword, getBotNames } from './detector.js';
6
+ import { sessionManager } from '@aalis/api-session-manager';
7
+ import { archiveSwallowed, createBotNames, hitsMuteKeyword, isActiveTrigger, isAddressed, markTriggered, trigger, } from '@aalis/api-trigger';
8
+ import { config, definePlugin, events, lifecycle, logger, optional, provide } from '@aalis/core';
9
+ import { defaultTriggerPolicyConfig, resolveTriggerPolicyConfig } from './config.js';
10
+ import { clearSessionIdle, PlatformIdleScheduler, scheduleSessionIdle } from './idle-scheduler.js';
11
+ import { applyScoreDecay, calculateScoreIncrement, createState, getCurrentThreshold, sweepStaleStates, } from './state.js';
10
12
  // ----- 元数据 -----
11
13
  const configSchema = {
12
14
  scopes: {
@@ -15,7 +17,7 @@ const configSchema = {
15
17
  default: defaultTriggerPolicyConfig.scopes,
16
18
  dynamicOptions: 'gateway-scopes',
17
19
  allowCustom: true,
18
- description: '格式 platform:sessionType,支持通配 *;onebot:group / *:group / onebot:* / *。默认 *:group。',
20
+ description: '格式 platform:sessionType,支持通配 *;onebot:group / *:group / onebot:* / *。默认 *:group;默认作用域不含 WebUI/CLI,如需纳入,在这里显式添加。',
19
21
  },
20
22
  intervalMode: {
21
23
  type: 'select',
@@ -27,7 +29,12 @@ const configSchema = {
27
29
  { label: 'both (任一满足)', value: 'both' },
28
30
  ],
29
31
  },
30
- triggerOnAt: { type: 'boolean', label: '检测 @ 提及', default: defaultTriggerPolicyConfig.triggerOnAt },
32
+ triggerOnAt: {
33
+ type: 'boolean',
34
+ label: '检测 @ 提及',
35
+ default: defaultTriggerPolicyConfig.triggerOnAt,
36
+ description: '@ 自己算"被点名"(戳一戳、名字同理):点名直接开口,回合记为 immediate,点名者即授权主体。',
37
+ },
31
38
  triggerOnPoke: {
32
39
  type: 'boolean',
33
40
  label: '戳一戳直触发',
@@ -41,6 +48,67 @@ const configSchema = {
41
48
  label: '禁言关键词命中时长(秒)',
42
49
  default: defaultTriggerPolicyConfig.muteTimeSeconds,
43
50
  },
51
+ fixedInterval: {
52
+ type: 'number',
53
+ label: '固定间隔(每 N 条触发)',
54
+ default: defaultTriggerPolicyConfig.fixedInterval,
55
+ },
56
+ activityScoreLower: { type: 'number', label: '活跃指数下限', default: defaultTriggerPolicyConfig.activityScoreLower },
57
+ activityScoreUpper: { type: 'number', label: '活跃指数上限', default: defaultTriggerPolicyConfig.activityScoreUpper },
58
+ activityDecayMinutes: {
59
+ type: 'number',
60
+ label: '阈值衰减分钟',
61
+ default: defaultTriggerPolicyConfig.activityDecayMinutes,
62
+ },
63
+ scoreDecayMinutes: {
64
+ type: 'number',
65
+ label: '评分衰减分钟(0=不衰减)',
66
+ default: defaultTriggerPolicyConfig.scoreDecayMinutes,
67
+ },
68
+ idleTriggerScope: {
69
+ type: 'select',
70
+ label: '闲置触发范围',
71
+ default: defaultTriggerPolicyConfig.idleTriggerScope,
72
+ options: [
73
+ { label: 'off (关闭)', value: 'off' },
74
+ { label: 'session (每会话独立定时)', value: 'session' },
75
+ { label: 'platform (跨会话选举)', value: 'platform' },
76
+ ],
77
+ },
78
+ idleTriggerStrategy: {
79
+ type: 'select',
80
+ label: '闲置触发策略',
81
+ default: defaultTriggerPolicyConfig.idleTriggerStrategy,
82
+ options: [
83
+ { label: 'all-quiet (所有会话都静默时)', value: 'all-quiet' },
84
+ { label: 'fixed (固定间隔)', value: 'fixed' },
85
+ ],
86
+ },
87
+ idleTriggerMinutes: {
88
+ type: 'number',
89
+ label: '闲置触发分钟',
90
+ default: defaultTriggerPolicyConfig.idleTriggerMinutes,
91
+ },
92
+ idleTriggerStyle: {
93
+ type: 'select',
94
+ label: '闲置触发风格',
95
+ default: defaultTriggerPolicyConfig.idleTriggerStyle,
96
+ options: [
97
+ { label: 'exponential (指数退避)', value: 'exponential' },
98
+ { label: 'fixed (固定)', value: 'fixed' },
99
+ ],
100
+ },
101
+ idleTriggerMaxMinutes: {
102
+ type: 'number',
103
+ label: '闲置触发上限分钟',
104
+ default: defaultTriggerPolicyConfig.idleTriggerMaxMinutes,
105
+ },
106
+ idleTriggerJitter: { type: 'boolean', label: '闲置触发抖动', default: defaultTriggerPolicyConfig.idleTriggerJitter },
107
+ idleTriggerPrompt: {
108
+ type: 'string',
109
+ label: '闲置触发系统提示',
110
+ default: defaultTriggerPolicyConfig.idleTriggerPrompt,
111
+ },
44
112
  overrides: {
45
113
  type: 'array',
46
114
  label: '分作用域覆盖',
@@ -67,21 +135,47 @@ const configSchema = {
67
135
  triggerNames: { type: 'string', label: '触发名别名(逗号分隔)' },
68
136
  muteKeywords: { type: 'string', label: '禁言关键词(逗号分隔)' },
69
137
  muteTimeSeconds: { type: 'number', label: '禁言关键词时长(秒)' },
138
+ fixedInterval: { type: 'number', label: '固定间隔(每 N 条触发)' },
139
+ activityScoreLower: { type: 'number', label: '活跃指数下限' },
140
+ activityScoreUpper: { type: 'number', label: '活跃指数上限' },
141
+ activityDecayMinutes: { type: 'number', label: '阈值衰减分钟' },
142
+ scoreDecayMinutes: { type: 'number', label: '评分衰减分钟' },
143
+ idleTriggerScope: {
144
+ type: 'select',
145
+ label: '闲置触发范围',
146
+ options: [
147
+ { label: 'off', value: 'off' },
148
+ { label: 'session', value: 'session' },
149
+ { label: 'platform', value: 'platform' },
150
+ ],
151
+ },
152
+ idleTriggerMinutes: { type: 'number', label: '闲置触发分钟' },
153
+ idleTriggerMaxMinutes: { type: 'number', label: '闲置触发上限分钟' },
154
+ idleTriggerJitter: { type: 'boolean', label: '闲置触发抖动' },
155
+ idleTriggerPrompt: { type: 'string', label: '闲置触发系统提示' },
70
156
  },
71
157
  },
72
158
  };
73
- // ----- 服务描述符(按激活绑定;调用型:绑定接口是 ServiceRef)-----
74
- export const triggerPolicy = defineService('trigger-policy');
75
159
  // ----- 入口 -----
76
160
  const uses = {
77
161
  logger,
162
+ events,
78
163
  hooks,
164
+ lifecycle,
79
165
  config,
80
166
  provide,
81
167
  gateway,
82
- // 缺席时按"无状态即放行"评估;归档缺席则被吞掉的消息不进档,判定照常
168
+ /**
169
+ * trigger 由本插件自己提供,只能声明成 optional:写 required 会把激活闸架在自己的产出上。
170
+ * 经它判断本插件是不是生效的触发插件(服务胜者)。
171
+ */
172
+ trigger: optional(trigger),
173
+ // 缺席时不设禁言:关键词照样吞掉本条,但不会写入禁言期
83
174
  flowControl: optional(flowControl),
84
175
  persona: optional(persona),
176
+ // 名字表按会话取人设:解析会话配置里的角色卡;缺席时取全局默认的卡
177
+ sessionManager: optional(sessionManager),
178
+ // 缺席时被吞掉的消息不进档,判定照常
85
179
  messageArchive: optional(messageArchive),
86
180
  };
87
181
  export default definePlugin({
@@ -89,150 +183,171 @@ export default definePlugin({
89
183
  displayName: '触发策略',
90
184
  subsystem: 'scheduler',
91
185
  configSchema,
92
- provides: [triggerPolicy],
186
+ provides: [trigger],
93
187
  uses,
94
188
  apply: run,
95
189
  });
96
190
  function run(caps) {
97
- const { logger, hooks, provide, persona, flowControl, messageArchive } = caps;
191
+ const { logger, events, hooks, lifecycle, provide, flowControl, messageArchive } = caps;
98
192
  const cfg = resolveTriggerPolicyConfig(caps.config);
99
- /** 从 IncomingMessage 派生 per-scope override 用的 targetId(群=groupId / 私=userId / 其他=空) */
100
- function extractTargetId(message) {
101
- if (message.sessionType === 'group')
102
- return message.groupId ?? '';
103
- if (message.sessionType === 'private')
104
- return message.userId ?? '';
105
- return '';
193
+ const states = new Map();
194
+ /** 名字表:别名与全部人设按会话取的名字、昵称;某个人设读名字出错只跳过它的名字 */
195
+ const botNames = createBotNames(caps.persona, caps.sessionManager, logger, '[trigger]');
196
+ // 本插件在 trigger 服务里的实例:服务胜者是它时本插件生效,否则对每条消息直接放行、闲置也不开口
197
+ const self = { label: '规则(计数/评分)' };
198
+ provide(trigger, self, { label: self.label });
199
+ const isActive = () => caps.trigger.current === self;
200
+ const idleCaps = { logger, gateway: caps.gateway, flowControl, isActive };
201
+ const platformIdle = new PlatformIdleScheduler(idleCaps, cfg, states);
202
+ /** 计数与活跃指数清零(禁言与判定放行时) */
203
+ function resetCounters(s) {
204
+ s.messageCount = 0;
205
+ s.activityScore = 0;
106
206
  }
107
- /** 把"被策略吞掉"的入站消息归档(与 flow-control 的 shadow 归档对齐) */
108
- async function shadowArchive(message) {
109
- const archive = messageArchive.current;
110
- if (!archive)
207
+ /** 按会话重排 session 档 idle(非 session 档时只清定时器) */
208
+ function rescheduleIdle(sessionId) {
209
+ const s = states.get(sessionId);
210
+ if (!s)
111
211
  return;
112
- try {
113
- await archive.archiveIncoming(message);
114
- }
115
- catch (err) {
116
- logger.warn(`[trigger] shadow 归档失败: ${err}`);
212
+ const e = resolveEffectiveConfig(cfg, s.platform, s.sessionType, s.targetId);
213
+ scheduleSessionIdle(idleCaps, e, s, sessionId, () => rescheduleIdle(sessionId));
214
+ }
215
+ /** 记一条真人入站的计数:评分衰减、计数、评分增量、用户交互。衰减按上一条消息的时间算,须在 recordActivity 之前调用 */
216
+ function recordIncoming(s, e, userId) {
217
+ applyScoreDecay(s, e);
218
+ if (userId)
219
+ s.userInteractions.set(userId, (s.userInteractions.get(userId) ?? 0) + 1);
220
+ s.messageCount++;
221
+ s.activityScore += calculateScoreIncrement(s, e, userId);
222
+ }
223
+ /**
224
+ * 记一次真人活动:最近消息时间、闲置退避复位为 1,并从现在起重排 session 档 idle。
225
+ * 作用域内的真人消息都算,禁言期内与命中禁言关键词的也算(它们只是不计数)
226
+ */
227
+ function recordActivity(sessionId, s) {
228
+ s.lastMessageTime = Date.now();
229
+ s.idleBackoff = 1;
230
+ rescheduleIdle(sessionId);
231
+ }
232
+ /** 要不要开口:点名直接开口,否则按会话此刻的计数与评分判定 */
233
+ function decide(s, e, addressed) {
234
+ if (addressed)
235
+ return { speak: true, reason: '点名' };
236
+ const threshold = getCurrentThreshold(s, e);
237
+ const fixedOk = s.messageCount >= e.fixedInterval;
238
+ const dynamicOk = s.activityScore >= threshold;
239
+ let speak = false;
240
+ switch (e.intervalMode) {
241
+ case 'fixed':
242
+ speak = fixedOk;
243
+ break;
244
+ case 'dynamic':
245
+ speak = dynamicOk;
246
+ break;
247
+ case 'both':
248
+ speak = fixedOk || dynamicOk;
249
+ break;
117
250
  }
251
+ // 让运维一眼看到"还差多少条/多少分会触发"
252
+ const reason = `计数=${s.messageCount}/${e.fixedInterval} 指数=${s.activityScore.toFixed(3)} (阈值=${threshold.toFixed(3)})`;
253
+ return { speak, reason };
118
254
  }
119
- const service = {
120
- decide(message) {
121
- const tid = extractTargetId(message);
122
- if (!isScopeEnabled(cfg, message.platform, message.sessionType, tid)) {
123
- return {
124
- kind: 'direct',
125
- reason: `scope 不在触发策略名单内 (${message.platform ?? '?'}:${message.sessionType ?? '?'})`,
126
- };
127
- }
128
- const eff = resolveEffectiveConfig(cfg, message.platform, message.sessionType, tid);
129
- // 注意力动作(well-known noticeType=poke)默认视同 @ 直触发:能进到这里说明
130
- // adapter 已经判断过目标是 bot(私聊戳全转 inbound / 群聊戳仅 target=self 才转)。
131
- // triggerOnPoke 关闭时落回下方意愿评估,且**跳过 @/名字检测**:poke 的 content
132
- // 是合成文案(内嵌戳者昵称),昵称含 bot 名会被名字检测误判成提及——
133
- // 用户改个名就能让开关对自己失效(对抗审计实测),元数据不当发言评估。
134
- if (message.noticeType === WellKnownNoticeTypes.Poke) {
135
- if (eff.triggerOnPoke) {
136
- return { kind: 'immediate', reason: 'poke notice' };
137
- }
138
- }
139
- else if (checkImmediateTrigger(persona, eff, message.content)) {
140
- return { kind: 'immediate', reason: '@/name match' };
141
- }
142
- const flow = flowControl.current;
143
- const snap = flow?.getStateSnapshot(message.sessionId);
144
- if (!snap) {
145
- return { kind: 'interval', reason: 'no flow state, default-pass' };
146
- }
147
- const fixedOk = snap.messageCount >= snap.fixedInterval;
148
- const dynamicOk = snap.activityScore >= (flow?.getThreshold(message.sessionId) ?? 0);
149
- let trigger = false;
150
- switch (eff.intervalMode) {
151
- case 'fixed':
152
- trigger = fixedOk;
153
- break;
154
- case 'dynamic':
155
- trigger = dynamicOk;
156
- break;
157
- case 'both':
158
- trigger = fixedOk || dynamicOk;
159
- break;
160
- }
161
- return trigger
162
- ? { kind: 'interval', reason: `interval-mode=${eff.intervalMode}` }
163
- : { kind: 'swallow', reason: 'below threshold' };
164
- },
165
- getBotNames() {
166
- return getBotNames(persona, cfg);
167
- },
168
- detectMuteKeyword(content) {
169
- return checkMuteKeyword(cfg, content);
170
- },
171
- };
172
- provide(triggerPolicy, service);
173
- logger.info(`[trigger] 已启用 (模式=${cfg.intervalMode}, @提及=${cfg.triggerOnAt}, ` +
174
- `别名=${cfg.triggerNames.length}, mute关键词=${cfg.muteKeywords.length}, ` +
175
- `mute时长=${cfg.muteTimeSeconds}s, scopes=${cfg.scopes.join('|') || '<空>'}, ` +
255
+ logger.info(`[trigger] 已启用 (模式=${cfg.intervalMode}, 固定间隔=${cfg.fixedInterval}, ` +
256
+ `阈值=${cfg.activityScoreLower}~${cfg.activityScoreUpper}, @提及=${cfg.triggerOnAt}, ` +
257
+ `别名=${cfg.triggerNames.length}, mute关键词=${cfg.muteKeywords.length}, mute时长=${cfg.muteTimeSeconds}s, ` +
258
+ `idle=${cfg.idleTriggerScope}/${cfg.idleTriggerStrategy}, scopes=${cfg.scopes.join('|') || '<空>'}, ` +
176
259
  `overrides=${cfg.overrides.length})`);
177
- // ===== inbound:trigger 相位:触发判定 =====
178
- // 由 plugin-gateway 在 inbound:flow 之后、inbound:dispatch 之前触发。
179
- // 进入本相位意味着已通过冷却/限速闸门。
260
+ // ===== inbound:trigger 相位:要不要开口 =====
261
+ // 由 plugin-gateway 在 inbound:command 之后、inbound:flow 之前触发。放行的消息写好 triggerType,
262
+ // 交给 flow 相位做节流硬闸(immediate 穿透冷却与限速)。判定是同步的:记入站、判定、清零在同一拍做完,
263
+ // 同一会话接连到达的消息按到达顺序逐条判定,放行顺序即到达顺序。
180
264
  hooks.middleware(INBOUND_PHASE.TRIGGER, async (data, next) => {
265
+ // 不是生效的触发插件:什么都不做(不计数、不识别、不归档),交给生效者或往下走
266
+ if (!isActiveTrigger(data, caps.trigger, self))
267
+ return next();
181
268
  const { message } = data;
182
- if (message.source === 'idle-trigger')
183
- return next(); // 内部注入跳过策略
184
- const flow = flowControl.current;
185
- const tid = extractTargetId(message);
269
+ // 内部注入(闲置触发、定时任务、workflow、跨会话委派)都带 source,跳过策略:不计数、不改 triggerType。
270
+ // 真人消息由平台适配器投递,不设 source。
271
+ if (message.source)
272
+ return next();
186
273
  // 不在触发策略作用域内(默认 *:group):直接放行。
187
274
  // 必须在 mute 检查之前进行,否则 QQ 群的 mute 关键词会泄漏到 WebUI/私聊等不在 scope 内的会话。
188
- if (!isScopeEnabled(cfg, message.platform, message.sessionType, tid)) {
275
+ const tid = extractTargetId(message);
276
+ if (!isScopeEnabled(cfg, message.platform, message.sessionType, tid))
277
+ return next();
278
+ const sessionId = message.sessionId;
279
+ const flow = flowControl.current;
280
+ // 作用域内的真人消息都是会话活动,禁言期内的也是:会话还没有状态(如平台禁言先于任何消息)就在这里建
281
+ let s = states.get(sessionId);
282
+ if (!s) {
283
+ s = createState(message.platform, message.sessionType, tid);
284
+ states.set(sessionId, s);
285
+ }
286
+ // 禁言期:不累计计数,已攒的计数与评分清零(平台禁言只能在这里清:禁言期来消息时);
287
+ // 也不再识别禁言关键词,避免缩短平台禁言。仍记为真人活动,放行给 flow 相位吞掉并归档。
288
+ if (flow?.isMuted(sessionId)) {
289
+ resetCounters(s);
290
+ recordActivity(sessionId, s);
189
291
  return next();
190
292
  }
191
- const eff = resolveEffectiveConfig(cfg, message.platform, message.sessionType, tid);
192
- // mute 关键词命中:设置自禁言并 swallow
193
- if (checkMuteKeyword(eff, message.content)) {
194
- logger.info(`[trigger] mute 关键词命中 → swallow + setMuted(${eff.muteTimeSeconds}s): ${message.sessionId}`);
195
- flow?.setMuted(message.sessionId, eff.muteTimeSeconds);
196
- // 与 dev OneBot ChatFlow 一致:设置自禁言后调度一次 idle,
197
- // 让禁言结束附近能正常进入「长期静默→主动招呼」路径。
198
- flow?.rescheduleIdle(message.sessionId, message.platform);
199
- await shadowArchive(message);
293
+ const e = resolveEffectiveConfig(cfg, message.platform, message.sessionType, tid);
294
+ // 禁言关键词:设置自禁言、计数与评分当场清零,记为真人活动,吞掉本条
295
+ if (hitsMuteKeyword(message, e.muteKeywords)) {
296
+ logger.info(`[trigger] mute 关键词命中 → swallow + setMuted(${e.muteTimeSeconds}s): ${sessionId}`);
297
+ flow?.setMuted(sessionId, e.muteTimeSeconds, message.platform);
298
+ resetCounters(s);
299
+ recordActivity(sessionId, s);
300
+ await archiveSwallowed(message, messageArchive, logger, '[trigger]');
200
301
  return; // swallow
201
302
  }
202
- let decision;
203
- try {
204
- decision = service.decide(message);
303
+ recordIncoming(s, e, message.userId);
304
+ recordActivity(sessionId, s);
305
+ const addressed = isAddressed(message, botNames(e.triggerNames, message), e);
306
+ const decision = decide(s, e, addressed);
307
+ // 判定日志:不含消息正文
308
+ logger.debug(`[trigger] 判定 | session=${sessionId} | speak=${decision.speak} | addressed=${addressed} | reason=${decision.reason}`);
309
+ if (!decision.speak) {
310
+ await archiveSwallowed(message, messageArchive, logger, '[trigger]');
311
+ return; // swallow
205
312
  }
206
- catch (err) {
207
- logger.warn(`[trigger] decide() 异常,默认放行: ${err}`);
208
- await next();
313
+ // 判定放行即复位:之后若被 flow 相位的冷却/限速吞掉,这次触发作废
314
+ resetCounters(s);
315
+ s.lastTriggerTime = Date.now();
316
+ markTriggered(message, addressed);
317
+ await next();
318
+ });
319
+ // agent 真实回复:记为 bot 开口并重排 session 档 idle。不复位退避——bot 回复闲置提示不算真人活动。
320
+ // 不生效时不记(闲置也不开口)
321
+ events.on('outbound:message', (msg) => {
322
+ if (msg.source !== 'agent' || !msg.sessionId || !isActive())
209
323
  return;
210
- }
211
- // 统一状态日志(与历史 dev OneBot ChatFlow 的"消息计数/发言指数"日志保持一致):
212
- // 让运维可以一眼看到"还差多少条/多少分会触发"。
213
- const snap = flow?.getStateSnapshot(message.sessionId);
214
- const threshold = flow?.getThreshold(message.sessionId);
215
- const stateStr = snap
216
- ? `计数=${snap.messageCount}/${snap.fixedInterval} | 指数=${snap.activityScore.toFixed(3)} (阈值=${(threshold ?? 0).toFixed(3)})`
217
- : '无 flow 状态';
218
- if (decision.kind === 'immediate' || decision.kind === 'interval') {
219
- logger.debug(`[trigger] ${decision.kind} → 触发 | session=${message.sessionId} | ${stateStr} | ${decision.reason}`);
220
- flow?.recordTriggered(message.sessionId);
221
- message.triggerType = decision.kind;
222
- // interval 回合无主发言者:授权身份回填为无主体,不让「恰好撞阈值的那个人」
223
- //(陌生人或 owner)的等级决定 AI 自发行为能调什么工具。immediate 是被点名,
224
- // 点名者就是主体,维持缺省(actor 回退到会话身份)。只对多人会话:scope 可配成
225
- // 把私聊纳入,私聊里的 interval 只是频率闸,发言者就是唯一主体,不存在歧义。
226
- if (decision.kind === 'interval' && message.sessionType !== 'private' && !message.actor) {
227
- message.actor = selfInitiatedActor(message.platform);
228
- }
229
- await next();
324
+ const s = states.get(msg.sessionId);
325
+ if (!s)
230
326
  return;
231
- }
232
- // swallow
233
- logger.debug(`[trigger] 未触发 → 吞噬 | session=${message.sessionId} | ${stateStr} | ${decision.reason}`);
234
- await shadowArchive(message);
235
- // flow-control 已在前置中调度 idle,无需重复
327
+ s.lastBotActivityAt = Date.now();
328
+ rescheduleIdle(msg.sessionId);
329
+ });
330
+ // 平台级 idle 启动
331
+ events.on('app:ready', () => {
332
+ platformIdle.start();
333
+ });
334
+ // 长寿进程下避免 states 无限增长:每天扫描一次,清理 30 天无活动且无 idle 定时器的会话
335
+ const SWEEP_INTERVAL_MS = 24 * 60 * 60 * 1000;
336
+ const sweepTimer = setInterval(() => {
337
+ const cleaned = sweepStaleStates(states, Date.now());
338
+ if (cleaned > 0)
339
+ logger.debug(`[trigger] TTL 清理已淘汰 ${cleaned} 个长期非活跃会话状态`);
340
+ }, SWEEP_INTERVAL_MS);
341
+ if (typeof sweepTimer.unref === 'function')
342
+ sweepTimer.unref();
343
+ lifecycle.onDispose(() => {
344
+ clearInterval(sweepTimer);
345
+ platformIdle.stop();
346
+ for (const s of states.values())
347
+ clearSessionIdle(s);
348
+ // 清表:session 档闲置注入要等整个 agent 回合,停用时可能还在途;回来时 rescheduleIdle 取不到状态,
349
+ // 不再排定时器(判定是同步的,入站中间件在 await 之后不再读写状态表)
350
+ states.clear();
236
351
  });
237
352
  }
238
353
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { TriggerPolicyConfig } from './config.js';
2
+ export interface TriggerSessionState {
3
+ /** 该 session 所属 platform(用于 per-scope 覆盖匹配与 idle 注入) */
4
+ platform: string;
5
+ /** 该 session 的 sessionType(如 group/private/channel);用于 per-scope 覆盖匹配 */
6
+ sessionType: string;
7
+ /** 该 session 的目标 id(群号/用户号/频道号);用于 per-scope 覆盖匹配 */
8
+ targetId: string;
9
+ messageCount: number;
10
+ activityScore: number;
11
+ lastMessageTime: number;
12
+ /** 上次判定放行(immediate / interval)的时刻;动态阈值从这里开始衰减 */
13
+ lastTriggerTime: number;
14
+ /** bot 最近一次开口:agent 真实回复或 idle 注入的时刻 */
15
+ lastBotActivityAt: number;
16
+ /** 每个用户在本会话的入站条数(评分权重用) */
17
+ userInteractions: Map<string, number>;
18
+ idleTimer: ReturnType<typeof setTimeout> | null;
19
+ idleBackoff: number;
20
+ }
21
+ export declare function createState(platform: string, sessionType?: string, targetId?: string): TriggerSessionState;
22
+ /** 会话最近一次活动:真人消息或 bot 开口,取较晚者 */
23
+ export declare function lastActivityOf(state: TriggerSessionState): number;
24
+ /** 当前阈值(动态衰减) */
25
+ export declare function getCurrentThreshold(state: TriggerSessionState, cfg: TriggerPolicyConfig): number;
26
+ /** 评分按距离上次消息的时间线性衰减(原地修改) */
27
+ export declare function applyScoreDecay(state: TriggerSessionState, cfg: TriggerPolicyConfig): void;
28
+ /** 计算单条入站对评分的增量(受用户交互权重影响) */
29
+ export declare function calculateScoreIncrement(state: TriggerSessionState, cfg: TriggerPolicyConfig, userId?: string): number;
30
+ /** 会话状态的保留期:超过它无活动且无 idle 定时器即淘汰 */
31
+ export declare const SESSION_TTL_MS: number;
32
+ /** 删除无 idle 定时器且超过 TTL 无活动的会话状态,返回删除数 */
33
+ export declare function sweepStaleStates(states: Map<string, TriggerSessionState>, now: number): number;
34
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,MAAM,WAAW,mBAAmB;IAClC,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,eAAe,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,2BAA2B;IAC3B,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,SAAS,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC;IAChD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,SAAK,EAAE,QAAQ,SAAK,GAAG,mBAAmB,CAclG;AAED,iCAAiC;AACjC,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAEjE;AAED,iBAAiB;AACjB,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,mBAAmB,EAAE,GAAG,EAAE,mBAAmB,GAAG,MAAM,CAMhG;AAED,6BAA6B;AAC7B,wBAAgB,eAAe,CAAC,KAAK,EAAE,mBAAmB,EAAE,GAAG,EAAE,mBAAmB,GAAG,IAAI,CAO1F;AAED,8BAA8B;AAC9B,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,mBAAmB,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAUrH;AAED,oCAAoC;AACpC,eAAO,MAAM,cAAc,QAA2B,CAAC;AAEvD,yCAAyC;AACzC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAU9F"}
package/dist/state.js ADDED
@@ -0,0 +1,68 @@
1
+ // ----- 触发会话状态 + 衰减/计数算法 + TTL 清扫 -----
2
+ export function createState(platform, sessionType = '', targetId = '') {
3
+ return {
4
+ platform,
5
+ sessionType,
6
+ targetId,
7
+ messageCount: 0,
8
+ activityScore: 0,
9
+ lastMessageTime: 0,
10
+ lastTriggerTime: 0,
11
+ lastBotActivityAt: 0,
12
+ userInteractions: new Map(),
13
+ idleTimer: null,
14
+ idleBackoff: 1,
15
+ };
16
+ }
17
+ /** 会话最近一次活动:真人消息或 bot 开口,取较晚者 */
18
+ export function lastActivityOf(state) {
19
+ return Math.max(state.lastMessageTime, state.lastBotActivityAt);
20
+ }
21
+ /** 当前阈值(动态衰减) */
22
+ export function getCurrentThreshold(state, cfg) {
23
+ if (state.lastTriggerTime === 0)
24
+ return cfg.activityScoreLower;
25
+ const elapsed = Date.now() - state.lastTriggerTime;
26
+ const decayMs = cfg.activityDecayMinutes * 60 * 1000;
27
+ const factor = Math.max(0, 1 - elapsed / decayMs);
28
+ return cfg.activityScoreLower + (cfg.activityScoreUpper - cfg.activityScoreLower) * factor;
29
+ }
30
+ /** 评分按距离上次消息的时间线性衰减(原地修改) */
31
+ export function applyScoreDecay(state, cfg) {
32
+ if (cfg.scoreDecayMinutes <= 0 || state.activityScore <= 0 || state.lastMessageTime === 0)
33
+ return;
34
+ const elapsed = Date.now() - state.lastMessageTime;
35
+ const decayMs = cfg.scoreDecayMinutes * 60 * 1000;
36
+ const factor = Math.max(0, 1 - elapsed / decayMs);
37
+ state.activityScore *= factor;
38
+ if (state.activityScore < 0.001)
39
+ state.activityScore = 0;
40
+ }
41
+ /** 计算单条入站对评分的增量(受用户交互权重影响) */
42
+ export function calculateScoreIncrement(state, cfg, userId) {
43
+ const base = 1.0 / Math.max(1, cfg.fixedInterval);
44
+ let userWeight = 1.0;
45
+ if (userId) {
46
+ const count = state.userInteractions.get(userId);
47
+ if (count) {
48
+ userWeight = 1.0 + 0.5 * Math.min(count / 10, 1.0);
49
+ }
50
+ }
51
+ return base * userWeight;
52
+ }
53
+ /** 会话状态的保留期:超过它无活动且无 idle 定时器即淘汰 */
54
+ export const SESSION_TTL_MS = 30 * 24 * 60 * 60 * 1000;
55
+ /** 删除无 idle 定时器且超过 TTL 无活动的会话状态,返回删除数 */
56
+ export function sweepStaleStates(states, now) {
57
+ let cleaned = 0;
58
+ for (const [sid, s] of states) {
59
+ if (s.idleTimer)
60
+ continue;
61
+ if (now - lastActivityOf(s) > SESSION_TTL_MS) {
62
+ states.delete(sid);
63
+ cleaned++;
64
+ }
65
+ }
66
+ return cleaned;
67
+ }
68
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}