evolcore 0.0.32 → 0.0.34
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/CHANGELOG.md +61 -0
- package/bin/ec.js +3 -2
- package/bin/install-codex-managed-hooks.mjs +135 -37
- package/dist/agents/baseagent-availability.js +20 -36
- package/dist/agents/claude-runner.js +111 -15
- package/dist/agents/codex/app-server-client.js +3 -0
- package/dist/agents/codex/diagnostics.js +112 -54
- package/dist/agents/codex-runner.js +241 -63
- package/dist/agents/ecagent-runner.js +78 -33
- package/dist/agents/runner-types.js +5 -6
- package/dist/aun/aid/identity.js +1 -1
- package/dist/aun/group/operations.js +0 -1
- package/dist/aun/msg/history.js +1 -0
- package/dist/aun/msg/p2p.js +0 -1
- package/dist/aun/outbox.js +50 -1
- package/dist/channels/aun.js +44 -8
- package/dist/channels/daemon.js +261 -3
- package/dist/cli/agent-command.js +58 -24
- package/dist/cli/agent.js +1 -1
- package/dist/cli/aun-commands.js +368 -31
- package/dist/cli/contact.js +8 -2
- package/dist/cli/ctl-command.js +3 -1
- package/dist/cli/daemon-commands.js +197 -27
- package/dist/cli/debug-mode.js +154 -0
- package/dist/cli/fs-command.js +2 -1
- package/dist/cli/handoff-command.js +3 -0
- package/dist/cli/index.js +98 -67
- package/dist/cli/init.js +2 -2
- package/dist/cli/integrity-command.js +196 -0
- package/dist/cli/managed-command-guard.js +5 -0
- package/dist/cli/memory-command.js +166 -146
- package/dist/cli/queue-command.js +9 -4
- package/dist/cli/session-command.js +194 -0
- package/dist/cli/skill-command.js +78 -2
- package/dist/cli/task-context.js +1 -0
- package/dist/cli/thread-command.js +622 -0
- package/dist/cli/trigger-command.js +10 -3
- package/dist/config/builtin-roles.js +1 -0
- package/dist/config/config-field-policy.js +6 -3
- package/dist/config/config-manager.js +26 -2
- package/dist/config/contact-book-store.js +5 -0
- package/dist/config/resolved-config-op.js +3 -0
- package/dist/config/role-service.js +13 -0
- package/dist/config/runtime-env.js +16 -0
- package/dist/config-store.js +45 -0
- package/dist/core/audit/log-integrity.js +3 -1
- package/dist/core/auth/agent-delegation.js +133 -36
- package/dist/core/auth/debug-context.js +139 -0
- package/dist/core/auth/delegation-diagnostics.js +414 -0
- package/dist/core/auth/operation-authorizer.js +25 -2
- package/dist/core/auth/operation-catalog.js +49 -0
- package/dist/core/background-session/session-cleanup.js +212 -0
- package/dist/core/background-session/types.js +10 -0
- package/dist/core/bootstrap-messages.js +1 -1
- package/dist/core/bootstrap-service.js +6 -3
- package/dist/core/command/agent-control.js +18 -26
- package/dist/core/command/command-handler.js +197 -27
- package/dist/core/command/daemon-diagnostics.js +1 -0
- package/dist/core/command/memory-slash.js +6 -2
- package/dist/core/command/menu-catalog.js +51 -1
- package/dist/core/command/menu-handler.js +114 -23
- package/dist/core/command/menu-protocol.js +25 -1
- package/dist/core/command/skill-slash.js +322 -0
- package/dist/core/command/slash-gate.js +6 -4
- package/dist/core/command/slash-handler.js +195 -13
- package/dist/core/command/topic-slash.js +528 -0
- package/dist/core/daemon-bootstrap.js +4 -7
- package/dist/core/evolagent-registry.js +20 -5
- package/dist/core/file-integrity/read.js +61 -0
- package/dist/core/file-integrity/store.js +262 -0
- package/dist/core/handoff/runtime.js +5 -11
- package/dist/core/handoff/store.js +5 -0
- package/dist/core/ipc-registration.js +175 -3
- package/dist/core/memory/batch-meta.js +132 -0
- package/dist/core/memory/consolidation-context.js +83 -29
- package/dist/core/memory/consolidation-ops-records.js +49 -16
- package/dist/core/memory/consolidation-queue-format.js +21 -0
- package/dist/core/memory/consolidation.js +264 -205
- package/dist/core/memory/index-manager.js +19 -28
- package/dist/core/memory/memory-admin.js +19 -14
- package/dist/core/memory/memory-document.js +53 -9
- package/dist/core/memory/memory-writer.js +30 -15
- package/dist/core/message/aun-ipc-sender.js +161 -6
- package/dist/core/message/im-renderer.js +169 -10
- package/dist/core/message/message-bridge.js +15 -4
- package/dist/core/message/message-log.js +1 -0
- package/dist/core/message/peer-mode.js +6 -1
- package/dist/core/message/response-engine.js +929 -110
- package/dist/core/message/subtask-tool-projection.js +140 -0
- package/dist/core/model/catalog-service.js +17 -12
- package/dist/core/permission/ec-command-parser.js +217 -9
- package/dist/core/permission/protected-paths.js +5 -1
- package/dist/core/permission/readonly-shell-query.js +43 -5
- package/dist/core/permission/session-path-grants.js +334 -0
- package/dist/core/permission/tool-canonical.js +226 -0
- package/dist/core/permission/tool-policy.js +30 -62
- package/dist/core/role/runtime-policy.js +21 -10
- package/dist/core/session/session-fs-store.js +123 -8
- package/dist/core/session/session-idle-monitor.js +249 -22
- package/dist/core/session/session-manager.js +129 -14
- package/dist/core/skill/command-parser.js +13 -0
- package/dist/core/skill/index-generator.js +21 -4
- package/dist/core/skill/startup.js +41 -0
- package/dist/core/skill/switch-resolver.js +55 -29
- package/dist/core/system-session/grants.js +40 -0
- package/dist/core/system-session/memory.js +222 -0
- package/dist/core/system-session/registry.js +74 -0
- package/dist/core/system-session/types.js +14 -0
- package/dist/core/thread/command-parser.js +125 -0
- package/dist/core/thread/index.js +1 -0
- package/dist/core/thread/ipc-operation.js +95 -0
- package/dist/core/thread/thread-context-storage.js +131 -0
- package/dist/core/thread/thread-operation.js +258 -0
- package/dist/core/thread/thread-route.js +33 -0
- package/dist/core/thread/thread-service.js +770 -0
- package/dist/core/thread/types.js +1 -0
- package/dist/eck/kit-renderer.js +7 -2
- package/dist/eck/manifest-engine.js +24 -4
- package/dist/eck/message-renderer.js +35 -0
- package/dist/index.js +19 -7
- package/dist/ipc.js +140 -50
- package/dist/paths.js +93 -0
- package/dist/response-system/engines/v1/proactive-flow.js +169 -80
- package/dist/stats/billing.js +20 -8
- package/dist/trigger/authorization.js +57 -28
- package/dist/trigger/feedback.js +13 -2
- package/dist/trigger/parser.js +70 -1
- package/dist/trigger/system-definitions.js +3 -3
- package/dist/trigger/validation.js +14 -0
- package/dist/utils/cross-platform.js +11 -2
- package/dist/utils/error-dict.json +18 -4
- package/dist/utils/error-utils.js +143 -1
- package/dist/utils/instance-registry.js +13 -8
- package/dist/utils/log-writer.js +12 -0
- package/dist/utils/process-introspect.js +11 -0
- package/kits/docs/context-assembly.md +1 -1
- package/kits/docs/evolcore/INDEX.md +1 -0
- package/kits/docs/evolcore/agent-create.md +40 -28
- package/kits/docs/evolcore/agent.md +21 -6
- package/kits/docs/evolcore/config.md +2 -2
- package/kits/docs/evolcore/ctl.md +2 -2
- package/kits/docs/evolcore/ec-capabilities.md +5 -1
- package/kits/docs/evolcore/fs-architecture.md +4 -5
- package/kits/docs/evolcore/fs.md +1 -1
- package/kits/docs/evolcore/group-collaboration.md +4 -6
- package/kits/docs/evolcore/group.md +11 -12
- package/kits/docs/evolcore/memory-architecture.md +4 -5
- package/kits/docs/evolcore/memory-consolidation.md +19 -15
- package/kits/docs/evolcore/memory-tags.md +3 -1
- package/kits/docs/evolcore/memory.md +24 -12
- package/kits/docs/evolcore/menu-exec-schema-commands.md +2 -2
- package/kits/docs/evolcore/menu-protocol.md +7 -0
- package/kits/docs/evolcore/model.md +16 -0
- package/kits/docs/evolcore/msg.md +8 -11
- package/kits/docs/evolcore/thread-chain.md +267 -0
- package/kits/docs/prompt-loading-architecture.md +1 -1
- package/kits/eck_manifest.json +55 -40
- package/kits/eck_manifest.memory.json +0 -12
- package/kits/eck_message_manifest.json +169 -10
- package/kits/rules/01-overview.md +11 -0
- package/kits/rules/03-identity.md +6 -3
- package/kits/rules/05-venue.md +1 -1
- package/kits/rules/06-channel.md +1 -1
- package/kits/rules/07-memory-and-thread.md +199 -0
- package/kits/schemas/_meta.json +7 -1
- package/kits/schemas/agent-config.schema.13.json +1 -1
- package/kits/schemas/daemon.schema.7.json +140 -0
- package/kits/schemas/relation-config.schema.9.json +18 -3
- package/kits/schemas/role-config.schema.1.json +6 -6
- package/kits/schemas/single-session.schema.1.json +6 -6
- package/kits/schemas/single-session.schema.2.json +6 -6
- package/kits/schemas/single-session.schema.3.json +6 -6
- package/kits/skills/.switches.json +12 -1
- package/kits/skills/ec-group/SKILL.md +234 -0
- package/kits/skills/ec-skill/SKILL.md +10 -1
- package/kits/skills/ec-skill/scripts/cli.mjs +16 -2
- package/kits/skills/ec-skill/scripts/skill.mjs +1 -1
- package/kits/skills/scrapling-article-fetch/SKILL.md +128 -0
- package/kits/skills/scrapling-article-fetch/scripts/check_python_env.py +54 -0
- package/kits/skills/scrapling-article-fetch/scripts/render_markdown_reply.py +35 -0
- package/kits/skills/scrapling-article-fetch/scripts/run_pipeline.sh +16 -0
- package/kits/skills/scrapling-article-fetch/scripts/scrapling_fetch.py +344 -0
- package/kits/skills/thread-ops/SKILL.md +492 -0
- package/kits/skills/wechat-article-media-download/SKILL.md +65 -0
- package/kits/skills/wechat-article-media-download/scripts/download.py +163 -0
- package/kits/skills/wechat-article-reader/SKILL.md +97 -0
- package/kits/skills/wechat-article-reader/scripts/fetch.mjs +256 -0
- package/kits/templates/bootstrap-welcome.md +7 -7
- package/kits/templates/memory-consolidation/forget.md +7 -2
- package/kits/templates/memory-consolidation/generalize.md +9 -4
- package/kits/templates/memory-consolidation/notes.md +11 -11
- package/kits/templates/memory-consolidation/profile.md +8 -3
- package/kits/templates/memory-consolidation/promote.md +8 -3
- package/kits/templates/memory-consolidation/workflow.md +6 -6
- package/kits/templates/message-fragments/handoff-request-to-target.md +1 -1
- package/kits/templates/message-fragments/item.md +2 -1
- package/kits/templates/message-fragments/thread-context.md +6 -0
- package/kits/templates/message-fragments/trigger-session.md +2 -0
- package/kits/templates/message-fragments/trigger-thread-check.md +2 -0
- package/kits/templates/roles/member.json +2 -0
- package/kits/templates/roles/visitor.json +2 -0
- package/kits/templates/system-fragments/bootstrap.md +67 -72
- package/kits/templates/system-fragments/channel.md +3 -6
- package/kits/templates/system-fragments/commands.md +1 -0
- package/kits/templates/system-fragments/managed-runtime.md +15 -0
- package/kits/templates/system-fragments/memory.md +16 -9
- package/kits/templates/system-fragments/reply.md +7 -6
- package/kits/templates/system-fragments/session.md +5 -14
- package/package.json +6 -3
- package/dist/core/memory/memory-session-policy.js +0 -41
- package/dist/core/memory/memory-signature.js +0 -257
- package/kits/docs/evolcore/group-fs.md +0 -17
- package/kits/docs/venues/aun-group.md +0 -45
- package/kits/docs/venues/group.md +0 -43
|
@@ -12,37 +12,35 @@ import fs from 'fs';
|
|
|
12
12
|
import path from 'path';
|
|
13
13
|
import { agentDir, resolveRoot } from '../../paths.js';
|
|
14
14
|
import { serializeConsolidationContext } from './consolidation-context.js';
|
|
15
|
-
import {
|
|
15
|
+
import { assertSystemSessionLaunchable } from '../system-session/registry.js';
|
|
16
|
+
import { ensureSessionRuntimeDir } from '../../cli/task-context.js';
|
|
16
17
|
import { formatChannelKey } from '../channel-loader.js';
|
|
17
|
-
import { formatPeerKey } from '../relation/peer-identity.js';
|
|
18
18
|
import { logger } from '../../utils/logger.js';
|
|
19
|
-
import { appendOpsRecord } from './consolidation-ops-records.js';
|
|
19
|
+
import { appendOpsRecord, feedbackFilePath, readFeedbackText } from './consolidation-ops-records.js';
|
|
20
|
+
import { updateBatchMeta } from './batch-meta.js';
|
|
20
21
|
import { checkConsolidationCandidates, shouldUseMetaIndex } from './consolidation-trigger.js';
|
|
21
22
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
23
|
+
* 清理旧整理批次,全局保留最新的 10 个(不区分 aid 或 mode)。
|
|
24
|
+
* 启动新整理时调用;selfAid 参数保留供日志上下文用,不参与过滤。
|
|
24
25
|
*/
|
|
25
|
-
function cleanupPreviousConsolidationBatches(
|
|
26
|
+
function cleanupPreviousConsolidationBatches(_selfAid) {
|
|
26
27
|
try {
|
|
27
28
|
const batchRoot = path.join(resolveRoot(), 'memory', 'consolidation-batches');
|
|
28
29
|
if (!fs.existsSync(batchRoot))
|
|
29
30
|
return;
|
|
30
|
-
// 匹配格式:YYYYMMDDTHHMMSS-<selfAid>-*
|
|
31
|
-
const escapedAid = selfAid.replace(/\./g, '\\.');
|
|
32
|
-
const pattern = new RegExp(`^\\d{8}T\\d{6}-${escapedAid}-`);
|
|
33
31
|
const entries = fs.readdirSync(batchRoot, { withFileTypes: true })
|
|
34
|
-
.filter(e => e.isDirectory()
|
|
32
|
+
.filter(e => e.isDirectory())
|
|
35
33
|
.map(e => ({ name: e.name, path: path.join(batchRoot, e.name) }))
|
|
36
|
-
.sort((a, b) => b.name.localeCompare(a.name)); //
|
|
37
|
-
|
|
38
|
-
for (let i =
|
|
34
|
+
.sort((a, b) => b.name.localeCompare(a.name)); // 时间戳前缀,字典序即时间序,最新的在前
|
|
35
|
+
const KEEP = 10;
|
|
36
|
+
for (let i = KEEP; i < entries.length; i++) {
|
|
39
37
|
const dir = entries[i];
|
|
40
38
|
try {
|
|
41
39
|
fs.rmSync(dir.path, { recursive: true, force: true });
|
|
42
|
-
logger.debug(`[Memory]
|
|
40
|
+
logger.debug(`[Memory] 清理旧整理批次: ${dir.name}`);
|
|
43
41
|
}
|
|
44
42
|
catch (e) {
|
|
45
|
-
logger.warn(`[Memory]
|
|
43
|
+
logger.warn(`[Memory] 清理旧整理批次失败 ${dir.name}: ${e?.message}`);
|
|
46
44
|
}
|
|
47
45
|
}
|
|
48
46
|
}
|
|
@@ -50,47 +48,6 @@ function cleanupPreviousConsolidationBatches(selfAid) {
|
|
|
50
48
|
logger.warn(`[Memory] 清理整理批次时出错: ${e?.message}`);
|
|
51
49
|
}
|
|
52
50
|
}
|
|
53
|
-
export function buildDebugTaskContext(input) {
|
|
54
|
-
const { session } = input;
|
|
55
|
-
const meta = (session.metadata ?? {});
|
|
56
|
-
const sessionType = session.sessionType ?? meta.sessionType ?? 'main';
|
|
57
|
-
let channel = session.channelType || session.channel;
|
|
58
|
-
let chatType = session.chatType || 'private';
|
|
59
|
-
let peerId = meta.peerId;
|
|
60
|
-
let peerKeyId = chatType === 'group'
|
|
61
|
-
? (meta.groupId || session.channelId)
|
|
62
|
-
: (meta.peerId || session.channelId);
|
|
63
|
-
let threadId = session.threadId || undefined;
|
|
64
|
-
if (session.channelId?.startsWith('trigger:') && session.selfAID && input.getTrigger) {
|
|
65
|
-
const triggerId = session.channelId.slice('trigger:'.length);
|
|
66
|
-
const origin = input.getTrigger(session.selfAID, triggerId)?.origin;
|
|
67
|
-
if (origin?.channelType) {
|
|
68
|
-
channel = origin.channelType;
|
|
69
|
-
chatType = origin.delivery?.chatType ?? 'private';
|
|
70
|
-
peerId = origin.peerId;
|
|
71
|
-
peerKeyId = chatType === 'group' ? origin.channelId : (origin.peerId ?? origin.channelId);
|
|
72
|
-
threadId = origin.threadId;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
sessionId: session.id,
|
|
77
|
-
baseagent: session.baseagent,
|
|
78
|
-
channel,
|
|
79
|
-
channelId: session.channelId,
|
|
80
|
-
chatType,
|
|
81
|
-
selfAid: session.selfAID,
|
|
82
|
-
peerId,
|
|
83
|
-
peerKey: channel && peerKeyId ? formatPeerKey(channel, peerKeyId) : undefined,
|
|
84
|
-
peerName: meta.peerName,
|
|
85
|
-
peerType: meta.peerType,
|
|
86
|
-
threadId,
|
|
87
|
-
sessionType,
|
|
88
|
-
memoryMode: meta.memoryMode,
|
|
89
|
-
memoryScope: meta.memoryScope,
|
|
90
|
-
consolidationBatchDir: meta.consolidationBatchDir ?? meta.consolidationLogBase,
|
|
91
|
-
sessionRuntimeDir: input.sessionRuntimeDir,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
51
|
/**
|
|
95
52
|
* 序列化上下文并直接创建整理会话。
|
|
96
53
|
* 失败抛错,调用方负责决定是否记录诊断或回传错误。
|
|
@@ -103,10 +60,15 @@ export async function launchConsolidation(channel, params) {
|
|
|
103
60
|
const selfAid = effectiveCtx.selfAid;
|
|
104
61
|
if (!selfAid)
|
|
105
62
|
throw new Error('无法确定当前 agent AID(selfAid 为空)');
|
|
63
|
+
// 系统会话标记:类型 / subtype 必须已注册,runner 必须受支持(Gemini 拒绝)。
|
|
64
|
+
// 放在认领 processing 之前,拒绝时不留副作用。
|
|
65
|
+
const systemSession = { type: 'memory', subtype: mode };
|
|
66
|
+
assertSystemSessionLaunchable(systemSession, effectiveCtx.baseagent ?? 'claude');
|
|
106
67
|
// 清理旧的整理批次(保留最新的一个历史)
|
|
107
68
|
cleanupPreviousConsolidationBatches(selfAid);
|
|
108
69
|
// notes 模式:pending/ → processing/ 快照迁移(在序列化上下文之前执行,声明认领)
|
|
109
70
|
let memoryDir;
|
|
71
|
+
let claimedProcessing = false;
|
|
110
72
|
if (mode === 'notes') {
|
|
111
73
|
memoryDir = effectiveCtx.peerKey
|
|
112
74
|
? path.join(resolveRoot(), 'agents', selfAid, 'relations', effectiveCtx.peerKey, 'memory')
|
|
@@ -114,13 +76,13 @@ export async function launchConsolidation(channel, params) {
|
|
|
114
76
|
const pendingDir = path.join(memoryDir, 'pending');
|
|
115
77
|
const processingDir = path.join(memoryDir, 'processing');
|
|
116
78
|
if (fs.existsSync(processingDir)) {
|
|
117
|
-
|
|
118
|
-
logger.warn(`[Memory] processing/ 已存在,跳过本次迁移(上一批未收尾): ${processingDir}`);
|
|
79
|
+
throw new Error(`上一批整理尚未收尾,不能重新认领 processing: ${processingDir}`);
|
|
119
80
|
}
|
|
120
81
|
else if (fs.existsSync(pendingDir)) {
|
|
121
82
|
try {
|
|
122
83
|
const count = fs.readdirSync(pendingDir).filter(f => f.endsWith('.md')).length;
|
|
123
84
|
fs.renameSync(pendingDir, processingDir);
|
|
85
|
+
claimedProcessing = true;
|
|
124
86
|
// 立即重建空 pending 目录,供主会话后续写 note
|
|
125
87
|
fs.mkdirSync(pendingDir, { recursive: true });
|
|
126
88
|
logger.info(`[Memory] pending → processing 快照完成(${count} 条 note): ${processingDir}`);
|
|
@@ -131,20 +93,28 @@ export async function launchConsolidation(channel, params) {
|
|
|
131
93
|
}
|
|
132
94
|
}
|
|
133
95
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
96
|
+
let ctxFile;
|
|
97
|
+
try {
|
|
98
|
+
ctxFile = serializeConsolidationContext({
|
|
99
|
+
mode,
|
|
100
|
+
triggeredBy,
|
|
101
|
+
taskCtx: effectiveCtx,
|
|
102
|
+
ownerAid,
|
|
103
|
+
ownerInvolved: params.ownerInvolved,
|
|
104
|
+
forgetAfterDays: params.forgetAfterDays,
|
|
105
|
+
scopeOverride: params.scopeOverride,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
if (claimedProcessing && memoryDir)
|
|
110
|
+
restorePendingNotes(memoryDir);
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
144
113
|
const baseagent = effectiveCtx.baseagent ?? 'claude';
|
|
145
114
|
const now = Date.now();
|
|
146
115
|
const scopeTag = params.scopeOverride ? `-${params.scopeOverride}` : '';
|
|
147
|
-
const
|
|
116
|
+
const kind = `memory-consolidate-${mode}${scopeTag}`;
|
|
117
|
+
const triggerId = `${kind}-${now.toString(36)}`;
|
|
148
118
|
// 整理会话的渠道信息(origin):发起时抓取,供反馈时直接投递到原会话渠道。
|
|
149
119
|
// 用 channelId/peerId/threadId 三要素——不依赖 evolcore sessionId,renew/`/new` 换会话也不影响送达。
|
|
150
120
|
const feedbackOrigin = effectiveCtx.channel && effectiveCtx.peerId ? {
|
|
@@ -156,109 +126,76 @@ export async function launchConsolidation(channel, params) {
|
|
|
156
126
|
...(effectiveCtx.threadId ? { threadId: effectiveCtx.threadId } : {}),
|
|
157
127
|
delivery: { chatType: effectiveCtx.chatType ?? 'private' },
|
|
158
128
|
} : undefined;
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
'',
|
|
179
|
-
'请先读取上述上下文文件,再按照注入的整理规范完成本次整理。',
|
|
180
|
-
].join('\n'),
|
|
129
|
+
const projectPath = params.projectPath ?? path.join(resolveRoot(), 'agents', selfAid);
|
|
130
|
+
const prompt = [
|
|
131
|
+
'你正在执行记忆整理任务。',
|
|
132
|
+
`本次整理模式:${mode}`,
|
|
133
|
+
`整理上下文文件路径:${ctxFile.filePath}`,
|
|
134
|
+
'',
|
|
135
|
+
'请先读取上述上下文文件,再按照注入的整理规范完成本次整理。',
|
|
136
|
+
].join('\n');
|
|
137
|
+
// 通过 BackgroundSessionLauncher 拉起独立会话。
|
|
138
|
+
// 不再构造 TriggerDefinition——与 trigger 调度系统完全解耦。
|
|
139
|
+
// on_next_launch 默认策略由 launchBackgroundSession() 负责清理 evolcore session chat 目录;
|
|
140
|
+
// cleanupPreviousConsolidationLogs()(上方已调用)负责清理 memory/consolidation-logs/ 日志目录。
|
|
141
|
+
// 两者清理的是不同的数据,互不重复。
|
|
142
|
+
// 详见 docs/background-session/background-session-launcher.md
|
|
143
|
+
let handle;
|
|
144
|
+
try {
|
|
145
|
+
handle = await channel.launch({
|
|
146
|
+
kind,
|
|
147
|
+
instanceId: now.toString(36),
|
|
181
148
|
baseagent,
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
triggerDef.execution.feedbackOrigin = feedbackOrigin;
|
|
149
|
+
agentAid: selfAid,
|
|
150
|
+
projectPath,
|
|
151
|
+
prompt,
|
|
152
|
+
metadata: {
|
|
153
|
+
// 系统会话的唯一判据:路径 / 工具 / ec 命令由 system-session/memory.ts 决定,与角色无关
|
|
154
|
+
systemSession,
|
|
155
|
+
sessionType: 'memory',
|
|
156
|
+
memoryMode: mode,
|
|
157
|
+
...(params.scopeOverride ? { memoryScope: params.scopeOverride } : {}),
|
|
158
|
+
// 透传到 session.metadata,供 ipc.ts 写 ops 流水、收尾流程读取
|
|
159
|
+
consolidationBatchDir: ctxFile.batchDir,
|
|
160
|
+
...(ctxFile.chatDir ? { consolidationChatDir: ctxFile.chatDir } : {}),
|
|
161
|
+
...(claimedProcessing && memoryDir ? { consolidationMemoryDir: memoryDir } : {}),
|
|
162
|
+
...(ownerAid ? { consolidationOwnerAid: ownerAid } : {}),
|
|
163
|
+
consolidationUsedThreadSnapshots: !!ctxFile.threadFiles?.length,
|
|
164
|
+
...(ctxFile.snapshotThroughTs ? { consolidationSnapshotThroughTs: ctxFile.snapshotThroughTs } : {}),
|
|
165
|
+
...(effectiveCtx.peerKey ? { peerKey: effectiveCtx.peerKey } : {}),
|
|
166
|
+
...(feedbackOrigin ? { feedbackOrigin } : {}),
|
|
167
|
+
consolidationTriggeredBy: triggeredBy,
|
|
168
|
+
},
|
|
169
|
+
// cleanupPolicy 用默认 on_next_launch:清 evolcore session 记录;日志目录由 cleanupPreviousConsolidationLogs() 负责
|
|
170
|
+
});
|
|
205
171
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
//
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
baseagent,
|
|
220
|
-
session,
|
|
221
|
-
causation: undefined,
|
|
222
|
-
}).catch((e) => {
|
|
223
|
-
logger.warn(`[Memory] 整理会话执行失败(mode=${mode},session=${session.id}): ${e?.message}`);
|
|
172
|
+
catch (error) {
|
|
173
|
+
if (claimedProcessing && memoryDir)
|
|
174
|
+
restorePendingNotes(memoryDir);
|
|
175
|
+
recordConsolidationOutcome(ctxFile.contextFilePath, `启动失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
// launch() 在会话创建后即返回,sessionId 立即可用;不等会话结束。
|
|
179
|
+
// 收尾由 bg-session:completed/error/interrupted 事件驱动,这里只记录异常结局。
|
|
180
|
+
const executionSessionId = handle.sessionId;
|
|
181
|
+
void handle.result.then(r => {
|
|
182
|
+
if (r.outcome !== 'completed') {
|
|
183
|
+
logger.warn(`[Memory] 整理会话未正常结束(mode=${mode},outcome=${r.outcome}): ${r.error ?? ''}`);
|
|
184
|
+
}
|
|
224
185
|
});
|
|
225
186
|
logger.info(`[Memory] 已拉起整理会话(mode=${mode},triggeredBy=${triggeredBy},` +
|
|
226
|
-
`selfAid=${selfAid}${effectiveCtx.peerKey ? `,peerKey=${effectiveCtx.peerKey}` : ''}
|
|
227
|
-
|
|
187
|
+
`selfAid=${selfAid}${effectiveCtx.peerKey ? `,peerKey=${effectiveCtx.peerKey}` : ''}` +
|
|
188
|
+
`${executionSessionId ? `,session=${executionSessionId}` : ''})`);
|
|
228
189
|
return {
|
|
229
190
|
triggerId,
|
|
230
191
|
contextFile: ctxFile.filePath,
|
|
231
192
|
contextFilePath: ctxFile.contextFilePath,
|
|
232
193
|
logFile: ctxFile.contextFilePath,
|
|
233
194
|
batchDir: ctxFile.batchDir,
|
|
234
|
-
executionSessionId
|
|
195
|
+
executionSessionId,
|
|
196
|
+
waitForAgentSessionId: handle.waitForAgentSessionId,
|
|
235
197
|
};
|
|
236
198
|
}
|
|
237
|
-
/**
|
|
238
|
-
* 手动 consolidate 用:在超时内轮询等 runner 分配 agentSessionId。
|
|
239
|
-
* 拿到立即返回;超时返回已拿到的部分,不抛错。
|
|
240
|
-
*
|
|
241
|
-
* 会话创建后 executionSessionId 立刻可用,但 agentSessionId 要等 runner 初始化
|
|
242
|
-
* 并开始第一轮才写入 session 记录,所以这里必须轮询等待。
|
|
243
|
-
*/
|
|
244
|
-
export async function waitForConsolidationSession(opts) {
|
|
245
|
-
const executionSessionId = opts.executionSessionId;
|
|
246
|
-
if (!executionSessionId)
|
|
247
|
-
return {};
|
|
248
|
-
const deadline = Date.now() + (opts.timeoutMs ?? 10_000);
|
|
249
|
-
const interval = opts.intervalMs ?? 250;
|
|
250
|
-
while (true) {
|
|
251
|
-
try {
|
|
252
|
-
const agentSessionId = await opts.readAgentSessionId(executionSessionId);
|
|
253
|
-
if (agentSessionId)
|
|
254
|
-
return { executionSessionId, agentSessionId };
|
|
255
|
-
}
|
|
256
|
-
catch { /* 会话记录写到一半,下一轮再读 */ }
|
|
257
|
-
if (Date.now() >= deadline)
|
|
258
|
-
return { executionSessionId };
|
|
259
|
-
await new Promise(r => setTimeout(r, interval));
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
199
|
/** 把 entry 移进 destDir;重名时加时间戳后缀,不覆盖已有文件。 */
|
|
263
200
|
function moveIntoDir(srcPath, destDir, stamp) {
|
|
264
201
|
const name = path.basename(srcPath);
|
|
@@ -276,6 +213,17 @@ function moveIntoDir(srcPath, destDir, stamp) {
|
|
|
276
213
|
}
|
|
277
214
|
fs.renameSync(srcPath, dest);
|
|
278
215
|
}
|
|
216
|
+
function restorePendingNotes(memoryDir) {
|
|
217
|
+
const processingDir = path.join(memoryDir, 'processing');
|
|
218
|
+
if (!fs.existsSync(processingDir))
|
|
219
|
+
return;
|
|
220
|
+
const pendingDir = path.join(memoryDir, 'pending');
|
|
221
|
+
fs.mkdirSync(pendingDir, { recursive: true });
|
|
222
|
+
const stamp = Date.now().toString(36);
|
|
223
|
+
for (const entry of fs.readdirSync(processingDir))
|
|
224
|
+
moveIntoDir(path.join(processingDir, entry), pendingDir, stamp);
|
|
225
|
+
fs.rmdirSync(processingDir);
|
|
226
|
+
}
|
|
279
227
|
/**
|
|
280
228
|
* 整理会话结束后的收尾,task:completed / task:error / task:interrupted 都走这里。
|
|
281
229
|
* - processing/ 里的 note:成功 → archive/notes/,失败 → 归还 pending/(下次重试)
|
|
@@ -306,9 +254,10 @@ export async function onConsolidationComplete(params) {
|
|
|
306
254
|
result.movedTo = noteDest;
|
|
307
255
|
}
|
|
308
256
|
}
|
|
309
|
-
|
|
257
|
+
// C3: update mode-specific checkpoint only when thread snapshots were used
|
|
258
|
+
if (params.success && params.chatDir && params.mode && params.usedThreadSnapshots) {
|
|
310
259
|
const { writeCheckpoint } = await import('./consolidation-context.js');
|
|
311
|
-
writeCheckpoint(params.chatDir, now);
|
|
260
|
+
writeCheckpoint(params.chatDir, params.snapshotThroughTs ?? now, params.mode, params.scopeOverride);
|
|
312
261
|
result.checkpointWritten = true;
|
|
313
262
|
}
|
|
314
263
|
const { summarizeOpsRecords, appendOpsRecord } = await import('./consolidation-ops-records.js');
|
|
@@ -396,6 +345,7 @@ export async function rollbackConsolidation(batchDir, selfAid) {
|
|
|
396
345
|
}
|
|
397
346
|
const MAX_CONCURRENT_CONSOLIDATION = 5;
|
|
398
347
|
export function createConsolidationSessionFinalizer({ sessionManager, getAgent, agentMap, releaseSlot, enqueueConsolidation, sendFeedback, }) {
|
|
348
|
+
const finalizedSessions = new Set();
|
|
399
349
|
return async (sessionId, success) => {
|
|
400
350
|
let releaseAid;
|
|
401
351
|
try {
|
|
@@ -408,6 +358,9 @@ export function createConsolidationSessionFinalizer({ sessionManager, getAgent,
|
|
|
408
358
|
const batchDir = (meta.consolidationBatchDir ?? meta.consolidationLogBase);
|
|
409
359
|
if (!batchDir)
|
|
410
360
|
return;
|
|
361
|
+
if (finalizedSessions.has(sessionId))
|
|
362
|
+
return;
|
|
363
|
+
finalizedSessions.add(sessionId);
|
|
411
364
|
releaseAid = session.selfAID;
|
|
412
365
|
const { summarizeOpsRecords, collectAffectedScopes } = await import('./consolidation-ops-records.js');
|
|
413
366
|
if (!success) {
|
|
@@ -418,6 +371,10 @@ export function createConsolidationSessionFinalizer({ sessionManager, getAgent,
|
|
|
418
371
|
batchDir,
|
|
419
372
|
chatDir: meta.consolidationChatDir,
|
|
420
373
|
memoryDir: meta.consolidationMemoryDir,
|
|
374
|
+
mode: meta.memoryMode,
|
|
375
|
+
scopeOverride: meta.memoryScope,
|
|
376
|
+
usedThreadSnapshots: meta.consolidationUsedThreadSnapshots === true,
|
|
377
|
+
snapshotThroughTs: meta.consolidationSnapshotThroughTs,
|
|
421
378
|
});
|
|
422
379
|
try {
|
|
423
380
|
const affectedScopes = collectAffectedScopes(batchDir);
|
|
@@ -429,9 +386,8 @@ export function createConsolidationSessionFinalizer({ sessionManager, getAgent,
|
|
|
429
386
|
for (const [scope, memoryDir] of affectedScopes) {
|
|
430
387
|
const consolidatedDir = path.join(memoryDir, 'consolidated');
|
|
431
388
|
const indexPath = path.join(memoryDir, 'MEMORY.md');
|
|
432
|
-
const invalidDir = path.join(memoryDir, 'archive', 'invalid');
|
|
433
389
|
try {
|
|
434
|
-
await rebuildIndex(consolidatedDir, indexPath, scope,
|
|
390
|
+
await rebuildIndex(consolidatedDir, indexPath, scope, maxBytes);
|
|
435
391
|
}
|
|
436
392
|
catch { }
|
|
437
393
|
}
|
|
@@ -513,12 +469,28 @@ export function createConsolidationSessionFinalizer({ sessionManager, getAgent,
|
|
|
513
469
|
fs.writeFileSync(historyPath, JSON.stringify({ note: `runner ${baseagent} does not support getSessionMessages` }) + '\n', 'utf-8');
|
|
514
470
|
}
|
|
515
471
|
}
|
|
472
|
+
// feedback 只读一次:先落 batch.md,再清 scratch/,投递复用同一份文本
|
|
473
|
+
const customText = readFeedbackText(batchDir);
|
|
474
|
+
// batch.md 收尾更新:写入最终状态和 feedback 正文
|
|
475
|
+
try {
|
|
476
|
+
updateBatchMeta(batchDir, {
|
|
477
|
+
status: success ? 'completed' : 'failed',
|
|
478
|
+
finishedAt: new Date().toISOString(),
|
|
479
|
+
success,
|
|
480
|
+
...(session.agentSessionId ? { agentSessionId: session.agentSessionId } : {}),
|
|
481
|
+
feedbackText: customText,
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
catch { /* 失败静默 */ }
|
|
485
|
+
// scratch/ 是会话期临时工作区,feedback 已落 batch.md,不分成败与触发方式一律清掉
|
|
486
|
+
try {
|
|
487
|
+
fs.rmSync(path.dirname(feedbackFilePath(batchDir)), { recursive: true, force: true });
|
|
488
|
+
}
|
|
489
|
+
catch { /* 静默,不影响投递 */ }
|
|
516
490
|
const feedbackOrigin = meta.feedbackOrigin;
|
|
517
491
|
const triggeredBy = meta.consolidationTriggeredBy;
|
|
518
492
|
if (feedbackOrigin && triggeredBy && triggeredBy !== 'periodic-trigger' && session.selfAID) {
|
|
519
493
|
try {
|
|
520
|
-
const { readFeedbackText } = await import('./consolidation-ops-records.js');
|
|
521
|
-
const customText = readFeedbackText(batchDir);
|
|
522
494
|
const text = customText ?? renderDefaultConsolidationFeedback({
|
|
523
495
|
mode: meta.memoryMode,
|
|
524
496
|
triggeredBy,
|
|
@@ -537,8 +509,23 @@ export function createConsolidationSessionFinalizer({ sessionManager, getAgent,
|
|
|
537
509
|
logger.warn(`[Memory] 整理收尾失败(session=${sessionId}): ${error?.message}`);
|
|
538
510
|
}
|
|
539
511
|
finally {
|
|
540
|
-
if (releaseAid)
|
|
541
|
-
releaseSlot(releaseAid);
|
|
512
|
+
if (releaseAid && sessionId)
|
|
513
|
+
releaseSlot(releaseAid, sessionId);
|
|
514
|
+
// runtime 目录清理:immediate 策略下,finalizer 是最后一个要读它的消费者。
|
|
515
|
+
// 用 sessionId 无状态重算路径,不依赖 spec 传递——保证即使 spec 不传 runtimeDir
|
|
516
|
+
// 字段,目录也能在会话结束后被清掉。
|
|
517
|
+
if (sessionId) {
|
|
518
|
+
const runtimeDir = ensureSessionRuntimeDir(sessionId);
|
|
519
|
+
if (runtimeDir) {
|
|
520
|
+
try {
|
|
521
|
+
fs.rmSync(runtimeDir, { recursive: true, force: true });
|
|
522
|
+
logger.debug(`[Memory] 清理 runtime 目录: ${runtimeDir}`);
|
|
523
|
+
}
|
|
524
|
+
catch (cleanupError) {
|
|
525
|
+
logger.warn(`[Memory] runtime 目录清理失败(session=${sessionId}): ${cleanupError?.message}`);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
542
529
|
}
|
|
543
530
|
};
|
|
544
531
|
}
|
|
@@ -563,19 +550,48 @@ export function createConsolidationFeedbackSender(getChannel) {
|
|
|
563
550
|
replyContext.threadId = threadId;
|
|
564
551
|
if (chatType)
|
|
565
552
|
replyContext.delivery = { chatType };
|
|
566
|
-
|
|
567
|
-
|
|
553
|
+
// 对比期:同一份反馈 notice、text 各发一条,观察两种模式在对端的差异,
|
|
554
|
+
// 跑通后删掉 text 那条。两条 taskId 后缀不同,避免共用 operationId 被出站去重吞掉一条;
|
|
555
|
+
// 各自 try,一条失败不连累另一条。
|
|
556
|
+
const stamp = Date.now();
|
|
557
|
+
const envelopeFor = (suffix) => buildEnvelope({
|
|
558
|
+
taskId: `memory-feedback-${stamp}-${suffix}`,
|
|
568
559
|
channel: binding.adapter.channelKey,
|
|
569
560
|
channelId,
|
|
570
561
|
agentName: binding.agentName,
|
|
571
562
|
replyContext: Object.keys(replyContext).length > 0 ? replyContext : undefined,
|
|
572
|
-
}), {
|
|
573
|
-
kind: 'result.text',
|
|
574
|
-
text,
|
|
575
|
-
isFinal: true,
|
|
576
|
-
format: 'markdown',
|
|
577
563
|
});
|
|
578
|
-
|
|
564
|
+
const attempts = [
|
|
565
|
+
{
|
|
566
|
+
mode: 'notice',
|
|
567
|
+
send: () => binding.adapter.send(envelopeFor('notice'), {
|
|
568
|
+
kind: 'system.notice',
|
|
569
|
+
text,
|
|
570
|
+
subtype: 'memory.consolidation.result',
|
|
571
|
+
}),
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
mode: 'text',
|
|
575
|
+
send: () => binding.adapter.send(envelopeFor('text'), {
|
|
576
|
+
kind: 'result.text',
|
|
577
|
+
text,
|
|
578
|
+
isFinal: true,
|
|
579
|
+
format: 'markdown',
|
|
580
|
+
}),
|
|
581
|
+
},
|
|
582
|
+
];
|
|
583
|
+
const failures = [];
|
|
584
|
+
for (const { mode, send } of attempts) {
|
|
585
|
+
try {
|
|
586
|
+
await send();
|
|
587
|
+
logger.info(`[Memory] 整理反馈已投递(mode=${mode},aid=${selfAid},channelId=${channelId})`);
|
|
588
|
+
}
|
|
589
|
+
catch (error) {
|
|
590
|
+
failures.push(`${mode}: ${error?.message}`);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
if (failures.length > 0)
|
|
594
|
+
throw new Error(failures.join('; '));
|
|
579
595
|
};
|
|
580
596
|
}
|
|
581
597
|
export function registerConsolidationSessionEvents({ eventBus, permissionGateway, finalize, }) {
|
|
@@ -583,28 +599,43 @@ export function registerConsolidationSessionEvents({ eventBus, permissionGateway
|
|
|
583
599
|
if ('sessionId' in event && event.sessionId) {
|
|
584
600
|
permissionGateway.cancelAll(event.sessionId, event.reason || 'interrupted');
|
|
585
601
|
}
|
|
586
|
-
void finalize(event.sessionId, false);
|
|
587
602
|
});
|
|
588
603
|
eventBus.subscribe('task:error', event => {
|
|
589
604
|
if ('sessionId' in event && event.sessionId) {
|
|
590
605
|
permissionGateway.cancelAll(event.sessionId, 'task_error', false);
|
|
591
606
|
}
|
|
592
|
-
void finalize(event.sessionId, false);
|
|
593
607
|
});
|
|
594
608
|
eventBus.subscribe('task:completed', event => {
|
|
595
609
|
if ('sessionId' in event && event.sessionId) {
|
|
596
610
|
permissionGateway.cancelAll(event.sessionId, 'task_completed', false);
|
|
597
611
|
}
|
|
598
|
-
|
|
612
|
+
});
|
|
613
|
+
eventBus.subscribe('bg-session:completed', event => {
|
|
614
|
+
if (event.type === 'bg-session:completed')
|
|
615
|
+
void finalize(event.sessionId, true);
|
|
616
|
+
});
|
|
617
|
+
eventBus.subscribe('bg-session:error', event => {
|
|
618
|
+
if (event.type === 'bg-session:error')
|
|
619
|
+
void finalize(event.sessionId, false);
|
|
620
|
+
});
|
|
621
|
+
eventBus.subscribe('bg-session:interrupted', event => {
|
|
622
|
+
if (event.type === 'bg-session:interrupted')
|
|
623
|
+
void finalize(event.sessionId, false);
|
|
599
624
|
});
|
|
600
625
|
}
|
|
601
626
|
export class ConsolidationQueue {
|
|
602
627
|
daemonChannel;
|
|
603
628
|
activeAgents = new Set();
|
|
604
629
|
queues = new Map();
|
|
630
|
+
activeSessions = new Map();
|
|
631
|
+
timers = new Map();
|
|
632
|
+
finalizer;
|
|
605
633
|
constructor(daemonChannel) {
|
|
606
634
|
this.daemonChannel = daemonChannel;
|
|
607
635
|
}
|
|
636
|
+
setFinalizer(finalizer) {
|
|
637
|
+
this.finalizer = finalizer;
|
|
638
|
+
}
|
|
608
639
|
async enqueue(params) {
|
|
609
640
|
const aid = params.taskCtx.selfAid;
|
|
610
641
|
if (!aid)
|
|
@@ -619,9 +650,30 @@ export class ConsolidationQueue {
|
|
|
619
650
|
this.queues.set(aid, queue);
|
|
620
651
|
logger.info(`[Memory] 整理请求入队(aid=${aid},mode=${params.mode},` +
|
|
621
652
|
`队列长度=${queue.length},全局活跃=${this.activeAgents.size})`);
|
|
622
|
-
return
|
|
653
|
+
return {
|
|
654
|
+
triggerId: '',
|
|
655
|
+
contextFile: '',
|
|
656
|
+
contextFilePath: '',
|
|
657
|
+
batchDir: '',
|
|
658
|
+
queued: {
|
|
659
|
+
position: queue.length,
|
|
660
|
+
agentQueueLength: queue.length,
|
|
661
|
+
agentBusy,
|
|
662
|
+
activeCount: this.activeAgents.size,
|
|
663
|
+
maxConcurrent: MAX_CONCURRENT_CONSOLIDATION,
|
|
664
|
+
totalQueued: [...this.queues.values()].reduce((total, pending) => total + pending.length, 0),
|
|
665
|
+
},
|
|
666
|
+
};
|
|
623
667
|
}
|
|
624
|
-
release(aid) {
|
|
668
|
+
release(aid, sessionId) {
|
|
669
|
+
const activeSessionId = this.activeSessions.get(aid);
|
|
670
|
+
if (sessionId && activeSessionId !== undefined && activeSessionId !== sessionId)
|
|
671
|
+
return;
|
|
672
|
+
const timer = this.timers.get(aid);
|
|
673
|
+
if (timer)
|
|
674
|
+
clearTimeout(timer);
|
|
675
|
+
this.timers.delete(aid);
|
|
676
|
+
this.activeSessions.delete(aid);
|
|
625
677
|
this.activeAgents.delete(aid);
|
|
626
678
|
void this.drain();
|
|
627
679
|
}
|
|
@@ -631,7 +683,30 @@ export class ConsolidationQueue {
|
|
|
631
683
|
return null;
|
|
632
684
|
this.activeAgents.add(aid);
|
|
633
685
|
try {
|
|
634
|
-
|
|
686
|
+
const launched = await launchConsolidation(this.daemonChannel, params);
|
|
687
|
+
if (launched.executionSessionId) {
|
|
688
|
+
const sessionId = launched.executionSessionId;
|
|
689
|
+
this.activeSessions.set(aid, sessionId);
|
|
690
|
+
const timer = setTimeout(() => {
|
|
691
|
+
if (this.activeSessions.get(aid) !== sessionId)
|
|
692
|
+
return;
|
|
693
|
+
logger.warn(`[Memory] 整理会话超时收尾(aid=${aid},session=${sessionId})`);
|
|
694
|
+
if (this.finalizer)
|
|
695
|
+
void this.finalizer(sessionId, false).finally(() => this.release(aid, sessionId));
|
|
696
|
+
else
|
|
697
|
+
this.release(aid, sessionId);
|
|
698
|
+
}, 15 * 60_000);
|
|
699
|
+
timer.unref?.();
|
|
700
|
+
this.timers.set(aid, timer);
|
|
701
|
+
}
|
|
702
|
+
appendOpsRecord(launched.batchDir, {
|
|
703
|
+
ts: new Date().toISOString(),
|
|
704
|
+
op: 'session-start',
|
|
705
|
+
sessionId: launched.executionSessionId ?? launched.triggerId,
|
|
706
|
+
mode: params.mode,
|
|
707
|
+
triggeredBy: params.triggeredBy,
|
|
708
|
+
});
|
|
709
|
+
return launched;
|
|
635
710
|
}
|
|
636
711
|
catch (error) {
|
|
637
712
|
logger.warn(`[Memory] 拉起整理会话失败(aid=${aid},mode=${params.mode}): ${error?.message}`);
|
|
@@ -659,33 +734,17 @@ export class ConsolidationQueue {
|
|
|
659
734
|
}
|
|
660
735
|
}
|
|
661
736
|
}
|
|
662
|
-
export function registerConsolidationLaunchExecutor({ ipcServer,
|
|
737
|
+
export function registerConsolidationLaunchExecutor({ ipcServer, enqueueConsolidation, }) {
|
|
663
738
|
ipcServer.setConsolidationLaunchExecutor(async (params) => {
|
|
664
739
|
if (!params.taskCtx.selfAid)
|
|
665
740
|
throw new Error('无法确定当前 agent AID(selfAid 为空)');
|
|
666
741
|
const launched = await enqueueConsolidation(params);
|
|
667
|
-
if (!launched)
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
batchDir: '',
|
|
674
|
-
queued: true,
|
|
675
|
-
};
|
|
676
|
-
}
|
|
677
|
-
appendOpsRecord(launched.batchDir, {
|
|
678
|
-
ts: new Date().toISOString(),
|
|
679
|
-
op: 'session-start',
|
|
680
|
-
sessionId: launched.triggerId,
|
|
681
|
-
mode: params.mode,
|
|
682
|
-
triggeredBy: params.triggeredBy,
|
|
683
|
-
});
|
|
684
|
-
const ids = await waitForConsolidationSession({
|
|
685
|
-
executionSessionId: launched.executionSessionId,
|
|
686
|
-
readAgentSessionId: async (id) => (await sessionManager.getSessionById(id))?.agentSessionId,
|
|
687
|
-
});
|
|
688
|
-
return { ...launched, ...ids };
|
|
742
|
+
if (!launched)
|
|
743
|
+
throw new Error('拉起整理会话失败,详见 daemon 日志');
|
|
744
|
+
if (launched.queued)
|
|
745
|
+
return launched;
|
|
746
|
+
const { waitForAgentSessionId, ...result } = launched;
|
|
747
|
+
return result;
|
|
689
748
|
});
|
|
690
749
|
}
|
|
691
750
|
export function registerConsolidationCheckExecutor({ ipcServer, agentRegistry, enqueueConsolidation, }) {
|