@aalis/plugin-trigger-policy 0.12.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/README.md +1 -1
- package/dist/config.d.ts +32 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +51 -71
- package/dist/config.js.map +1 -1
- package/dist/idle-scheduler.d.ts +36 -0
- package/dist/idle-scheduler.d.ts.map +1 -0
- package/dist/idle-scheduler.js +206 -0
- package/dist/idle-scheduler.js.map +1 -0
- package/dist/index.d.ts +13 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +249 -133
- package/dist/index.js.map +1 -1
- package/dist/state.d.ts +34 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +68 -0
- package/dist/state.js.map +1 -0
- package/package.json +20 -13
- package/dist/detector.d.ts +0 -18
- package/dist/detector.d.ts.map +0 -1
- package/dist/detector.js +0 -47
- package/dist/detector.js.map +0 -1
- package/dist/types.d.ts +0 -16
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -6
- package/dist/types.js.map +0 -1
package/README.md
CHANGED
package/dist/config.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export type IdleTriggerScope = 'off' | 'session' | 'platform';
|
|
2
|
+
export type IdleTriggerStrategy = 'all-quiet' | 'fixed';
|
|
3
|
+
export type IdleTriggerStyle = 'exponential' | 'fixed';
|
|
1
4
|
export interface TriggerPolicyConfig {
|
|
2
5
|
/**
|
|
3
6
|
* 统一作用域名单:platform:sessionType[:targetId],支持 *。
|
|
@@ -23,6 +26,24 @@ export interface TriggerPolicyConfig {
|
|
|
23
26
|
muteKeywords: string[];
|
|
24
27
|
/** mute 关键词命中时通知 flow-control 设置的禁言时长(秒) */
|
|
25
28
|
muteTimeSeconds: number;
|
|
29
|
+
/** 固定间隔:每 N 条消息累计一次触发 */
|
|
30
|
+
fixedInterval: number;
|
|
31
|
+
/** 动态阈值上下限(刚触发后高、长时间未触发后低) */
|
|
32
|
+
activityScoreLower: number;
|
|
33
|
+
activityScoreUpper: number;
|
|
34
|
+
/** 阈值衰减分钟数:距上次触发越久,阈值越低 */
|
|
35
|
+
activityDecayMinutes: number;
|
|
36
|
+
/** 评分本身的衰减分钟数(0 表示评分不主动衰减) */
|
|
37
|
+
scoreDecayMinutes: number;
|
|
38
|
+
/** 闲置触发范围 */
|
|
39
|
+
idleTriggerScope: IdleTriggerScope;
|
|
40
|
+
idleTriggerStrategy: IdleTriggerStrategy;
|
|
41
|
+
idleTriggerMinutes: number;
|
|
42
|
+
idleTriggerStyle: IdleTriggerStyle;
|
|
43
|
+
idleTriggerMaxMinutes: number;
|
|
44
|
+
idleTriggerJitter: boolean;
|
|
45
|
+
/** 闲置触发注入的 system 提示文本 */
|
|
46
|
+
idleTriggerPrompt: string;
|
|
26
47
|
}
|
|
27
48
|
export interface TriggerScopeOverride {
|
|
28
49
|
scope: string;
|
|
@@ -32,10 +53,18 @@ export interface TriggerScopeOverride {
|
|
|
32
53
|
triggerNames?: string[];
|
|
33
54
|
muteKeywords?: string[];
|
|
34
55
|
muteTimeSeconds?: number;
|
|
56
|
+
fixedInterval?: number;
|
|
57
|
+
activityScoreLower?: number;
|
|
58
|
+
activityScoreUpper?: number;
|
|
59
|
+
activityDecayMinutes?: number;
|
|
60
|
+
scoreDecayMinutes?: number;
|
|
61
|
+
idleTriggerScope?: IdleTriggerScope;
|
|
62
|
+
idleTriggerMinutes?: number;
|
|
63
|
+
idleTriggerStyle?: IdleTriggerStyle;
|
|
64
|
+
idleTriggerMaxMinutes?: number;
|
|
65
|
+
idleTriggerJitter?: boolean;
|
|
66
|
+
idleTriggerPrompt?: string;
|
|
35
67
|
}
|
|
36
68
|
export declare const defaultTriggerPolicyConfig: TriggerPolicyConfig;
|
|
37
69
|
export declare function resolveTriggerPolicyConfig(raw: Record<string, unknown>): TriggerPolicyConfig;
|
|
38
|
-
/** scope 匹配:3 段 platform:sessionType[:targetId],支持 * 与省略。 */
|
|
39
|
-
export declare function isScopeEnabled(cfg: TriggerPolicyConfig, platform: string | undefined, sessionType: string | undefined, targetId?: string | undefined): boolean;
|
|
40
|
-
export declare function resolveEffectiveConfig(cfg: TriggerPolicyConfig, platform: string | undefined, sessionType: string | undefined, targetId?: string | undefined): TriggerPolicyConfig;
|
|
41
70
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;;;OAIG;IACH,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAClC,2CAA2C;IAC3C,YAAY,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,SAAS,GAAG,UAAU,CAAC;AAC9D,MAAM,MAAM,mBAAmB,GAAG,WAAW,GAAG,OAAO,CAAC;AACxD,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,OAAO,CAAC;AAEvD,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;;;OAIG;IACH,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAClC,2CAA2C;IAC3C,YAAY,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IAE3C,sBAAsB;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,wDAAwD;IACxD,aAAa,EAAE,OAAO,CAAC;IACvB,+BAA+B;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,yBAAyB;IACzB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,4CAA4C;IAC5C,eAAe,EAAE,MAAM,CAAC;IAExB,yBAAyB;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,2BAA2B;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,8BAA8B;IAC9B,iBAAiB,EAAE,MAAM,CAAC;IAE1B,aAAa;IACb,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,0BAA0B;IAC1B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,0BAA0B,EAAE,mBAqBxC,CAAC;AAaF,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,mBAAmB,CAiC5F"}
|
package/dist/config.js
CHANGED
|
@@ -8,6 +8,18 @@ export const defaultTriggerPolicyConfig = {
|
|
|
8
8
|
triggerNames: [],
|
|
9
9
|
muteKeywords: [],
|
|
10
10
|
muteTimeSeconds: 60,
|
|
11
|
+
fixedInterval: 5,
|
|
12
|
+
activityScoreLower: 0.3,
|
|
13
|
+
activityScoreUpper: 0.85,
|
|
14
|
+
activityDecayMinutes: 10,
|
|
15
|
+
scoreDecayMinutes: 0,
|
|
16
|
+
idleTriggerScope: 'off',
|
|
17
|
+
idleTriggerStrategy: 'all-quiet',
|
|
18
|
+
idleTriggerMinutes: 180,
|
|
19
|
+
idleTriggerStyle: 'exponential',
|
|
20
|
+
idleTriggerMaxMinutes: 1440,
|
|
21
|
+
idleTriggerJitter: true,
|
|
22
|
+
idleTriggerPrompt: '',
|
|
11
23
|
};
|
|
12
24
|
function parseStringList(val) {
|
|
13
25
|
if (Array.isArray(val))
|
|
@@ -36,79 +48,23 @@ export function resolveTriggerPolicyConfig(raw) {
|
|
|
36
48
|
muteTimeSeconds: typeof raw.muteTimeSeconds === 'number' && raw.muteTimeSeconds > 0
|
|
37
49
|
? Math.floor(raw.muteTimeSeconds)
|
|
38
50
|
: d.muteTimeSeconds,
|
|
51
|
+
fixedInterval: raw.fixedInterval ?? d.fixedInterval,
|
|
52
|
+
activityScoreLower: raw.activityScoreLower ?? d.activityScoreLower,
|
|
53
|
+
activityScoreUpper: raw.activityScoreUpper ?? d.activityScoreUpper,
|
|
54
|
+
activityDecayMinutes: raw.activityDecayMinutes ?? d.activityDecayMinutes,
|
|
55
|
+
scoreDecayMinutes: raw.scoreDecayMinutes ?? d.scoreDecayMinutes,
|
|
56
|
+
idleTriggerScope: (() => {
|
|
57
|
+
const v = raw.idleTriggerScope;
|
|
58
|
+
return v === 'off' || v === 'session' || v === 'platform' ? v : d.idleTriggerScope;
|
|
59
|
+
})(),
|
|
60
|
+
idleTriggerStrategy: raw.idleTriggerStrategy === 'fixed' ? 'fixed' : 'all-quiet',
|
|
61
|
+
idleTriggerMinutes: raw.idleTriggerMinutes ?? d.idleTriggerMinutes,
|
|
62
|
+
idleTriggerStyle: raw.idleTriggerStyle ?? d.idleTriggerStyle,
|
|
63
|
+
idleTriggerMaxMinutes: raw.idleTriggerMaxMinutes ?? d.idleTriggerMaxMinutes,
|
|
64
|
+
idleTriggerJitter: raw.idleTriggerJitter ?? d.idleTriggerJitter,
|
|
65
|
+
idleTriggerPrompt: raw.idleTriggerPrompt || d.idleTriggerPrompt,
|
|
39
66
|
};
|
|
40
67
|
}
|
|
41
|
-
/** scope 匹配:3 段 platform:sessionType[:targetId],支持 * 与省略。 */
|
|
42
|
-
export function isScopeEnabled(cfg, platform, sessionType, targetId) {
|
|
43
|
-
const p = platform ?? '';
|
|
44
|
-
const t = sessionType ?? '';
|
|
45
|
-
const tid = targetId ?? '';
|
|
46
|
-
for (const raw of cfg.scopes) {
|
|
47
|
-
if (matchScopeString(raw, p, t, tid))
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
for (const o of cfg.overrides) {
|
|
51
|
-
if (matchScopeString(o.scope, p, t, tid))
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
export function resolveEffectiveConfig(cfg, platform, sessionType, targetId) {
|
|
57
|
-
if (cfg.overrides.length === 0)
|
|
58
|
-
return cfg;
|
|
59
|
-
const p = platform ?? '';
|
|
60
|
-
const t = sessionType ?? '';
|
|
61
|
-
const tid = targetId ?? '';
|
|
62
|
-
let best = null;
|
|
63
|
-
let bestSpec = -1;
|
|
64
|
-
for (const o of cfg.overrides) {
|
|
65
|
-
const parts = parseScopePattern(o.scope);
|
|
66
|
-
if (!matchScopeParts(parts, p, t, tid))
|
|
67
|
-
continue;
|
|
68
|
-
const spec = scopeSpecificity(parts);
|
|
69
|
-
if (spec > bestSpec) {
|
|
70
|
-
best = o;
|
|
71
|
-
bestSpec = spec;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
if (!best)
|
|
75
|
-
return cfg;
|
|
76
|
-
const merged = { ...cfg };
|
|
77
|
-
if (best.intervalMode !== undefined)
|
|
78
|
-
merged.intervalMode = best.intervalMode;
|
|
79
|
-
if (best.triggerOnAt !== undefined)
|
|
80
|
-
merged.triggerOnAt = best.triggerOnAt;
|
|
81
|
-
if (best.triggerOnPoke !== undefined)
|
|
82
|
-
merged.triggerOnPoke = best.triggerOnPoke;
|
|
83
|
-
if (best.triggerNames !== undefined)
|
|
84
|
-
merged.triggerNames = best.triggerNames;
|
|
85
|
-
if (best.muteKeywords !== undefined)
|
|
86
|
-
merged.muteKeywords = best.muteKeywords;
|
|
87
|
-
if (best.muteTimeSeconds !== undefined)
|
|
88
|
-
merged.muteTimeSeconds = best.muteTimeSeconds;
|
|
89
|
-
return merged;
|
|
90
|
-
}
|
|
91
|
-
function parseScopePattern(s) {
|
|
92
|
-
const parts = (s || '').split(':');
|
|
93
|
-
return {
|
|
94
|
-
platform: parts[0] || '*',
|
|
95
|
-
sessionType: parts[1] || '*',
|
|
96
|
-
targetId: parts[2] || '*',
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
function matchScopeParts(pat, p, t, tid) {
|
|
100
|
-
return ((pat.platform === '*' || pat.platform === '' || pat.platform === p) &&
|
|
101
|
-
(pat.sessionType === '*' || pat.sessionType === '' || pat.sessionType === t) &&
|
|
102
|
-
(pat.targetId === '*' || pat.targetId === '' || pat.targetId === tid));
|
|
103
|
-
}
|
|
104
|
-
function matchScopeString(raw, p, t, tid) {
|
|
105
|
-
return matchScopeParts(parseScopePattern(raw), p, t, tid);
|
|
106
|
-
}
|
|
107
|
-
function scopeSpecificity(pat) {
|
|
108
|
-
return ((pat.platform !== '*' && pat.platform !== '' ? 4 : 0) +
|
|
109
|
-
(pat.sessionType !== '*' && pat.sessionType !== '' ? 2 : 0) +
|
|
110
|
-
(pat.targetId !== '*' && pat.targetId !== '' ? 1 : 0));
|
|
111
|
-
}
|
|
112
68
|
function parseOverrides(raw) {
|
|
113
69
|
if (!Array.isArray(raw))
|
|
114
70
|
return [];
|
|
@@ -143,6 +99,30 @@ function parseOverrides(raw) {
|
|
|
143
99
|
if (typeof obj.muteTimeSeconds === 'number' && obj.muteTimeSeconds > 0) {
|
|
144
100
|
o.muteTimeSeconds = Math.floor(obj.muteTimeSeconds);
|
|
145
101
|
}
|
|
102
|
+
for (const k of [
|
|
103
|
+
'fixedInterval',
|
|
104
|
+
'activityScoreLower',
|
|
105
|
+
'activityScoreUpper',
|
|
106
|
+
'activityDecayMinutes',
|
|
107
|
+
'scoreDecayMinutes',
|
|
108
|
+
'idleTriggerMinutes',
|
|
109
|
+
'idleTriggerMaxMinutes',
|
|
110
|
+
]) {
|
|
111
|
+
const v = obj[k];
|
|
112
|
+
if (typeof v === 'number')
|
|
113
|
+
o[k] = v;
|
|
114
|
+
}
|
|
115
|
+
if (typeof obj.idleTriggerJitter === 'boolean')
|
|
116
|
+
o.idleTriggerJitter = obj.idleTriggerJitter;
|
|
117
|
+
if (typeof obj.idleTriggerPrompt === 'string' && obj.idleTriggerPrompt !== '') {
|
|
118
|
+
o.idleTriggerPrompt = obj.idleTriggerPrompt;
|
|
119
|
+
}
|
|
120
|
+
const sScope = obj.idleTriggerScope;
|
|
121
|
+
if (sScope === 'off' || sScope === 'session' || sScope === 'platform')
|
|
122
|
+
o.idleTriggerScope = sScope;
|
|
123
|
+
const sStyle = obj.idleTriggerStyle;
|
|
124
|
+
if (sStyle === 'exponential' || sStyle === 'fixed')
|
|
125
|
+
o.idleTriggerStyle = sStyle;
|
|
146
126
|
out.push(o);
|
|
147
127
|
}
|
|
148
128
|
return out;
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,qBAAqB;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { FlowControlService } from '@aalis/api-flow-control';
|
|
2
|
+
import { type GatewayService } from '@aalis/api-gateway';
|
|
3
|
+
import type { Logger, ServiceRef } from '@aalis/core';
|
|
4
|
+
import type { TriggerPolicyConfig } from './config.js';
|
|
5
|
+
import { type TriggerSessionState } from './state.js';
|
|
6
|
+
/** 调度器用到的能力:日志、网关与流控闸门(只读当前提供者),以及本插件此刻是否生效 */
|
|
7
|
+
export interface IdleCaps {
|
|
8
|
+
logger: Logger;
|
|
9
|
+
gateway: Pick<ServiceRef<GatewayService>, 'current'>;
|
|
10
|
+
flowControl: Pick<ServiceRef<FlowControlService>, 'current'>;
|
|
11
|
+
isActive(): boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function scheduleSessionIdle(caps: IdleCaps, cfg: TriggerPolicyConfig, state: TriggerSessionState, sessionId: string, reschedule: () => void): void;
|
|
14
|
+
export declare function clearSessionIdle(state: TriggerSessionState): void;
|
|
15
|
+
export declare class PlatformIdleScheduler {
|
|
16
|
+
private readonly caps;
|
|
17
|
+
private readonly cfg;
|
|
18
|
+
private readonly states;
|
|
19
|
+
private timer;
|
|
20
|
+
private running;
|
|
21
|
+
/** stop() 之后不再重排——tick 回调可能已在飞行中,回来时要认这面旗,否则留下僵尸定时器 */
|
|
22
|
+
private stopped;
|
|
23
|
+
/** start() 时刻——无任何活动记录时拿它当「最后一次活动」的基准 */
|
|
24
|
+
private startedAt;
|
|
25
|
+
constructor(caps: IdleCaps, cfg: TriggerPolicyConfig, states: Map<string, TriggerSessionState>);
|
|
26
|
+
start(): void;
|
|
27
|
+
stop(): void;
|
|
28
|
+
/** 距离全部会话静默达标还需多少 ms(返回 0 = 已达标) */
|
|
29
|
+
private timeUntilAllQuiet;
|
|
30
|
+
/** 选一个最适合主动开聊的会话(带该会话的有效提示词) */
|
|
31
|
+
private pickTarget;
|
|
32
|
+
/** 跑一次 tick(发没发出去都不影响重排间隔,故无返回值) */
|
|
33
|
+
private runOnce;
|
|
34
|
+
private schedule;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=idle-scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idle-scheduler.d.ts","sourceRoot":"","sources":["../src/idle-scheduler.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,KAAK,cAAc,EAA0B,MAAM,oBAAoB,CAAC;AACjF,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAkB,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtE,+CAA+C;AAC/C,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC,CAAC;IACrD,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,SAAS,CAAC,CAAC;IAC7D,QAAQ,IAAI,OAAO,CAAC;CACrB;AA8BD,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,QAAQ,EACd,GAAG,EAAE,mBAAmB,EACxB,KAAK,EAAE,mBAAmB,EAC1B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,IAAI,GACrB,IAAI,CAsCN;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAKjE;AAOD,qBAAa,qBAAqB;IAS9B,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAVzB,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,OAAO,CAAS;IACxB,uDAAuD;IACvD,OAAO,CAAC,OAAO,CAAS;IACxB,yCAAyC;IACzC,OAAO,CAAC,SAAS,CAAK;gBAGH,IAAI,EAAE,QAAQ,EACd,GAAG,EAAE,mBAAmB,EACxB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC;IAG3D,KAAK,IAAI,IAAI;IAMb,IAAI,IAAI,IAAI;IAQZ,oCAAoC;IACpC,OAAO,CAAC,iBAAiB;IAazB,gCAAgC;IAChC,OAAO,CAAC,UAAU;IAiBlB,oCAAoC;YACtB,OAAO;IA2BrB,OAAO,CAAC,QAAQ;CAiCjB"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// ----- 闲置触发调度器 -----
|
|
2
|
+
//
|
|
3
|
+
// session 范围:每会话一个 setTimeout,触发时合成 system 提示注入 gateway。
|
|
4
|
+
// platform 范围:跨平台一个 tick,挑"最久未联系"的 session 主动开聊。
|
|
5
|
+
// 到点时本插件不是生效的触发插件(trigger 服务胜者)就不开口:不注入,也不记为 bot 开口。
|
|
6
|
+
import { resolveEffectiveConfig } from '@aalis/api-gateway';
|
|
7
|
+
import { lastActivityOf } from './state.js';
|
|
8
|
+
const DEFAULT_PROMPT = '当前会话已长时间无消息,请根据人设主动开启一个轻松的话题或问候。不要提及"系统提示"或表明你是被触发发言的。';
|
|
9
|
+
function buildIdleMessage(sessionId, platform, prompt) {
|
|
10
|
+
return {
|
|
11
|
+
content: prompt?.trim() ? prompt : DEFAULT_PROMPT,
|
|
12
|
+
sessionId,
|
|
13
|
+
platform,
|
|
14
|
+
source: 'idle-trigger',
|
|
15
|
+
triggerType: 'idle',
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 经 gateway 注入,走完整入站相位链。gateway 是本插件的必需依赖,只在它丢失到调度收敛之间可能短暂缺席;
|
|
20
|
+
* 那时 inbound:message 同样无人消费(消费方就是 gateway 插件),这次注入只记一条 debug 放弃
|
|
21
|
+
*/
|
|
22
|
+
async function injectIdle(caps, msg) {
|
|
23
|
+
const gateway = caps.gateway.current;
|
|
24
|
+
if (!gateway) {
|
|
25
|
+
caps.logger.debug(`[trigger] 空闲触发放弃(gateway 缺席): session=${msg.sessionId}`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
await gateway.ingressMessage(msg);
|
|
29
|
+
}
|
|
30
|
+
// ===== session 范围调度 =====
|
|
31
|
+
export function scheduleSessionIdle(caps, cfg, state, sessionId, reschedule) {
|
|
32
|
+
clearSessionIdle(state);
|
|
33
|
+
if (cfg.idleTriggerScope !== 'session')
|
|
34
|
+
return;
|
|
35
|
+
if (cfg.idleTriggerMinutes <= 0)
|
|
36
|
+
return;
|
|
37
|
+
let delayMs;
|
|
38
|
+
if (cfg.idleTriggerStyle === 'exponential') {
|
|
39
|
+
delayMs = Math.min(cfg.idleTriggerMinutes * state.idleBackoff * 60 * 1000, cfg.idleTriggerMaxMinutes * 60 * 1000);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
delayMs = cfg.idleTriggerMinutes * 60 * 1000;
|
|
43
|
+
}
|
|
44
|
+
if (cfg.idleTriggerJitter) {
|
|
45
|
+
const jitter = delayMs * (0.1 * (Math.random() * 2 - 1));
|
|
46
|
+
delayMs = Math.max(60_000, delayMs + jitter);
|
|
47
|
+
}
|
|
48
|
+
state.idleTimer = setTimeout(async () => {
|
|
49
|
+
try {
|
|
50
|
+
// 本插件不生效、或禁言期(flow 相位也会吞,这里省掉一次注入)不开口:跳过本次并按原退避重排
|
|
51
|
+
const skip = !caps.isActive() ? '触发策略未生效' : caps.flowControl.current?.isMuted(sessionId) ? '禁言中' : '';
|
|
52
|
+
if (skip) {
|
|
53
|
+
caps.logger.debug(`[trigger] 空闲触发跳过(${skip}): session=${sessionId}`);
|
|
54
|
+
reschedule();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
caps.logger.info(`[trigger] 空闲触发: session=${sessionId} (退避 x${state.idleBackoff})`);
|
|
58
|
+
if (cfg.idleTriggerStyle === 'exponential') {
|
|
59
|
+
state.idleBackoff = Math.min(state.idleBackoff * 2, 64);
|
|
60
|
+
}
|
|
61
|
+
state.lastBotActivityAt = Date.now();
|
|
62
|
+
await injectIdle(caps, buildIdleMessage(sessionId, state.platform, cfg.idleTriggerPrompt));
|
|
63
|
+
reschedule();
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
caps.logger.warn(`空闲触发执行失败: ${err}`);
|
|
67
|
+
}
|
|
68
|
+
}, delayMs);
|
|
69
|
+
caps.logger.debug(`[trigger] 空闲触发已调度: session=${sessionId}, ${Math.round(delayMs / 60_000)}分钟后`);
|
|
70
|
+
}
|
|
71
|
+
export function clearSessionIdle(state) {
|
|
72
|
+
if (state.idleTimer) {
|
|
73
|
+
clearTimeout(state.idleTimer);
|
|
74
|
+
state.idleTimer = null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// ===== platform 范围调度 =====
|
|
78
|
+
/** 两轮 tick 之间的最小间隔(阈值更长则按阈值) */
|
|
79
|
+
const IDLE_RETRY_MIN_MS = 60_000;
|
|
80
|
+
export class PlatformIdleScheduler {
|
|
81
|
+
caps;
|
|
82
|
+
cfg;
|
|
83
|
+
states;
|
|
84
|
+
timer = null;
|
|
85
|
+
running = false;
|
|
86
|
+
/** stop() 之后不再重排——tick 回调可能已在飞行中,回来时要认这面旗,否则留下僵尸定时器 */
|
|
87
|
+
stopped = false;
|
|
88
|
+
/** start() 时刻——无任何活动记录时拿它当「最后一次活动」的基准 */
|
|
89
|
+
startedAt = 0;
|
|
90
|
+
constructor(caps, cfg, states) {
|
|
91
|
+
this.caps = caps;
|
|
92
|
+
this.cfg = cfg;
|
|
93
|
+
this.states = states;
|
|
94
|
+
}
|
|
95
|
+
start() {
|
|
96
|
+
this.stopped = false;
|
|
97
|
+
this.startedAt = Date.now();
|
|
98
|
+
this.schedule();
|
|
99
|
+
}
|
|
100
|
+
stop() {
|
|
101
|
+
this.stopped = true;
|
|
102
|
+
if (this.timer) {
|
|
103
|
+
clearTimeout(this.timer);
|
|
104
|
+
this.timer = null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/** 距离全部会话静默达标还需多少 ms(返回 0 = 已达标) */
|
|
108
|
+
timeUntilAllQuiet(thresholdMs) {
|
|
109
|
+
let maxLast = 0;
|
|
110
|
+
for (const s of this.states.values()) {
|
|
111
|
+
const last = lastActivityOf(s);
|
|
112
|
+
if (last > maxLast)
|
|
113
|
+
maxLast = last;
|
|
114
|
+
}
|
|
115
|
+
// 没有任何活动记录(states 为空)≠「已达标」:直接返回 0 会让 schedule 退化成每秒一 tick
|
|
116
|
+
// 的死转。改用 start() 时刻当基准——从启动起静默满一个阈值才算达标。
|
|
117
|
+
const since = maxLast || this.startedAt || Date.now();
|
|
118
|
+
const elapsed = Date.now() - since;
|
|
119
|
+
return Math.max(0, thresholdMs - elapsed);
|
|
120
|
+
}
|
|
121
|
+
/** 选一个最适合主动开聊的会话(带该会话的有效提示词) */
|
|
122
|
+
pickTarget() {
|
|
123
|
+
const flow = this.caps.flowControl.current;
|
|
124
|
+
let best = null;
|
|
125
|
+
for (const [sid, s] of this.states) {
|
|
126
|
+
// 禁言会话选了也会被 flow 相位吞掉;冷却对闲置注入只在这里把关(flow 相位对内部注入不查冷却),限速在 flow 相位(作用域内)还会再查一次
|
|
127
|
+
if (flow?.isMuted(sid) || flow?.isCoolingDown(sid) || flow?.isRateLimited(sid))
|
|
128
|
+
continue;
|
|
129
|
+
const e = resolveEffectiveConfig(this.cfg, s.platform, s.sessionType, s.targetId);
|
|
130
|
+
// per-scope 覆盖单独关掉('off')或改成 session 档的会话不能被 platform 档抓来开聊
|
|
131
|
+
if (e.idleTriggerScope !== 'platform')
|
|
132
|
+
continue;
|
|
133
|
+
const lastActivity = lastActivityOf(s);
|
|
134
|
+
if (!best || lastActivity < best.lastActivity) {
|
|
135
|
+
best = { sessionId: sid, state: s, lastActivity, prompt: e.idleTriggerPrompt };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return best;
|
|
139
|
+
}
|
|
140
|
+
/** 跑一次 tick(发没发出去都不影响重排间隔,故无返回值) */
|
|
141
|
+
async runOnce() {
|
|
142
|
+
if (this.running)
|
|
143
|
+
return;
|
|
144
|
+
this.running = true;
|
|
145
|
+
try {
|
|
146
|
+
if (!this.caps.isActive()) {
|
|
147
|
+
this.caps.logger.debug('[trigger] platform idle tick: 触发策略未生效,跳过');
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const target = this.pickTarget();
|
|
151
|
+
if (!target) {
|
|
152
|
+
this.caps.logger.debug('[trigger] platform idle tick: 无可发送候选,跳过');
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
this.caps.logger.info(`[trigger] platform idle tick: 主动开聊 → ${target.sessionId} ` +
|
|
156
|
+
`(idle=${Math.round((Date.now() - target.lastActivity) / 60_000)}min)`);
|
|
157
|
+
// 注入即记为 bot 开口:agent 对闲置提示沉默时,下一轮也不会再挑中同一会话
|
|
158
|
+
target.state.lastBotActivityAt = Date.now();
|
|
159
|
+
await injectIdle(this.caps, buildIdleMessage(target.sessionId, target.state.platform, target.prompt));
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
this.caps.logger.warn(`[trigger] platform idle tick 失败: ${err}`);
|
|
163
|
+
}
|
|
164
|
+
finally {
|
|
165
|
+
this.running = false;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
schedule(minDelayMs = 0) {
|
|
169
|
+
if (this.stopped)
|
|
170
|
+
return;
|
|
171
|
+
if (this.timer) {
|
|
172
|
+
clearTimeout(this.timer);
|
|
173
|
+
this.timer = null;
|
|
174
|
+
}
|
|
175
|
+
if (this.cfg.idleTriggerScope !== 'platform')
|
|
176
|
+
return;
|
|
177
|
+
if (this.cfg.idleTriggerMinutes <= 0)
|
|
178
|
+
return;
|
|
179
|
+
const baseMs = this.cfg.idleTriggerMinutes * 60_000;
|
|
180
|
+
let delay;
|
|
181
|
+
if (this.cfg.idleTriggerStrategy === 'fixed') {
|
|
182
|
+
delay = baseMs;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
delay = this.timeUntilAllQuiet(baseMs);
|
|
186
|
+
if (delay === 0)
|
|
187
|
+
delay = 1000;
|
|
188
|
+
}
|
|
189
|
+
if (delay < minDelayMs)
|
|
190
|
+
delay = minDelayMs;
|
|
191
|
+
this.timer = setTimeout(async () => {
|
|
192
|
+
if (this.cfg.idleTriggerStrategy === 'all-quiet') {
|
|
193
|
+
const remaining = this.timeUntilAllQuiet(baseMs);
|
|
194
|
+
if (remaining > 0) {
|
|
195
|
+
this.schedule();
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
await this.runOnce();
|
|
200
|
+
// 每轮之后**无条件**退避一个阈值量级:无候选时静默达标条件在 tick 之后仍然成立,
|
|
201
|
+
// 照 delay===0→1s 重排就是 1 Hz 死转。发没发出去都一样等,语义是「每轮之间至少隔一个阈值量级」。
|
|
202
|
+
this.schedule(Math.max(baseMs, IDLE_RETRY_MIN_MS));
|
|
203
|
+
}, delay);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=idle-scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idle-scheduler.js","sourceRoot":"","sources":["../src/idle-scheduler.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
import type
|
|
2
|
-
export type { TriggerDecision, TriggerKind, TriggerPolicyService } from './types.js';
|
|
1
|
+
import { type TriggerService } from '@aalis/api-trigger';
|
|
3
2
|
import { type TriggerPolicyConfig } from './config.js';
|
|
4
|
-
export declare const triggerPolicy: import("@aalis/core").ServiceDescriptor<TriggerPolicyService, import("@aalis/core").ServiceRef<TriggerPolicyService>>;
|
|
5
3
|
declare const _default: import("@aalis/core").PluginDefinition<{
|
|
6
4
|
logger: import("@aalis/core").ServiceDescriptor<(identity: symbol) => import("@aalis/core").Logger, import("@aalis/core").Logger>;
|
|
7
|
-
|
|
5
|
+
events: import("@aalis/core").ServiceDescriptor<(identity: symbol) => import("@aalis/core").Events, import("@aalis/core").Events>;
|
|
6
|
+
hooks: import("@aalis/core").ServiceDescriptor<import("@aalis/api-hooks").HookRegistry, import("@aalis/api-hooks").Hooks>;
|
|
7
|
+
lifecycle: import("@aalis/core").ServiceDescriptor<(identity: symbol) => import("@aalis/core").LifecycleCap, import("@aalis/core").LifecycleCap>;
|
|
8
8
|
config: import("@aalis/core").ServiceDescriptor<(identity: symbol) => Readonly<Record<string, unknown>>, Readonly<Record<string, unknown>>>;
|
|
9
9
|
provide: import("@aalis/core").ServiceDescriptor<(identity: symbol) => import("@aalis/core").Provide, import("@aalis/core").Provide>;
|
|
10
10
|
gateway: import("@aalis/core").ServiceDescriptor<import("@aalis/api-gateway").GatewayService, import("@aalis/core").ServiceRef<import("@aalis/api-gateway").GatewayService>>;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
/**
|
|
12
|
+
* trigger 由本插件自己提供,只能声明成 optional:写 required 会把激活闸架在自己的产出上。
|
|
13
|
+
* 经它判断本插件是不是生效的触发插件(服务胜者)。
|
|
14
|
+
*/
|
|
15
|
+
trigger: import("@aalis/core").OptionalUse<TriggerService, import("@aalis/core").ServiceRef<TriggerService>>;
|
|
16
|
+
flowControl: import("@aalis/core").OptionalUse<import("@aalis/api-flow-control").FlowControlService, import("@aalis/core").ServiceRef<import("@aalis/api-flow-control").FlowControlService>>;
|
|
17
|
+
persona: import("@aalis/core").OptionalUse<import("@aalis/api-persona").PersonaService, import("@aalis/core").ServiceRef<import("@aalis/api-persona").PersonaService>>;
|
|
18
|
+
sessionManager: import("@aalis/core").OptionalUse<import("@aalis/api-session-manager").SessionManagerService, import("@aalis/core").ServiceRef<import("@aalis/api-session-manager").SessionManagerService>>;
|
|
19
|
+
messageArchive: import("@aalis/core").OptionalUse<import("@aalis/api-message-archive").MessageArchiveService, import("@aalis/core").ServiceRef<import("@aalis/api-message-archive").MessageArchiveService>>;
|
|
14
20
|
}>;
|
|
15
21
|
export default _default;
|
|
16
22
|
export type { TriggerPolicyConfig };
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAOL,KAAK,cAAc,EAEpB,MAAM,oBAAoB,CAAC;AAK5B,OAAO,EAA0D,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;;;;;;;;;IA4K7G;;;OAGG;;;;;;;AAYL,wBAQG;AAwLH,YAAY,EAAE,mBAAmB,EAAE,CAAC"}
|