@aalis/plugin-tool-session 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.
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +799 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ace Nyan <ace@acenyan.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# @aalis/plugin-tool-session
|
|
2
|
+
|
|
3
|
+
会话历史读取工具。提供 `session_get_history` 工具与 `session-history` 服务,按 Aalis sessionId 读取指定会话最近若干条消息(默认仅同平台范围内)。
|
|
4
|
+
|
|
5
|
+
详见 [docs/plugins/plugin-tool-session.md](../../docs/plugins/plugin-tool-session.md)。
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @aalis/plugin-tool-session
|
|
11
|
+
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ConfigSchema, Context } from '@aalis/core';
|
|
2
|
+
import '@aalis/plugin-agent-api';
|
|
3
|
+
import '@aalis/plugin-tools-api';
|
|
4
|
+
import '@aalis/plugin-tool-session-api';
|
|
5
|
+
export declare const name = "@aalis/plugin-tool-session";
|
|
6
|
+
export declare const displayName = "\u4F1A\u8BDD\u5DE5\u5177";
|
|
7
|
+
export declare const subsystem = "session";
|
|
8
|
+
export declare const provides: string[];
|
|
9
|
+
export declare const inject: {
|
|
10
|
+
optional: string[];
|
|
11
|
+
};
|
|
12
|
+
export declare const configSchema: ConfigSchema;
|
|
13
|
+
/**
|
|
14
|
+
* 把一个时间值解析为毫秒时间戳。接受:
|
|
15
|
+
* - number:直接当毫秒时间戳(有限值)。
|
|
16
|
+
* - 纯数字字符串:当毫秒时间戳。
|
|
17
|
+
* - ISO 8601 等可被 `Date.parse` 识别的字符串。
|
|
18
|
+
* 无法解析时返回 `null`。
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseTimestamp(value: unknown): number | null;
|
|
21
|
+
/**
|
|
22
|
+
* 根据工具入参解析出时间区间 [fromTs, toTs](毫秒)。
|
|
23
|
+
* - 给定 `since`/`until`(ISO 或毫秒)→ 绝对区间;`until` 省略时取 `now`。
|
|
24
|
+
* - 否则给定 `within_minutes`(正数)→ 相对区间 [now - N 分钟, now]。
|
|
25
|
+
* - 都没给 → 返回 `null`(调用方退回纯条数检索)。
|
|
26
|
+
* 解析失败或区间非法时返回 `{ error }`。
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveTimeRange(args: {
|
|
29
|
+
within_minutes?: unknown;
|
|
30
|
+
since?: unknown;
|
|
31
|
+
until?: unknown;
|
|
32
|
+
}, now: number): {
|
|
33
|
+
fromTs: number;
|
|
34
|
+
toTs: number;
|
|
35
|
+
} | {
|
|
36
|
+
error: string;
|
|
37
|
+
} | null;
|
|
38
|
+
export declare function apply(ctx: Context, config: Record<string, unknown>): void;
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAOzD,OAAO,yBAAyB,CAAC;AACjC,OAAO,yBAAyB,CAAC;AACjC,OAAO,gCAAgC,CAAC;AAgHxC,eAAO,MAAM,IAAI,+BAA+B,CAAC;AACjD,eAAO,MAAM,WAAW,6BAAS,CAAC;AAClC,eAAO,MAAM,SAAS,YAAY,CAAC;AACnC,eAAO,MAAM,QAAQ,UAAsB,CAAC;AAC5C,eAAO,MAAM,MAAM;;CAElB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,YA4C1B,CAAC;AA8BF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAc5D;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EACpE,GAAG,EAAE,MAAM,GACV;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAmC7D;AA+nBD,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAWzE"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,799 @@
|
|
|
1
|
+
import { resolvePlatformBySession } from '@aalis/plugin-platform-api';
|
|
2
|
+
import { useToolService } from '@aalis/plugin-tools-api';
|
|
3
|
+
import '@aalis/plugin-agent-api';
|
|
4
|
+
import '@aalis/plugin-tools-api';
|
|
5
|
+
import '@aalis/plugin-tool-session-api';
|
|
6
|
+
// ===== 跨会话委派:proactive depth 防雪崩 =====
|
|
7
|
+
// 防止 A→B→C→... 无限链;任一会话被 delegate 进入 proactive 链路后,链上下一跳禁止再次 delegate。
|
|
8
|
+
const PROACTIVE_DEPTH_MAX = 1;
|
|
9
|
+
const PROACTIVE_DEPTH_TTL_MS = 10 * 60 * 1000;
|
|
10
|
+
const proactiveDepth = new Map();
|
|
11
|
+
function getProactiveDepth(sessionId) {
|
|
12
|
+
const entry = proactiveDepth.get(sessionId);
|
|
13
|
+
if (!entry)
|
|
14
|
+
return 0;
|
|
15
|
+
if (entry.expiresAt <= Date.now()) {
|
|
16
|
+
proactiveDepth.delete(sessionId);
|
|
17
|
+
return 0;
|
|
18
|
+
}
|
|
19
|
+
return entry.depth;
|
|
20
|
+
}
|
|
21
|
+
function setProactiveDepth(sessionId, depth) {
|
|
22
|
+
proactiveDepth.set(sessionId, { depth, expiresAt: Date.now() + PROACTIVE_DEPTH_TTL_MS });
|
|
23
|
+
}
|
|
24
|
+
// ===== 跨会话委派:近期派发记录(提醒型,不硬挡) =====
|
|
25
|
+
// 记录每个 (target_session_id, task) 最近一次派发状态。
|
|
26
|
+
// 下一次同目标派发时,在拼装给 target agent 的 task 前注入 META 提醒,
|
|
27
|
+
// 让 target agent 自主判断是否需要重发。不防止派发本身。
|
|
28
|
+
const RECENT_DELEGATION_TTL_MS = 60 * 1000;
|
|
29
|
+
const RECENT_DELEGATION_MAX = 256; // 防止无限增长
|
|
30
|
+
const recentDelegations = new Map();
|
|
31
|
+
function recentDelegationKey(targetSessionId, taskHash) {
|
|
32
|
+
return `${targetSessionId}::${taskHash}`;
|
|
33
|
+
}
|
|
34
|
+
function hashTask(task) {
|
|
35
|
+
// djb2 (xor variant):非密码学,零依赖,仅用于 60s 内区分 task 文本
|
|
36
|
+
const s = task.trim();
|
|
37
|
+
let h = 5381;
|
|
38
|
+
for (let i = 0; i < s.length; i++) {
|
|
39
|
+
h = (((h << 5) + h) ^ s.charCodeAt(i)) | 0;
|
|
40
|
+
}
|
|
41
|
+
return (h >>> 0).toString(16).padStart(8, '0');
|
|
42
|
+
}
|
|
43
|
+
function pruneRecentDelegations(now) {
|
|
44
|
+
for (const [key, entry] of recentDelegations) {
|
|
45
|
+
if (entry.expiresAt <= now)
|
|
46
|
+
recentDelegations.delete(key);
|
|
47
|
+
}
|
|
48
|
+
// 超上限时删最早的
|
|
49
|
+
if (recentDelegations.size > RECENT_DELEGATION_MAX) {
|
|
50
|
+
const oldest = [...recentDelegations.entries()].sort((a, b) => a[1].firedAt - b[1].firedAt);
|
|
51
|
+
for (let i = 0; i < oldest.length - RECENT_DELEGATION_MAX; i++) {
|
|
52
|
+
recentDelegations.delete(oldest[i][0]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function findRecentDelegationsForTarget(targetSessionId, now) {
|
|
57
|
+
const prefix = `${targetSessionId}::`;
|
|
58
|
+
const list = [];
|
|
59
|
+
for (const [key, entry] of recentDelegations) {
|
|
60
|
+
if (entry.expiresAt <= now)
|
|
61
|
+
continue;
|
|
62
|
+
if (!key.startsWith(prefix))
|
|
63
|
+
continue;
|
|
64
|
+
list.push(entry);
|
|
65
|
+
}
|
|
66
|
+
list.sort((a, b) => b.firedAt - a.firedAt);
|
|
67
|
+
return list;
|
|
68
|
+
}
|
|
69
|
+
function buildDelegationMetaBlock(sourceSessionId, targetSessionId, task, recents, now) {
|
|
70
|
+
void targetSessionId;
|
|
71
|
+
const lines = [];
|
|
72
|
+
lines.push('[跨会话委派 META]');
|
|
73
|
+
lines.push(`· 来源会话:${sourceSessionId}`);
|
|
74
|
+
lines.push('· 提醒:你本轮的对外回复内容会原样发送到当前会话所在平台(群/私聊/...)。');
|
|
75
|
+
lines.push('· 生成回复前请先回看你最近 history:若你认为本任务已经完成、或本轮要写的内容与上一条对外回复实质重复,');
|
|
76
|
+
lines.push(' 请输出空回复(不再对外发送),按你所属 persona / output 约定填写必要的内部状态字段即可。');
|
|
77
|
+
if (recents.length > 0) {
|
|
78
|
+
lines.push(`· 检测:60s 内本目标会话 已收到 ${recents.length} 次同/近期任务。最近的:`);
|
|
79
|
+
for (let i = 0; i < Math.min(recents.length, 3); i++) {
|
|
80
|
+
const r = recents[i];
|
|
81
|
+
const ageSec = Math.round((now - r.firedAt) / 1000);
|
|
82
|
+
const reply = r.lastReplyPreview ? ` reply="${r.lastReplyPreview}"` : '';
|
|
83
|
+
lines.push(` - ${ageSec}s 前 · from=${r.sourceSessionId} · status=${r.status}${reply} · task="${r.taskPreview}"`);
|
|
84
|
+
}
|
|
85
|
+
lines.push(' 若确认重复,请依上面提醒处理。');
|
|
86
|
+
}
|
|
87
|
+
lines.push('[任务正文]');
|
|
88
|
+
lines.push(task);
|
|
89
|
+
return lines.join('\n');
|
|
90
|
+
}
|
|
91
|
+
// ===== 插件元数据 =====
|
|
92
|
+
export const name = '@aalis/plugin-tool-session';
|
|
93
|
+
export const displayName = '会话工具';
|
|
94
|
+
export const subsystem = 'session';
|
|
95
|
+
export const provides = ['session-history'];
|
|
96
|
+
export const inject = {
|
|
97
|
+
optional: ['memory'],
|
|
98
|
+
};
|
|
99
|
+
export const configSchema = {
|
|
100
|
+
enabled: { type: 'boolean', label: '启用会话历史读取工具', default: true },
|
|
101
|
+
maxLimit: {
|
|
102
|
+
type: 'number',
|
|
103
|
+
label: '单次最多读取条数',
|
|
104
|
+
default: 100,
|
|
105
|
+
description: 'session_get_history 一次能返回的硬上限;LLM 传入 limit 超过此值会被 cap。建议 50~200。',
|
|
106
|
+
},
|
|
107
|
+
defaultLimit: {
|
|
108
|
+
type: 'number',
|
|
109
|
+
label: '默认读取条数(LLM 不传 limit 时)',
|
|
110
|
+
default: 20,
|
|
111
|
+
description: '不能超过 maxLimit。调高可让 agent 被动获取更多上下文,代价是 token 预算。',
|
|
112
|
+
},
|
|
113
|
+
scope: {
|
|
114
|
+
type: 'select',
|
|
115
|
+
label: '允许读取范围',
|
|
116
|
+
default: 'platform',
|
|
117
|
+
options: [
|
|
118
|
+
{ label: '仅当前会话', value: 'current' },
|
|
119
|
+
{ label: '同平台会话', value: 'platform' },
|
|
120
|
+
{ label: '全部会话', value: 'all' },
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
includeArchivedDefault: { type: 'boolean', label: '默认包含已归档消息', default: false },
|
|
124
|
+
perMessageMaxChars: {
|
|
125
|
+
type: 'number',
|
|
126
|
+
label: '每条消息截断字数',
|
|
127
|
+
default: 0,
|
|
128
|
+
description: '返给 LLM 的每条历史消息的字符上限;0 = 不截断(推荐)。超出会以「剩余 N 字符未展示」明示。',
|
|
129
|
+
},
|
|
130
|
+
crossSessionEnabled: {
|
|
131
|
+
type: 'boolean',
|
|
132
|
+
label: '启用跨会话委派 (delegate_to_session / list_known_sessions)',
|
|
133
|
+
default: true,
|
|
134
|
+
description: '允许 agent 列出其他活跃会话并向其派发任务(如私聊→群聊、跨平台委派)。受 proactive-depth 与平台限速保护。',
|
|
135
|
+
},
|
|
136
|
+
crossSessionDefaultTimeoutSec: {
|
|
137
|
+
type: 'number',
|
|
138
|
+
label: '跨会话委派默认等待秒数',
|
|
139
|
+
default: 60,
|
|
140
|
+
description: 'delegate_to_session 在未显式指定 timeout_seconds 时使用的等待上限。',
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
/** 无原生区间查询的后端:区间检索退回扫描历史的最大条数(best-effort 上界,防 OOM) */
|
|
144
|
+
const RANGE_FALLBACK_SCAN = 5000;
|
|
145
|
+
// ===== 时间区间解析(纯函数,单测覆盖见 test/plugins/session-history-range.test.ts) =====
|
|
146
|
+
/**
|
|
147
|
+
* 把一个时间值解析为毫秒时间戳。接受:
|
|
148
|
+
* - number:直接当毫秒时间戳(有限值)。
|
|
149
|
+
* - 纯数字字符串:当毫秒时间戳。
|
|
150
|
+
* - ISO 8601 等可被 `Date.parse` 识别的字符串。
|
|
151
|
+
* 无法解析时返回 `null`。
|
|
152
|
+
*/
|
|
153
|
+
export function parseTimestamp(value) {
|
|
154
|
+
if (value == null || value === '')
|
|
155
|
+
return null;
|
|
156
|
+
if (typeof value === 'number')
|
|
157
|
+
return Number.isFinite(value) ? value : null;
|
|
158
|
+
if (typeof value === 'string') {
|
|
159
|
+
const trimmed = value.trim();
|
|
160
|
+
if (trimmed === '')
|
|
161
|
+
return null;
|
|
162
|
+
if (/^\d+$/.test(trimmed)) {
|
|
163
|
+
const n = Number(trimmed);
|
|
164
|
+
return Number.isFinite(n) ? n : null;
|
|
165
|
+
}
|
|
166
|
+
const parsed = Date.parse(trimmed);
|
|
167
|
+
return Number.isNaN(parsed) ? null : parsed;
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* 根据工具入参解析出时间区间 [fromTs, toTs](毫秒)。
|
|
173
|
+
* - 给定 `since`/`until`(ISO 或毫秒)→ 绝对区间;`until` 省略时取 `now`。
|
|
174
|
+
* - 否则给定 `within_minutes`(正数)→ 相对区间 [now - N 分钟, now]。
|
|
175
|
+
* - 都没给 → 返回 `null`(调用方退回纯条数检索)。
|
|
176
|
+
* 解析失败或区间非法时返回 `{ error }`。
|
|
177
|
+
*/
|
|
178
|
+
export function resolveTimeRange(args, now) {
|
|
179
|
+
const hasSince = args.since != null && args.since !== '';
|
|
180
|
+
const hasUntil = args.until != null && args.until !== '';
|
|
181
|
+
const hasWithin = args.within_minutes != null && args.within_minutes !== '';
|
|
182
|
+
if (hasSince || hasUntil) {
|
|
183
|
+
let fromTs = 0;
|
|
184
|
+
if (hasSince) {
|
|
185
|
+
const parsed = parseTimestamp(args.since);
|
|
186
|
+
if (parsed == null) {
|
|
187
|
+
return { error: `无法解析 since 时间:${String(args.since)}(请用 ISO 8601 或毫秒时间戳)` };
|
|
188
|
+
}
|
|
189
|
+
fromTs = parsed;
|
|
190
|
+
}
|
|
191
|
+
let toTs = now;
|
|
192
|
+
if (hasUntil) {
|
|
193
|
+
const parsed = parseTimestamp(args.until);
|
|
194
|
+
if (parsed == null) {
|
|
195
|
+
return { error: `无法解析 until 时间:${String(args.until)}(请用 ISO 8601 或毫秒时间戳)` };
|
|
196
|
+
}
|
|
197
|
+
toTs = parsed;
|
|
198
|
+
}
|
|
199
|
+
if (fromTs > toTs)
|
|
200
|
+
return { error: 'since 不能晚于 until' };
|
|
201
|
+
return { fromTs, toTs };
|
|
202
|
+
}
|
|
203
|
+
if (hasWithin) {
|
|
204
|
+
const minutes = Number(args.within_minutes);
|
|
205
|
+
if (!Number.isFinite(minutes) || minutes <= 0) {
|
|
206
|
+
return { error: `within_minutes 必须为正数:${String(args.within_minutes)}` };
|
|
207
|
+
}
|
|
208
|
+
return { fromTs: now - minutes * 60_000, toTs: now };
|
|
209
|
+
}
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
function resolveConfig(raw) {
|
|
213
|
+
const scopeRaw = raw.scope;
|
|
214
|
+
const scope = scopeRaw === 'current' || scopeRaw === 'all' ? scopeRaw : 'platform';
|
|
215
|
+
const maxLimit = Math.max(1, Math.min(1000, Number(raw.maxLimit) || 100));
|
|
216
|
+
const defaultLimitRaw = Math.max(1, Math.floor(Number(raw.defaultLimit) || 20));
|
|
217
|
+
return {
|
|
218
|
+
enabled: raw.enabled !== false,
|
|
219
|
+
maxLimit,
|
|
220
|
+
defaultLimit: Math.min(defaultLimitRaw, maxLimit),
|
|
221
|
+
scope,
|
|
222
|
+
includeArchivedDefault: raw.includeArchivedDefault === true,
|
|
223
|
+
perMessageMaxChars: Math.max(0, Number(raw.perMessageMaxChars) || 0),
|
|
224
|
+
crossSessionEnabled: raw.crossSessionEnabled !== false,
|
|
225
|
+
crossSessionDefaultTimeoutSec: Number(raw.crossSessionDefaultTimeoutSec) || 60,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function parsePlatform(sessionId) {
|
|
229
|
+
return sessionId.split(':')[0] ?? '';
|
|
230
|
+
}
|
|
231
|
+
function formatHistoryMessage(message, index, perMessageMaxChars) {
|
|
232
|
+
const text = typeof message.content === 'string'
|
|
233
|
+
? message.content
|
|
234
|
+
: message.content == null
|
|
235
|
+
? ''
|
|
236
|
+
: JSON.stringify(message.content);
|
|
237
|
+
const content = perMessageMaxChars > 0 && text.length > perMessageMaxChars
|
|
238
|
+
? `${text.slice(0, perMessageMaxChars)}…[已截断,还剩 ${text.length - perMessageMaxChars} 个字符未展示]`
|
|
239
|
+
: text;
|
|
240
|
+
return {
|
|
241
|
+
index,
|
|
242
|
+
role: message.role,
|
|
243
|
+
content,
|
|
244
|
+
timestamp: message.timestamp ?? null,
|
|
245
|
+
name: message.name ?? null,
|
|
246
|
+
metadata: message.metadata ?? undefined,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
function canReadSessionHistory(currentSessionId, targetSessionId, currentPlatform, scope, checkers, callCtx) {
|
|
250
|
+
// 0. scope 粗筛
|
|
251
|
+
if (targetSessionId === currentSessionId) {
|
|
252
|
+
// 同会话仍允许平台 checker 表态(防御性)
|
|
253
|
+
}
|
|
254
|
+
else if (scope === 'current') {
|
|
255
|
+
return { ok: false, reason: '当前配置仅允许读取当前会话历史' };
|
|
256
|
+
}
|
|
257
|
+
else if (scope === 'platform') {
|
|
258
|
+
const current = currentPlatform || parsePlatform(currentSessionId);
|
|
259
|
+
const target = parsePlatform(targetSessionId);
|
|
260
|
+
if (!current || !target || current !== target) {
|
|
261
|
+
return {
|
|
262
|
+
ok: false,
|
|
263
|
+
reason: `当前配置仅允许读取同平台会话历史(当前=${current || 'unknown'}, 目标=${target || 'unknown'})`,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// scope === 'all' 直接走 checker 链
|
|
268
|
+
// 1. 找匹配目标 platform 的 checker,any-deny 短路;无匹配 checker 默认通过
|
|
269
|
+
const targetPlatform = parsePlatform(targetSessionId);
|
|
270
|
+
const matched = checkers.filter(c => c.platform === targetPlatform);
|
|
271
|
+
for (const checker of matched) {
|
|
272
|
+
const verdict = checker.check({ currentSessionId, targetSessionId, callCtx });
|
|
273
|
+
if (verdict?.decision === 'deny') {
|
|
274
|
+
return { ok: false, reason: verdict.reason || `平台 ${targetPlatform} 拒绝此次跨会话访问` };
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return { ok: true };
|
|
278
|
+
}
|
|
279
|
+
function createSessionHistoryService(ctx, cfg) {
|
|
280
|
+
const checkers = [];
|
|
281
|
+
return {
|
|
282
|
+
registerAccessChecker(checker) {
|
|
283
|
+
checkers.push(checker);
|
|
284
|
+
return () => {
|
|
285
|
+
const idx = checkers.indexOf(checker);
|
|
286
|
+
if (idx >= 0)
|
|
287
|
+
checkers.splice(idx, 1);
|
|
288
|
+
};
|
|
289
|
+
},
|
|
290
|
+
async getHistory(options, callCtx) {
|
|
291
|
+
const memory = ctx.getService('memory');
|
|
292
|
+
if (!memory)
|
|
293
|
+
return { error: 'memory 服务不可用' };
|
|
294
|
+
const targetSessionId = String(options.sessionId ?? '').trim();
|
|
295
|
+
if (!targetSessionId)
|
|
296
|
+
return { error: 'sessionId 不能为空' };
|
|
297
|
+
const verdict = canReadSessionHistory(callCtx.sessionId, targetSessionId, callCtx.platform, cfg.scope, checkers, callCtx);
|
|
298
|
+
if (!verdict.ok)
|
|
299
|
+
return { error: verdict.reason };
|
|
300
|
+
const limit = Math.max(1, Math.min(cfg.maxLimit, Math.floor(Number(options.limit) || cfg.defaultLimit)));
|
|
301
|
+
const includeArchived = typeof options.includeArchived === 'boolean' ? options.includeArchived : cfg.includeArchivedDefault;
|
|
302
|
+
// 区间检索模式:给定 sinceTs / untilTs 任一即进入。区间查询天然含归档(含完整记录),
|
|
303
|
+
// 故 include_archived 在此模式下不再区分,结果统一回显 includeArchived: true。
|
|
304
|
+
const hasRange = typeof options.sinceTs === 'number' || typeof options.untilTs === 'number';
|
|
305
|
+
try {
|
|
306
|
+
if (hasRange) {
|
|
307
|
+
const fromTs = typeof options.sinceTs === 'number' ? options.sinceTs : 0;
|
|
308
|
+
const toTs = typeof options.untilTs === 'number' ? options.untilTs : Date.now();
|
|
309
|
+
let ranged;
|
|
310
|
+
// 区间后端(getMessagesBySessionRange)天然含归档;仅当退化到 getHistory 时才是「仅活跃」。
|
|
311
|
+
let includesArchived = true;
|
|
312
|
+
if (memory.getMessagesBySessionRange) {
|
|
313
|
+
ranged = await memory.getMessagesBySessionRange(targetSessionId, fromTs, toTs);
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
// 后端不支持原生区间查询:退回扫描历史 + 客户端按时间过滤(best-effort,很早的窗口可能不全)。
|
|
317
|
+
let base;
|
|
318
|
+
if (memory.getFullHistory) {
|
|
319
|
+
base = await memory.getFullHistory(targetSessionId, RANGE_FALLBACK_SCAN);
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
base = await memory.getHistory(targetSessionId, RANGE_FALLBACK_SCAN);
|
|
323
|
+
includesArchived = false; // getHistory 不含归档,诚实回显
|
|
324
|
+
}
|
|
325
|
+
ranged = base.filter(m => {
|
|
326
|
+
const ts = m.timestamp ?? 0;
|
|
327
|
+
return ts >= fromTs && ts <= toTs;
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
// 区间查询按时间升序返回。窗口内超过 limit 时取**最早**的 limit 条(按阅读顺序、与「区间」语义一致),
|
|
331
|
+
// 并以 truncated 明示「窗口内还有更多、请缩小窗口」——不再静默丢弃。
|
|
332
|
+
// 注意:原生区间后端通常有约 500 条的硬上限,极大窗口可能在后端那步就已截断,故 truncated 为保守信号。
|
|
333
|
+
const sliced = ranged.slice(0, limit);
|
|
334
|
+
const truncated = ranged.length > sliced.length;
|
|
335
|
+
const result = {
|
|
336
|
+
ok: true,
|
|
337
|
+
sessionId: targetSessionId,
|
|
338
|
+
count: sliced.length,
|
|
339
|
+
limit,
|
|
340
|
+
includeArchived: includesArchived,
|
|
341
|
+
range: { fromTs, toTs },
|
|
342
|
+
...(truncated ? { truncated: true } : {}),
|
|
343
|
+
messages: sliced.map((message, index) => formatHistoryMessage(message, index + 1, cfg.perMessageMaxChars)),
|
|
344
|
+
};
|
|
345
|
+
return result;
|
|
346
|
+
}
|
|
347
|
+
const history = includeArchived && memory.getFullHistory
|
|
348
|
+
? await memory.getFullHistory(targetSessionId, limit)
|
|
349
|
+
: await memory.getHistory(targetSessionId, limit);
|
|
350
|
+
const result = {
|
|
351
|
+
ok: true,
|
|
352
|
+
sessionId: targetSessionId,
|
|
353
|
+
count: history.length,
|
|
354
|
+
limit,
|
|
355
|
+
includeArchived: includeArchived && !!memory.getFullHistory,
|
|
356
|
+
messages: history.map((message, index) => formatHistoryMessage(message, index + 1, cfg.perMessageMaxChars)),
|
|
357
|
+
};
|
|
358
|
+
return result;
|
|
359
|
+
}
|
|
360
|
+
catch (err) {
|
|
361
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
362
|
+
ctx.logger.warn(`session-history 读取失败 (${targetSessionId}): ${message}`);
|
|
363
|
+
return { error: `读取会话历史失败: ${message}` };
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
function registerSessionHistoryTools(ctx, historyService, cfg) {
|
|
369
|
+
useToolService(ctx).registerGroup({
|
|
370
|
+
name: 'session-history',
|
|
371
|
+
label: '会话历史读取',
|
|
372
|
+
description: '按 Aalis sessionId 读取近期会话历史,用于核实跨会话上下文',
|
|
373
|
+
});
|
|
374
|
+
useToolService(ctx).register({
|
|
375
|
+
groups: ['session-history'],
|
|
376
|
+
definition: {
|
|
377
|
+
type: 'function',
|
|
378
|
+
function: {
|
|
379
|
+
name: 'session_get_history',
|
|
380
|
+
description: [
|
|
381
|
+
'按 Aalis sessionId 读取指定会话的消息。',
|
|
382
|
+
'两种模式:',
|
|
383
|
+
'①【条数】默认——读最近若干条(limit 控制)。',
|
|
384
|
+
'②【时间区间】给定 within_minutes(最近 N 分钟)或 since/until(绝对区间)时启用——',
|
|
385
|
+
' 取该会话落在区间内的消息(含归档完整记录),按时间正序返回最早的 limit 条;',
|
|
386
|
+
' 窗口内更多时结果带 truncated:true(请缩小时间窗再查)。',
|
|
387
|
+
'适合在用户明确提到另一个会话、需要核实原文上下文、或要查「某段时间里聊了什么」时使用。',
|
|
388
|
+
'默认只允许读取配置范围内的会话;不要把它当作全局搜索工具,语义检索请用 memory_recall。',
|
|
389
|
+
].join('\n'),
|
|
390
|
+
parameters: {
|
|
391
|
+
type: 'object',
|
|
392
|
+
properties: {
|
|
393
|
+
session_id: { type: 'string', description: '目标 Aalis sessionId,例如 onebot:10000:group:20001' },
|
|
394
|
+
limit: {
|
|
395
|
+
type: 'number',
|
|
396
|
+
description: `读取多少条(区间模式下为区间内上限),默认 ${cfg.defaultLimit},最多 ${cfg.maxLimit}`,
|
|
397
|
+
},
|
|
398
|
+
include_archived: {
|
|
399
|
+
type: 'boolean',
|
|
400
|
+
description: '是否包含已归档消息(仅条数模式生效;区间模式恒含归档)。默认使用插件配置。',
|
|
401
|
+
},
|
|
402
|
+
within_minutes: {
|
|
403
|
+
type: 'number',
|
|
404
|
+
description: '时间区间:最近 N 分钟内的消息。与 since/until 互斥,后者优先。',
|
|
405
|
+
},
|
|
406
|
+
since: {
|
|
407
|
+
type: 'string',
|
|
408
|
+
description: '时间区间下界,ISO 8601(如 2026-06-15T08:00:00Z)或毫秒时间戳。给定 since/until 即进入区间模式。',
|
|
409
|
+
},
|
|
410
|
+
until: {
|
|
411
|
+
type: 'string',
|
|
412
|
+
description: '时间区间上界,ISO 8601 或毫秒时间戳。省略时默认取「现在」。',
|
|
413
|
+
},
|
|
414
|
+
},
|
|
415
|
+
required: ['session_id'],
|
|
416
|
+
additionalProperties: false,
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
handler: async (args, callCtx) => {
|
|
421
|
+
const targetSessionId = String(args.session_id ?? '').trim();
|
|
422
|
+
if (!targetSessionId)
|
|
423
|
+
return JSON.stringify({ error: 'session_id 不能为空' });
|
|
424
|
+
const range = resolveTimeRange(args, Date.now());
|
|
425
|
+
if (range && 'error' in range)
|
|
426
|
+
return JSON.stringify({ error: range.error });
|
|
427
|
+
const result = await historyService.getHistory({
|
|
428
|
+
sessionId: targetSessionId,
|
|
429
|
+
limit: Number(args.limit) || undefined,
|
|
430
|
+
includeArchived: typeof args.include_archived === 'boolean' ? args.include_archived : undefined,
|
|
431
|
+
sinceTs: range ? range.fromTs : undefined,
|
|
432
|
+
untilTs: range ? range.toTs : undefined,
|
|
433
|
+
}, callCtx);
|
|
434
|
+
return JSON.stringify(result);
|
|
435
|
+
},
|
|
436
|
+
});
|
|
437
|
+
ctx.logger.info('会话历史读取工具已注册');
|
|
438
|
+
}
|
|
439
|
+
function registerCrossSessionTools(ctx, cfg) {
|
|
440
|
+
useToolService(ctx).registerGroup({
|
|
441
|
+
name: 'session-delegate',
|
|
442
|
+
label: '跨会话派发',
|
|
443
|
+
description: '向已存在的其他会话(如另一个群、另一个 QQ 好友、另一个平台)派发任务并可选等待结果。',
|
|
444
|
+
});
|
|
445
|
+
// ---- list_known_sessions ----
|
|
446
|
+
// 列出最近活跃的会话(按平台/最近活跃时间),供 agent 在 delegate 前发现可派发目标,
|
|
447
|
+
// 避免凭空拼接 sessionId 出错。基于 memory 的 getRecentMessagesAcrossSessions 能力。
|
|
448
|
+
useToolService(ctx).register({
|
|
449
|
+
groups: ['session-delegate'],
|
|
450
|
+
definition: {
|
|
451
|
+
type: 'function',
|
|
452
|
+
function: {
|
|
453
|
+
name: 'list_known_sessions',
|
|
454
|
+
description: [
|
|
455
|
+
'列出 agent 最近活跃过的会话,按最近活动时间倒序返回,用于 delegate_to_session 之前发现目标 sessionId。',
|
|
456
|
+
'',
|
|
457
|
+
'【返回字段】',
|
|
458
|
+
'- session_id:完整 sessionId(可直接用于 delegate_to_session 的 target_session_id)',
|
|
459
|
+
'- platform:所属平台(如 onebot / webui / scheduler)',
|
|
460
|
+
'- last_activity_ts:最近一条消息的时间戳(毫秒)',
|
|
461
|
+
'- preview:最近一条消息的内容预览(截断到 80 字)',
|
|
462
|
+
'',
|
|
463
|
+
'【注意】',
|
|
464
|
+
'- 仅返回 memory 中存在历史的会话;从未对话过的群/好友需要用平台专属工具(如 onebot_get_group_list)查询。',
|
|
465
|
+
'- 默认排除当前会话本身。',
|
|
466
|
+
].join('\n'),
|
|
467
|
+
parameters: {
|
|
468
|
+
type: 'object',
|
|
469
|
+
properties: {
|
|
470
|
+
limit: {
|
|
471
|
+
type: 'number',
|
|
472
|
+
description: '最大返回会话数(默认 20,最大 100)',
|
|
473
|
+
},
|
|
474
|
+
platform: {
|
|
475
|
+
type: 'string',
|
|
476
|
+
description: '仅返回指定平台的会话(如 "onebot");省略则不限平台',
|
|
477
|
+
},
|
|
478
|
+
since_hours: {
|
|
479
|
+
type: 'number',
|
|
480
|
+
description: '仅返回最近 N 小时内有活动的会话(默认 168 小时 = 7 天)',
|
|
481
|
+
},
|
|
482
|
+
},
|
|
483
|
+
required: [],
|
|
484
|
+
additionalProperties: false,
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
handler: async (args, callCtx) => {
|
|
489
|
+
const memory = ctx.getService('memory');
|
|
490
|
+
if (!memory?.getRecentMessagesAcrossSessions) {
|
|
491
|
+
return JSON.stringify({
|
|
492
|
+
error: '当前 memory 服务不支持 getRecentMessagesAcrossSessions 能力',
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
const limit = Math.min(100, Math.max(1, Number(args.limit) || 20));
|
|
496
|
+
const sinceHours = Number.isFinite(Number(args.since_hours)) && Number(args.since_hours) > 0 ? Number(args.since_hours) : 168;
|
|
497
|
+
const platformFilter = typeof args.platform === 'string' && args.platform.trim().length > 0 ? args.platform.trim() : undefined;
|
|
498
|
+
const sinceTs = Date.now() - sinceHours * 3600 * 1000;
|
|
499
|
+
// 多取一些消息再按 session 聚合,确保 limit 个会话能凑齐
|
|
500
|
+
const records = await memory.getRecentMessagesAcrossSessions({
|
|
501
|
+
limit: Math.max(limit * 10, 200),
|
|
502
|
+
sinceTs,
|
|
503
|
+
platform: platformFilter,
|
|
504
|
+
excludeSessionIds: callCtx.sessionId ? [callCtx.sessionId] : undefined,
|
|
505
|
+
roles: ['user', 'assistant'],
|
|
506
|
+
});
|
|
507
|
+
const bySession = new Map();
|
|
508
|
+
for (const rec of records) {
|
|
509
|
+
const ts = rec.message.timestamp ?? 0;
|
|
510
|
+
const existing = bySession.get(rec.sessionId);
|
|
511
|
+
if (!existing || ts > existing.lastTs) {
|
|
512
|
+
const content = typeof rec.message.content === 'string' ? rec.message.content : '';
|
|
513
|
+
const preview = content.length > 80 ? `${content.slice(0, 80)}...` : content;
|
|
514
|
+
const platform = rec.message.metadata?.platform != null
|
|
515
|
+
? String(rec.message.metadata.platform)
|
|
516
|
+
: rec.sessionId.split(':')[0] || undefined;
|
|
517
|
+
bySession.set(rec.sessionId, {
|
|
518
|
+
sessionId: rec.sessionId,
|
|
519
|
+
platform,
|
|
520
|
+
lastTs: ts,
|
|
521
|
+
preview,
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
const items = [...bySession.values()]
|
|
526
|
+
.sort((a, b) => b.lastTs - a.lastTs)
|
|
527
|
+
.slice(0, limit)
|
|
528
|
+
.map(s => ({
|
|
529
|
+
session_id: s.sessionId,
|
|
530
|
+
platform: s.platform,
|
|
531
|
+
last_activity_ts: s.lastTs,
|
|
532
|
+
preview: s.preview,
|
|
533
|
+
}));
|
|
534
|
+
return JSON.stringify({
|
|
535
|
+
count: items.length,
|
|
536
|
+
since_hours: sinceHours,
|
|
537
|
+
sessions: items,
|
|
538
|
+
});
|
|
539
|
+
},
|
|
540
|
+
});
|
|
541
|
+
// ---- delegate_to_session ----
|
|
542
|
+
// 向已存在的目标会话派发一次任务,目标会话的 agent 在自己原本的人设/记忆/工具集下完整推理;
|
|
543
|
+
// 与 create_subtask 不同:目标不是新建的"子会话",而是任意已知 sessionId(如群聊、私聊、跨平台)。
|
|
544
|
+
useToolService(ctx).register({
|
|
545
|
+
groups: ['session-delegate'],
|
|
546
|
+
definition: {
|
|
547
|
+
type: 'function',
|
|
548
|
+
function: {
|
|
549
|
+
name: 'delegate_to_session',
|
|
550
|
+
description: [
|
|
551
|
+
'向指定的目标会话(target_session_id)派发一次任务,目标会话的 agent 会在它自己的人设、记忆、工具集、',
|
|
552
|
+
'平台环境下自主完成一次完整推理(可能调用工具、分多段回复等)。',
|
|
553
|
+
'',
|
|
554
|
+
'【典型使用场景】',
|
|
555
|
+
'- 你在私聊里被要求"去 xx 群禁言 yyy":群管理类工具只能在群聊会话内调用,',
|
|
556
|
+
' 此时应 delegate 到该群 sessionId,让群里的 agent 执行 onebot_group_ban。',
|
|
557
|
+
'- 跨平台转告:把消息从 webui 转告到某个 QQ 群。',
|
|
558
|
+
'- 主动联系某位好友 / 在某个群发布公告。',
|
|
559
|
+
'',
|
|
560
|
+
'【与 create_subtask 区别】',
|
|
561
|
+
'- create_subtask:新建一个"子会话"分支,状态独立、有 parent/child 关系,用于把当前任务拆分成并行子任务。',
|
|
562
|
+
'- delegate_to_session:目标是已经存在(或将以平台身份存在)的会话,没有 parent/child 关系,',
|
|
563
|
+
' 对目标会话来说就像收到一条"主动消息"。',
|
|
564
|
+
'',
|
|
565
|
+
'【sessionId 怎么拿】',
|
|
566
|
+
'- OneBot 群/私聊:onebot:<selfId>:group:<群号> 或 onebot:<selfId>:private:<QQ号>,',
|
|
567
|
+
' 也可先调用 onebot_resolve_session_id 转换。',
|
|
568
|
+
'- 其他平台:参考各平台 adapter 的 sessionId 约定。',
|
|
569
|
+
'',
|
|
570
|
+
'【安全限制】',
|
|
571
|
+
'- 防雪崩:被 delegate 进来的会话最多再链一层(A→B 允许,B 在 proactive 链中不能再 delegate)。',
|
|
572
|
+
'- 平台限速:平台 adapter 可声明 checkAndRecordProactiveSend 做主动发送频率限制,超额会被拒绝。',
|
|
573
|
+
'- 自委派被禁止:target_session_id 不能等于当前 sessionId。',
|
|
574
|
+
'',
|
|
575
|
+
'【wait_for_result】',
|
|
576
|
+
'- true(默认):同步等待目标 agent 完成一轮回复,把对方 reply 文本返回给你,最长等 timeout_seconds 秒。',
|
|
577
|
+
'- false:fire-and-forget,立刻返回"已派发",不阻塞当前会话。',
|
|
578
|
+
'',
|
|
579
|
+
'【fire-and-forget 时延 / 重复派发提醒】',
|
|
580
|
+
'- fire-and-forget 模式下,目标会话从被派发到真正对外发送通常需要 5~30 秒(大群历史多、目标 agent 多轮工具迭代会更慢)。',
|
|
581
|
+
'- 用户口头说"没收到"不等于目标真的没发;先用 onebot_get_session_history(或对应平台的 history 工具)',
|
|
582
|
+
' 查目标 sessionId 最近一条 role=assistant 输出,结合该会话所用 persona/output 约定判断是否已发出。',
|
|
583
|
+
'- 系统会在 60 秒内追踪同一 target_session_id 的多次派发,并在派发给目标 agent 的 task 前注入 META 块;',
|
|
584
|
+
' 目标 agent 可识别 META 后选择不重发(输出空回复)。但 META 是"提醒"非硬性拦截:',
|
|
585
|
+
' 调用方仍应避免短时间内对同一目标重复派发同一任务。',
|
|
586
|
+
'',
|
|
587
|
+
'【返回值字段】',
|
|
588
|
+
'- outcome: replied / silent / aborted。silent 表示目标 agent 本轮 reply 为空(可能在执行工具未发文本、',
|
|
589
|
+
' 或被中间件吞掉、或目标策略层主动静默);reply="" 不代表任务一定已完成。',
|
|
590
|
+
'- reply: 目标 agent 真正对外发出的可见文本(可能为空)。',
|
|
591
|
+
'- personaState: 可选字段。若目标会话挂载了 persona 且本轮产出结构化状态,则附带,用于辅助判断;',
|
|
592
|
+
' 不挂载或未产出时不出现,不要假设它一定存在。',
|
|
593
|
+
].join('\n'),
|
|
594
|
+
parameters: {
|
|
595
|
+
type: 'object',
|
|
596
|
+
properties: {
|
|
597
|
+
target_session_id: {
|
|
598
|
+
type: 'string',
|
|
599
|
+
description: '目标会话完整 sessionId(如 "onebot:10000:group:20002")',
|
|
600
|
+
},
|
|
601
|
+
task: {
|
|
602
|
+
type: 'string',
|
|
603
|
+
description: '给目标会话 agent 的任务说明。注意这不是要原样发出的文本,而是"该做什么/该说什么"的指令,' +
|
|
604
|
+
'目标 agent 会按自己的风格、记忆、工具集组织措辞和动作。',
|
|
605
|
+
},
|
|
606
|
+
wait_for_result: {
|
|
607
|
+
type: 'boolean',
|
|
608
|
+
description: '是否同步等待目标 agent 完成本轮回复并把内容返回。默认 true。',
|
|
609
|
+
},
|
|
610
|
+
timeout_seconds: {
|
|
611
|
+
type: 'number',
|
|
612
|
+
description: `wait_for_result=true 时的等待上限,默认 ${cfg.crossSessionDefaultTimeoutSec} 秒,最大 300 秒。`,
|
|
613
|
+
},
|
|
614
|
+
},
|
|
615
|
+
required: ['target_session_id', 'task'],
|
|
616
|
+
additionalProperties: false,
|
|
617
|
+
},
|
|
618
|
+
},
|
|
619
|
+
},
|
|
620
|
+
handler: async (args, callCtx) => {
|
|
621
|
+
const targetSessionId = String(args.target_session_id ?? '').trim();
|
|
622
|
+
const task = String(args.task ?? '');
|
|
623
|
+
const waitForResult = args.wait_for_result === undefined ? true : args.wait_for_result === true;
|
|
624
|
+
const requestedTimeoutSec = Number(args.timeout_seconds);
|
|
625
|
+
const timeoutSec = Number.isFinite(requestedTimeoutSec) && requestedTimeoutSec > 0
|
|
626
|
+
? Math.min(300, requestedTimeoutSec)
|
|
627
|
+
: cfg.crossSessionDefaultTimeoutSec;
|
|
628
|
+
const timeoutMs = Math.max(1000, timeoutSec * 1000);
|
|
629
|
+
if (!targetSessionId)
|
|
630
|
+
return JSON.stringify({ error: 'target_session_id 不能为空' });
|
|
631
|
+
if (!task.trim())
|
|
632
|
+
return JSON.stringify({ error: 'task 不能为空' });
|
|
633
|
+
if (targetSessionId === callCtx.sessionId) {
|
|
634
|
+
return JSON.stringify({ error: 'target_session_id 不能等于当前会话;如需自我追问请直接生成下一轮回复。' });
|
|
635
|
+
}
|
|
636
|
+
// 防雪崩:源 depth + 1 即将传给目标
|
|
637
|
+
const sourceDepth = getProactiveDepth(callCtx.sessionId);
|
|
638
|
+
const targetDepth = sourceDepth + 1;
|
|
639
|
+
if (targetDepth > PROACTIVE_DEPTH_MAX) {
|
|
640
|
+
return JSON.stringify({
|
|
641
|
+
error: `委派链已达最大深度 ${PROACTIVE_DEPTH_MAX}(当前会话本身正以 proactive 链路被驱动,禁止再次 delegate 以防雪崩)`,
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
// 解析目标平台,应用可选限速闸门
|
|
645
|
+
let platformName;
|
|
646
|
+
try {
|
|
647
|
+
const adapter = await resolvePlatformBySession(ctx, targetSessionId);
|
|
648
|
+
if (adapter) {
|
|
649
|
+
platformName = adapter.platform;
|
|
650
|
+
const gate = adapter.checkAndRecordProactiveSend;
|
|
651
|
+
if (typeof gate === 'function') {
|
|
652
|
+
const verdict = gate.call(adapter, targetSessionId);
|
|
653
|
+
if (!verdict.allowed) {
|
|
654
|
+
return JSON.stringify({ error: `委派被平台限速拦截:${verdict.reason ?? '超出限速阈值'}` });
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
catch (err) {
|
|
660
|
+
ctx.logger.warn(`[delegate] 解析目标平台失败 (${targetSessionId}): ${err}`);
|
|
661
|
+
}
|
|
662
|
+
// 标记目标进入 proactive 链路
|
|
663
|
+
setProactiveDepth(targetSessionId, targetDepth);
|
|
664
|
+
// ===== 注入 META 提示(提醒型,不挡派发) =====
|
|
665
|
+
const now = Date.now();
|
|
666
|
+
pruneRecentDelegations(now);
|
|
667
|
+
const taskHash = hashTask(task);
|
|
668
|
+
const dedupKey = recentDelegationKey(targetSessionId, taskHash);
|
|
669
|
+
const recents = findRecentDelegationsForTarget(targetSessionId, now);
|
|
670
|
+
const taskWithMeta = buildDelegationMetaBlock(callCtx.sessionId, targetSessionId, task, recents, now);
|
|
671
|
+
const entry = {
|
|
672
|
+
firedAt: now,
|
|
673
|
+
expiresAt: now + RECENT_DELEGATION_TTL_MS,
|
|
674
|
+
sourceSessionId: callCtx.sessionId,
|
|
675
|
+
taskPreview: task.length > 80 ? `${task.slice(0, 80)}...` : task,
|
|
676
|
+
taskHash,
|
|
677
|
+
status: waitForResult ? 'pending' : 'fired-no-wait',
|
|
678
|
+
};
|
|
679
|
+
recentDelegations.set(dedupKey, entry);
|
|
680
|
+
if (recents.length > 0) {
|
|
681
|
+
ctx.logger.info(`[delegate] META 提醒已注入:${targetSessionId} 在 60s 内已收到 ${recents.length} 次同/近期任务`);
|
|
682
|
+
}
|
|
683
|
+
const incoming = {
|
|
684
|
+
content: taskWithMeta,
|
|
685
|
+
sessionId: targetSessionId,
|
|
686
|
+
platform: platformName ?? callCtx.platform ?? 'internal',
|
|
687
|
+
source: `proactive:from:${callCtx.sessionId}`,
|
|
688
|
+
triggerType: 'proactive',
|
|
689
|
+
};
|
|
690
|
+
const taskPreview = task.length > 80 ? `${task.slice(0, 80)}... (+${task.length - 80}字,全文已完整传递给目标会话)` : task;
|
|
691
|
+
ctx.logger.info(`[delegate] from=${callCtx.sessionId} -> ${targetSessionId} depth=${targetDepth} wait=${waitForResult} task="${taskPreview}"`);
|
|
692
|
+
if (!waitForResult) {
|
|
693
|
+
ctx.emit('inbound:message', incoming).catch(err => {
|
|
694
|
+
ctx.logger.warn(`[delegate] 派发失败 (${targetSessionId}): ${err}`);
|
|
695
|
+
});
|
|
696
|
+
ctx.logger.info(`[delegate] return -> ${callCtx.sessionId} wait=false (fire-and-forget)`);
|
|
697
|
+
return JSON.stringify({
|
|
698
|
+
delegated: true,
|
|
699
|
+
targetSessionId,
|
|
700
|
+
wait: false,
|
|
701
|
+
depth: `${targetDepth}/${PROACTIVE_DEPTH_MAX}`,
|
|
702
|
+
message: '已派发,不等待目标会话结果',
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
// wait_for_result=true:在派发前注册 agent:turn:after 监听,捕获目标 sessionId 的首条 reply
|
|
706
|
+
let captured;
|
|
707
|
+
let resolveWait;
|
|
708
|
+
const waitPromise = new Promise(resolve => {
|
|
709
|
+
resolveWait = resolve;
|
|
710
|
+
});
|
|
711
|
+
const dispose = ctx.middleware('agent:turn:after', async (data, next) => {
|
|
712
|
+
await next();
|
|
713
|
+
if (captured)
|
|
714
|
+
return;
|
|
715
|
+
if (data.sessionId !== targetSessionId)
|
|
716
|
+
return;
|
|
717
|
+
captured = { reply: data.reply ?? '', outcome: data.outcome };
|
|
718
|
+
resolveWait?.();
|
|
719
|
+
});
|
|
720
|
+
const timeoutHandle = setTimeout(() => resolveWait?.(), timeoutMs);
|
|
721
|
+
try {
|
|
722
|
+
await ctx.emit('inbound:message', incoming);
|
|
723
|
+
await waitPromise;
|
|
724
|
+
}
|
|
725
|
+
finally {
|
|
726
|
+
clearTimeout(timeoutHandle);
|
|
727
|
+
dispose();
|
|
728
|
+
}
|
|
729
|
+
if (!captured) {
|
|
730
|
+
ctx.logger.warn(`[delegate] return -> ${callCtx.sessionId} timedOut=true wait=${timeoutSec}s (未捕获 agent:turn:after)`);
|
|
731
|
+
return JSON.stringify({
|
|
732
|
+
delegated: true,
|
|
733
|
+
targetSessionId,
|
|
734
|
+
wait: true,
|
|
735
|
+
timedOut: true,
|
|
736
|
+
depth: `${targetDepth}/${PROACTIVE_DEPTH_MAX}`,
|
|
737
|
+
message: `已派发但在 ${timeoutSec}s 内未捕获 agent:turn:after(目标可能仍在执行或被中间件 swallow)`,
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
// 更新 recentDelegations entry:写入回复结果,供后续重复派发提醒展示
|
|
741
|
+
const entryAfter = recentDelegations.get(dedupKey);
|
|
742
|
+
if (entryAfter) {
|
|
743
|
+
entryAfter.status = 'replied';
|
|
744
|
+
entryAfter.lastOutcome = captured.outcome;
|
|
745
|
+
const r = captured.reply ?? '';
|
|
746
|
+
entryAfter.lastReplyPreview =
|
|
747
|
+
r.length > 60 ? `${r.slice(0, 60).replace(/\n/g, ' ')}...` : r.replace(/\n/g, ' ');
|
|
748
|
+
}
|
|
749
|
+
const replyTruncated = captured.reply.length > 2000
|
|
750
|
+
? `${captured.reply.slice(0, 2000)}\n...[已截断, 原长 ${captured.reply.length} 字]`
|
|
751
|
+
: captured.reply;
|
|
752
|
+
// 可选附加:若目标会话挂载了 persona service 且本轮产出结构化状态,附带返回;
|
|
753
|
+
// 不挂载或未产出时不放该字段,避免上游对「persona 一定存在」做假设。
|
|
754
|
+
let personaState;
|
|
755
|
+
try {
|
|
756
|
+
const personaService = ctx.getService('persona');
|
|
757
|
+
const state = personaService?.getSessionState?.(targetSessionId);
|
|
758
|
+
if (state && Object.keys(state).length > 0) {
|
|
759
|
+
personaState = state;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
catch {
|
|
763
|
+
// service 未启用 / 未提供接口,静默忽略
|
|
764
|
+
}
|
|
765
|
+
const payload = {
|
|
766
|
+
delegated: true,
|
|
767
|
+
targetSessionId,
|
|
768
|
+
wait: true,
|
|
769
|
+
timedOut: false,
|
|
770
|
+
outcome: captured.outcome,
|
|
771
|
+
reply: replyTruncated,
|
|
772
|
+
depth: `${targetDepth}/${PROACTIVE_DEPTH_MAX}`,
|
|
773
|
+
};
|
|
774
|
+
if (personaState)
|
|
775
|
+
payload.personaState = personaState;
|
|
776
|
+
const replyPreview = captured.reply.length === 0
|
|
777
|
+
? '<空>'
|
|
778
|
+
: captured.reply.length > 60
|
|
779
|
+
? `"${captured.reply.slice(0, 60).replace(/\n/g, ' ')}..." (+${captured.reply.length - 60}字)`
|
|
780
|
+
: `"${captured.reply.replace(/\n/g, ' ')}"`;
|
|
781
|
+
ctx.logger.info(`[delegate] return -> ${callCtx.sessionId} outcome=${captured.outcome} reply=${replyPreview}${personaState ? ' personaState=yes' : ''}`);
|
|
782
|
+
return JSON.stringify(payload);
|
|
783
|
+
},
|
|
784
|
+
});
|
|
785
|
+
ctx.logger.info('跨会话协作工具已注册');
|
|
786
|
+
}
|
|
787
|
+
// ===== 插件入口 =====
|
|
788
|
+
export function apply(ctx, config) {
|
|
789
|
+
const cfg = resolveConfig(config);
|
|
790
|
+
if (!cfg.enabled)
|
|
791
|
+
return;
|
|
792
|
+
const historyService = createSessionHistoryService(ctx, cfg);
|
|
793
|
+
ctx.provide('session-history', historyService, { label: '会话历史读取' });
|
|
794
|
+
registerSessionHistoryTools(ctx, historyService, cfg);
|
|
795
|
+
if (cfg.crossSessionEnabled) {
|
|
796
|
+
registerCrossSessionTools(ctx, cfg);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aalis/plugin-tool-session",
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "会话工具:让 AI 读写当前会话状态",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"aalis",
|
|
9
|
+
"aalis-plugin"
|
|
10
|
+
],
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"types": "dist/index.d.ts",
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"dev": "tsc --watch"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@aalis/plugin-agent-api": "workspace:^",
|
|
22
|
+
"@aalis/plugin-platform-api": "workspace:^",
|
|
23
|
+
"@aalis/plugin-tool-session-api": "workspace:^",
|
|
24
|
+
"@aalis/plugin-tools-api": "workspace:^"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@aalis/core": "workspace:*",
|
|
28
|
+
"@aalis/plugin-memory-api": "workspace:*",
|
|
29
|
+
"@aalis/plugin-message-api": "workspace:*",
|
|
30
|
+
"@types/node": "^22.0.0",
|
|
31
|
+
"typescript": "^5.7.0"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@aalis/core": ">=0.2.0 <1.0.0"
|
|
35
|
+
},
|
|
36
|
+
"aalis": {
|
|
37
|
+
"service": {
|
|
38
|
+
"optional": [
|
|
39
|
+
"memory"
|
|
40
|
+
],
|
|
41
|
+
"provides": [
|
|
42
|
+
"session-history"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|