@xcanwin/manyoyo 8.7.1 → 8.7.2

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.
@@ -0,0 +1,82 @@
1
+ 'use strict';
2
+
3
+ // 回顾(隔了很久回来,用一句话说明刚才做到哪)。只对“最后一条消息是已经完成的最终回复”的 AGENT 生成。
4
+
5
+ const RECAP_IDLE_MS = 30 * 60 * 1000;
6
+
7
+ function isFinishedReply(message) {
8
+ return Boolean(message)
9
+ && message.role === 'assistant'
10
+ && message.mode === 'agent'
11
+ && message.pending !== true
12
+ && message.streamTrace !== true
13
+ && message.interrupted !== true
14
+ && typeof message.content === 'string'
15
+ && message.content.trim() !== '';
16
+ }
17
+
18
+ // 返回 { replyId, replyText, promptText, replyAtMs };最后一条不是已完成的最终回复(执行中、被中断、系统命令输出)就是 null
19
+ function findRecapTarget(messages) {
20
+ const list = Array.isArray(messages) ? messages.filter(item => item && item.streamTrace !== true) : [];
21
+ const last = list[list.length - 1];
22
+ if (!isFinishedReply(last)) {
23
+ return null;
24
+ }
25
+ let prompt = null;
26
+ for (let index = list.length - 2; index >= 0; index -= 1) {
27
+ if (list[index].role === 'user' && list[index].mode === 'agent') {
28
+ prompt = list[index];
29
+ break;
30
+ }
31
+ }
32
+ if (!prompt) {
33
+ return null;
34
+ }
35
+ const replyAtMs = Date.parse(last.timestamp);
36
+ return {
37
+ replyId: String(last.id || ''),
38
+ replyText: last.content,
39
+ promptText: typeof prompt.content === 'string' ? prompt.content : '',
40
+ replyAtMs: Number.isFinite(replyAtMs) ? replyAtMs : 0
41
+ };
42
+ }
43
+
44
+ // 是否要生成:没有目标、已经给这条回复生成过(除非 force)、空闲不到 30 分钟(除非 force)都不生成
45
+ function shouldGenerateRecap(agentSession, nowMs, force) {
46
+ const target = findRecapTarget(agentSession && agentSession.messages);
47
+ if (!target || !target.replyId) {
48
+ return null;
49
+ }
50
+ if (!force) {
51
+ if (agentSession.recap && agentSession.recap.forMessageId === target.replyId) {
52
+ return null;
53
+ }
54
+ if (!target.replyAtMs || nowMs - target.replyAtMs < RECAP_IDLE_MS) {
55
+ return null;
56
+ }
57
+ }
58
+ return target;
59
+ }
60
+
61
+ function normalizeStoredRecap(value, normalizeText) {
62
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
63
+ return null;
64
+ }
65
+ const text = normalizeText(value.text);
66
+ const forMessageId = typeof value.forMessageId === 'string' ? value.forMessageId : '';
67
+ if (!text || !forMessageId) {
68
+ return null;
69
+ }
70
+ return {
71
+ forMessageId,
72
+ text,
73
+ createdAt: typeof value.createdAt === 'string' && !Number.isNaN(Date.parse(value.createdAt)) ? value.createdAt : null
74
+ };
75
+ }
76
+
77
+ module.exports = {
78
+ RECAP_IDLE_MS,
79
+ findRecapTarget,
80
+ shouldGenerateRecap,
81
+ normalizeStoredRecap
82
+ };