evolcore 0.0.29 → 0.0.30
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 +7 -0
- package/dist/agents/codex-runner.js +61 -14
- package/dist/aun/aid/agentmd.js +224 -19
- package/dist/aun/aid/index.js +2 -1
- package/dist/aun/aid/managed-operation.js +70 -4
- package/dist/aun/group/index.js +1 -0
- package/dist/{core → aun}/group/invite-service.js +4 -4
- package/dist/channels/daemon.js +1 -1
- package/dist/cli/agent-command.js +7 -7
- package/dist/cli/aun-commands.js +97 -37
- package/dist/cli/data-command.js +2 -1
- package/dist/cli/managed-command-guard.js +2 -2
- package/dist/cli/model.js +1 -1
- package/dist/cli/response.js +1 -1
- package/dist/cli/trigger-command.js +52 -29
- package/dist/config/boot-log.js +95 -1
- package/dist/config/builtin-roles.js +1 -0
- package/dist/config/peer-role-resolver.js +21 -0
- package/dist/core/agent-ipc-registration.js +409 -0
- package/dist/core/agent-runtime.js +435 -0
- package/dist/core/auth/delegation-authorization.js +58 -0
- package/dist/core/auth/operation-catalog.js +8 -0
- package/dist/core/bootstrap-service.js +65 -1
- package/dist/core/channel-runtime.js +435 -0
- package/dist/core/command/command-handler.js +4 -1
- package/dist/core/daemon-bootstrap.js +151 -0
- package/dist/core/daemon-control.js +205 -0
- package/dist/core/daemon-lifecycle.js +225 -0
- package/dist/core/data-migration.js +4 -1
- package/dist/core/handoff/ipc-registration.js +156 -0
- package/dist/core/ipc-registration.js +457 -0
- package/dist/core/memory/consolidation-trigger.js +8 -0
- package/dist/core/memory/consolidation.js +838 -0
- package/dist/core/message/aun-ipc-sender.js +226 -0
- package/dist/core/message/outbound.js +165 -0
- package/dist/core/permission/approval-gateway.js +13 -0
- package/dist/core/permission/ec-command-parser.js +80 -35
- package/dist/core/permission/sandbox-runtime.js +23 -2
- package/dist/core/permission/tool-error-code.js +1 -0
- package/dist/core/permission/tool-policy.js +61 -24
- package/dist/core/session/session-idle-monitor.js +17 -0
- package/dist/index.js +352 -4841
- package/dist/ipc.js +2 -1
- package/dist/stats/db.js +24 -0
- package/dist/stats/index.js +1 -1
- package/dist/stats/writer.js +25 -1
- package/dist/trigger/application-service.js +157 -0
- package/dist/trigger/authorization.js +371 -0
- package/dist/trigger/ipc-service.js +406 -0
- package/dist/trigger/local-files.js +133 -0
- package/dist/trigger/manager.js +235 -22
- package/dist/trigger/scheduler.js +30 -5
- package/dist/trigger/script-executor.js +176 -39
- package/dist/trigger/script-sandbox.js +458 -0
- package/dist/trigger/system-definitions.js +188 -0
- package/dist/trigger/validation.js +0 -3
- package/dist/utils/aid-bind.js +1 -1
- package/dist/utils/evolcore-version.js +74 -0
- package/dist/utils/logger.js +16 -0
- package/kits/docs/evolcore/INDEX.md +1 -1
- package/kits/docs/evolcore/aid.md +9 -1
- package/kits/docs/evolcore/model.md +3 -2
- package/kits/docs/evolcore/rpc.md +4 -0
- package/kits/docs/evolcore/trigger.md +15 -1
- package/kits/schemas/relation-config.schema.9.json +1 -1
- package/kits/templates/system-fragments/commands.md +0 -1
- package/package.json +1 -1
- package/dist/core/memory/launch-consolidation.js +0 -395
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
import { TriggerDefinitionManager } from '../trigger/manager.js';
|
|
2
|
+
import { logger } from '../utils/logger.js';
|
|
3
|
+
import crypto from 'crypto';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { executeTaskResume } from './task/task-resume-operation.js';
|
|
7
|
+
import { isHClassPath, isSameOrDescendant } from './permission/protected-paths.js';
|
|
8
|
+
import { computeBuildId } from '../utils/evolcore-version.js';
|
|
9
|
+
import { loadAgent } from '../config-store.js';
|
|
10
|
+
import { executeLocalInitializationCommand, hasSuppliedInitialization } from '../cli/agent-create.js';
|
|
11
|
+
import { remoteAccessService } from './auth/remote-access-store.js';
|
|
12
|
+
import { createDelegationAuthorizer } from './auth/delegation-authorization.js';
|
|
13
|
+
import { executeDiagIpc } from './command/diag-service.js';
|
|
14
|
+
import { registerAgentOperationExecutor } from './agent-ipc-registration.js';
|
|
15
|
+
import { registerHandoffIpc } from './handoff/ipc-registration.js';
|
|
16
|
+
import { registerAunIpcSender } from './message/aun-ipc-sender.js';
|
|
17
|
+
import { registerConsolidationCheckExecutor, registerConsolidationLaunchExecutor, } from './memory/consolidation.js';
|
|
18
|
+
import { createTriggerBaseagentResolver, registerTriggerIpcExecutor } from '../trigger/ipc-service.js';
|
|
19
|
+
import { isLinkedInstall } from '../utils/npm-ops.js';
|
|
20
|
+
export function registerDaemonIpc({ ipcServer, agentRegistry, agentDelegationRegistry, sessionManager, statsCollector, aidStatsCollector, responseEngine, messageQueue, agentMap, commandHandler, channelInstances, eventBus, handoffRuntime, reloadCoordinator, agentApplicationService, agentInitializationService, enqueueConsolidation, completeAgentBootstrap, contactBinds, bindService, diagService, getProcessOwners, getControlAidState, daemonAid, triggerControlToken, triggerSchedulers, daemonTriggerOwner, primaryAgent, triggerAuthorization, }) {
|
|
21
|
+
const authorizeManagedAgentOperation = createDelegationAuthorizer({
|
|
22
|
+
agentDelegationRegistry,
|
|
23
|
+
sessionManager,
|
|
24
|
+
getProcessOwners,
|
|
25
|
+
});
|
|
26
|
+
registerCommandIpcProviders({
|
|
27
|
+
ipcServer,
|
|
28
|
+
agentRegistry,
|
|
29
|
+
triggerControlToken,
|
|
30
|
+
remoteAccessService,
|
|
31
|
+
authorizeManagedAgentOperation,
|
|
32
|
+
hasSuppliedInitialization,
|
|
33
|
+
loadAgent,
|
|
34
|
+
completeAgentBootstrap,
|
|
35
|
+
contactBinds,
|
|
36
|
+
cmdHandler: commandHandler,
|
|
37
|
+
executeDiag: command => executeDiagIpc(diagService, agentDelegationRegistry, getProcessOwners(), command),
|
|
38
|
+
channelInstances,
|
|
39
|
+
getControlAidState,
|
|
40
|
+
daemonAid,
|
|
41
|
+
bindService,
|
|
42
|
+
});
|
|
43
|
+
registerRuntimeIpcProviders({
|
|
44
|
+
ipcServer,
|
|
45
|
+
channelInstances,
|
|
46
|
+
messageQueue,
|
|
47
|
+
aidStatsCollector,
|
|
48
|
+
responseEngine,
|
|
49
|
+
sessionManager,
|
|
50
|
+
agentDelegationRegistry,
|
|
51
|
+
agentMap,
|
|
52
|
+
isLinkedInstall: isLinkedInstall(),
|
|
53
|
+
});
|
|
54
|
+
registerHandoffIpc({
|
|
55
|
+
ipcServer,
|
|
56
|
+
agentDelegationRegistry,
|
|
57
|
+
responseEngine,
|
|
58
|
+
sessionManager,
|
|
59
|
+
agentRegistry,
|
|
60
|
+
handoffRuntime,
|
|
61
|
+
getProcessOwners,
|
|
62
|
+
});
|
|
63
|
+
registerAunIpcSender({ ipcServer, channelInstances, agentDelegationRegistry, responseEngine, handoffRuntime });
|
|
64
|
+
ipcServer.setAgentReloadExecutor((aid, options) => reloadCoordinator.reload(aid, options));
|
|
65
|
+
registerConsolidationCheckExecutor({ ipcServer, agentRegistry, enqueueConsolidation });
|
|
66
|
+
ipcServer.setInitializationExecutor(async (command) => executeLocalInitializationCommand(agentInitializationService, command));
|
|
67
|
+
ipcServer.setAgentApplicationService(agentApplicationService);
|
|
68
|
+
registerQueueIpcProviders({ ipcServer, statsCollector, agentRegistry, messageQueue });
|
|
69
|
+
registerAgentOperationExecutor({
|
|
70
|
+
ipcServer,
|
|
71
|
+
sessionManager,
|
|
72
|
+
agentDelegationRegistry,
|
|
73
|
+
eventBus,
|
|
74
|
+
responseEngine,
|
|
75
|
+
handoffRuntime,
|
|
76
|
+
agentApplicationService,
|
|
77
|
+
agentInitializationService,
|
|
78
|
+
});
|
|
79
|
+
registerOperationIpcProviders({
|
|
80
|
+
ipcServer,
|
|
81
|
+
sessionManager,
|
|
82
|
+
messageQueue,
|
|
83
|
+
agentRegistry,
|
|
84
|
+
authorizeManagedAgentOperation,
|
|
85
|
+
recoverTask: request => responseEngine.recoverTask(request),
|
|
86
|
+
});
|
|
87
|
+
registerConsolidationLaunchExecutor({ ipcServer, sessionManager, enqueueConsolidation });
|
|
88
|
+
registerTriggerIpcExecutor(ipcServer, {
|
|
89
|
+
daemonTriggerOwnerAid: daemonTriggerOwner.aid,
|
|
90
|
+
daemonTriggerBaseagent: daemonTriggerOwner.baseagent,
|
|
91
|
+
getScheduler: agentAid => triggerSchedulers.get(agentAid),
|
|
92
|
+
hasAgent: agentAid => !!agentRegistry.get(agentAid),
|
|
93
|
+
getAgentBaseagent: agentAid => agentRegistry.get(agentAid)?.baseagent,
|
|
94
|
+
getAvailableBaseagents: createTriggerBaseagentResolver({
|
|
95
|
+
daemonTriggerOwnerAid: daemonTriggerOwner.aid,
|
|
96
|
+
getAgentName: agentAid => agentRegistry.get(agentAid)?.name,
|
|
97
|
+
getDaemonAgentName: () => primaryAgent?.name,
|
|
98
|
+
agentMap,
|
|
99
|
+
}),
|
|
100
|
+
getSessionById: sessionId => sessionManager.getSessionById(sessionId),
|
|
101
|
+
...triggerAuthorization,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
export function createIpcStatusProvider(dependencies) {
|
|
105
|
+
return () => {
|
|
106
|
+
const channels = {};
|
|
107
|
+
const channelsByType = {};
|
|
108
|
+
for (const instance of dependencies.channelInstances) {
|
|
109
|
+
const name = instance.adapter.channelName;
|
|
110
|
+
const status = instance.channel.getStatus?.() ?? { connected: true };
|
|
111
|
+
const channelType = instance.channelType || name;
|
|
112
|
+
channels[name] = { ...status, channelType };
|
|
113
|
+
if (!channelsByType[channelType])
|
|
114
|
+
channelsByType[channelType] = [];
|
|
115
|
+
channelsByType[channelType].push(name);
|
|
116
|
+
}
|
|
117
|
+
const snapshot = dependencies.statsCollector.getSnapshot();
|
|
118
|
+
const agents = dependencies.agentRegistry.list();
|
|
119
|
+
const runtimeError = dependencies.getAgentRuntimeError();
|
|
120
|
+
return {
|
|
121
|
+
pid: process.pid,
|
|
122
|
+
uptime: snapshot.uptimeMs,
|
|
123
|
+
build: {
|
|
124
|
+
runtimeMode: dependencies.runtimeIsDist ? 'dist' : 'source',
|
|
125
|
+
runtimeId: dependencies.runtimeBuildIdentity.id,
|
|
126
|
+
diskDistId: computeBuildId(dependencies.diskDistDir),
|
|
127
|
+
entry: dependencies.runtimeBuildIdentity.entry,
|
|
128
|
+
version: dependencies.runtimeBuildIdentity.version,
|
|
129
|
+
},
|
|
130
|
+
controlPlane: { ready: true, owned: dependencies.getProcessOwners().length > 0 },
|
|
131
|
+
agentRuntime: {
|
|
132
|
+
state: dependencies.getAgentRuntimeState(),
|
|
133
|
+
runnableAgents: agents.filter(agent => agent.status !== 'error' && agent.status !== 'disabled').length,
|
|
134
|
+
runningAgents: agents.filter(agent => agent.status === 'running').length,
|
|
135
|
+
...(runtimeError ? { error: runtimeError } : {}),
|
|
136
|
+
},
|
|
137
|
+
channels,
|
|
138
|
+
channelsByType,
|
|
139
|
+
queue: { pending: dependencies.messageQueue.getGlobalQueueLength(), processing: dependencies.messageQueue.getGlobalProcessingCount() },
|
|
140
|
+
stats: {
|
|
141
|
+
received: snapshot.lastHour.received,
|
|
142
|
+
sent: snapshot.lastHour.sent,
|
|
143
|
+
completed: snapshot.lastHour.completed,
|
|
144
|
+
errors: snapshot.lastHour.errors,
|
|
145
|
+
avgResponseMs: snapshot.lastHour.avgResponseMs,
|
|
146
|
+
},
|
|
147
|
+
controlAid: (() => {
|
|
148
|
+
if (!dependencies.daemonAid)
|
|
149
|
+
return undefined;
|
|
150
|
+
const aidState = dependencies.getControlAidState();
|
|
151
|
+
return {
|
|
152
|
+
aid: dependencies.daemonAid,
|
|
153
|
+
connected: aidState?.status === 'connected',
|
|
154
|
+
...(aidState ? {
|
|
155
|
+
status: aidState.status,
|
|
156
|
+
gatewayUrl: aidState.gatewayUrl,
|
|
157
|
+
reconnectCount: aidState.reconnectCount,
|
|
158
|
+
lastConnectedAt: aidState.lastConnectedAt,
|
|
159
|
+
lastTransportEventAt: aidState.lastTransportEventAt,
|
|
160
|
+
lastInboundAt: aidState.lastInboundAt,
|
|
161
|
+
lastError: aidState.lastError,
|
|
162
|
+
} : {}),
|
|
163
|
+
};
|
|
164
|
+
})(),
|
|
165
|
+
};
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
export function registerRuntimeIpcProviders({ ipcServer, channelInstances, messageQueue, aidStatsCollector, responseEngine, sessionManager, agentDelegationRegistry, agentMap, isLinkedInstall, }) {
|
|
169
|
+
ipcServer.setAunAidProvider(() => {
|
|
170
|
+
const out = [];
|
|
171
|
+
for (const instance of channelInstances) {
|
|
172
|
+
if (instance.channelType !== 'aun')
|
|
173
|
+
continue;
|
|
174
|
+
const channel = instance.channel;
|
|
175
|
+
if (typeof channel?.getAidState !== 'function')
|
|
176
|
+
continue;
|
|
177
|
+
try {
|
|
178
|
+
const aidState = channel.getAidState();
|
|
179
|
+
const agentName = aidState.agentName || aidState.aid;
|
|
180
|
+
const processing = messageQueue.getProcessingCountByAgent(agentName);
|
|
181
|
+
const queued = messageQueue.getQueueLengthByAgent(agentName);
|
|
182
|
+
out.push({ ...aidState, queueStatus: { processing, queued } });
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
// A channel may disappear while its state is being collected.
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return out;
|
|
189
|
+
});
|
|
190
|
+
for (const instance of channelInstances) {
|
|
191
|
+
if (instance.channelType !== 'aun')
|
|
192
|
+
continue;
|
|
193
|
+
const channel = instance.channel;
|
|
194
|
+
if (typeof channel?.setAidStatsCollector === 'function') {
|
|
195
|
+
channel.setAidStatsCollector(aidStatsCollector);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
aidStatsCollector.setQueueStatsProvider((agentName) => ({
|
|
199
|
+
processing: messageQueue.getProcessingCountByAgent(agentName),
|
|
200
|
+
queued: messageQueue.getQueueLengthByAgent(agentName),
|
|
201
|
+
muted: messageQueue.isAgentMuted(agentName),
|
|
202
|
+
}));
|
|
203
|
+
ipcServer.setAunAidStatsProvider(() => aidStatsCollector.getAllSnapshots());
|
|
204
|
+
ipcServer.setAunAidStatsRecorder((params) => {
|
|
205
|
+
aidStatsCollector.recordOutbound(params.aid, params.toPeer, Buffer.byteLength(params.text || '', 'utf-8'), params.text, false, params.encrypt, params.chatmode, 'send');
|
|
206
|
+
});
|
|
207
|
+
ipcServer.setTaskRuntimeContextProvider(({ sessionId }) => responseEngine.getTaskRuntimeContext(sessionId));
|
|
208
|
+
if (isLinkedInstall) {
|
|
209
|
+
ipcServer.setDebugTaskRuntimeContextProvider(async ({ sessionId }) => {
|
|
210
|
+
const session = await sessionManager.getSessionById(sessionId);
|
|
211
|
+
if (!session)
|
|
212
|
+
return null;
|
|
213
|
+
const { buildDebugTaskContext } = await import('./memory/consolidation.js');
|
|
214
|
+
const { ensureSessionRuntimeDir } = await import('../cli/task-context.js');
|
|
215
|
+
return buildDebugTaskContext({
|
|
216
|
+
session,
|
|
217
|
+
getTrigger: (agentAid, triggerId) => new TriggerDefinitionManager(agentAid).get(triggerId),
|
|
218
|
+
sessionRuntimeDir: ensureSessionRuntimeDir(session.id),
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
logger.info('[Memory] 开发仓安装:已启用 ec memory --debug <sessionId>');
|
|
222
|
+
}
|
|
223
|
+
ipcServer.setTaskRuntimeContextAuthorizer(({ sessionId, delegationToken, delegationCommandHash }) => {
|
|
224
|
+
const authorization = agentDelegationRegistry.validateForContext(delegationToken, sessionId, delegationCommandHash);
|
|
225
|
+
return authorization.ok
|
|
226
|
+
? { ok: true }
|
|
227
|
+
: { ok: false, code: authorization.code, error: authorization.reason };
|
|
228
|
+
});
|
|
229
|
+
ipcServer.setCodexPreToolUseExecutor(async (params) => {
|
|
230
|
+
for (const runner of new Set(agentMap.values())) {
|
|
231
|
+
if (typeof runner?.evaluatePreToolUse !== 'function')
|
|
232
|
+
continue;
|
|
233
|
+
const result = await runner.evaluatePreToolUse(params.threadId, params.toolName, params.toolInput, params.signal, params.callId, params.sessionToken);
|
|
234
|
+
if (result.applicable)
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
ok: false,
|
|
239
|
+
applicable: true,
|
|
240
|
+
decision: 'deny',
|
|
241
|
+
reason: 'No active EvolCore Codex runner accepted this managed hook credential',
|
|
242
|
+
};
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
export function registerQueueIpcProviders({ ipcServer, statsCollector, agentRegistry, messageQueue, }) {
|
|
246
|
+
ipcServer.setStatsProvider(() => statsCollector.getSnapshot());
|
|
247
|
+
ipcServer.setAgentStatsProvider(() => {
|
|
248
|
+
const agents = agentRegistry.list();
|
|
249
|
+
const snapshots = statsCollector.getSnapshots(agents.map(agent => agent.aid));
|
|
250
|
+
return agents.map((agent) => {
|
|
251
|
+
const snapshot = snapshots.get(agent.aid);
|
|
252
|
+
return {
|
|
253
|
+
aid: agent.aid,
|
|
254
|
+
received: snapshot.lastHour.received,
|
|
255
|
+
sent: snapshot.lastHour.sent,
|
|
256
|
+
completed: snapshot.lastHour.completed,
|
|
257
|
+
errors: snapshot.lastHour.errors,
|
|
258
|
+
interrupts: snapshot.lastHour.interrupts,
|
|
259
|
+
avgResponseMs: snapshot.lastHour.avgResponseMs,
|
|
260
|
+
processing: messageQueue.getProcessingCountByAgent(agent.aid),
|
|
261
|
+
queued: messageQueue.getQueueLengthByAgent(agent.aid),
|
|
262
|
+
muted: messageQueue.isAgentMuted(agent.aid),
|
|
263
|
+
};
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
ipcServer.setQueueSnapshotProvider((params) => {
|
|
267
|
+
const handle = agentRegistry.get(params.agent);
|
|
268
|
+
const agentName = handle?.name;
|
|
269
|
+
if (!agentName)
|
|
270
|
+
return [];
|
|
271
|
+
return messageQueue.getQueueItemsByAgent(agentName, { after: params.after, before: params.before });
|
|
272
|
+
});
|
|
273
|
+
ipcServer.setQueueActionExecutor(async (params) => {
|
|
274
|
+
const handle = agentRegistry.get(params.agent);
|
|
275
|
+
const agentName = handle?.name;
|
|
276
|
+
if (!agentName)
|
|
277
|
+
return { ok: false, error: `agent not found: ${params.agent}` };
|
|
278
|
+
switch (params.action) {
|
|
279
|
+
case 'clear':
|
|
280
|
+
return { ok: true, cleared: messageQueue.clearByAgent(agentName) };
|
|
281
|
+
case 'cancel':
|
|
282
|
+
if (!params.messageId)
|
|
283
|
+
return { ok: false, error: 'missing messageId' };
|
|
284
|
+
return { ok: true, cancelled: messageQueue.cancelMessageById(agentName, params.messageId) };
|
|
285
|
+
case 'interrupt': {
|
|
286
|
+
if (!params.sessionKey)
|
|
287
|
+
return { ok: false, error: 'missing sessionKey' };
|
|
288
|
+
const sessionId = messageQueue.findSessionIdBySessionKey(params.sessionKey);
|
|
289
|
+
if (!sessionId)
|
|
290
|
+
return { ok: false, error: `session not found: ${params.sessionKey}` };
|
|
291
|
+
return { ok: true, interrupted: await messageQueue.interruptBySession(sessionId) };
|
|
292
|
+
}
|
|
293
|
+
default:
|
|
294
|
+
return { ok: false, error: `unknown action: ${params.action}` };
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
export function registerCommandIpcProviders({ ipcServer, agentRegistry, triggerControlToken, remoteAccessService, authorizeManagedAgentOperation, hasSuppliedInitialization, loadAgent, completeAgentBootstrap, contactBinds, cmdHandler, executeDiag, channelInstances, getControlAidState, daemonAid, bindService, }) {
|
|
299
|
+
ipcServer.setAgentRegistry(agentRegistry);
|
|
300
|
+
ipcServer.setControlToken(triggerControlToken);
|
|
301
|
+
ipcServer.setRemoteAccessService(remoteAccessService);
|
|
302
|
+
ipcServer.setBootstrapCompleteExecutor(async (aid, auth) => {
|
|
303
|
+
if (auth?.sessionId) {
|
|
304
|
+
const authorization = await authorizeManagedAgentOperation({
|
|
305
|
+
sessionId: auth.sessionId,
|
|
306
|
+
delegationToken: auth.delegationToken,
|
|
307
|
+
delegationCommandHash: auth.delegationCommandHash,
|
|
308
|
+
targetAid: aid,
|
|
309
|
+
}, 'agent.bootstrapComplete');
|
|
310
|
+
if (!authorization.ok)
|
|
311
|
+
return authorization;
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
const providedToken = typeof auth?.controlToken === 'string' ? Buffer.from(auth.controlToken) : undefined;
|
|
315
|
+
const expectedToken = Buffer.from(triggerControlToken);
|
|
316
|
+
if (!providedToken
|
|
317
|
+
|| providedToken.length !== expectedToken.length
|
|
318
|
+
|| !crypto.timingSafeEqual(providedToken, expectedToken)) {
|
|
319
|
+
return { ok: false, code: 'INVALID_CONTROL_TOKEN', error: 'valid local control token is required' };
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
if (hasSuppliedInitialization(aid) || loadAgent(aid)?.initialization) {
|
|
323
|
+
return { ok: false, code: 'INITIALIZATION_MANAGED', error: 'Use the initialization service for this Agent' };
|
|
324
|
+
}
|
|
325
|
+
return completeAgentBootstrap(aid);
|
|
326
|
+
});
|
|
327
|
+
ipcServer.setDingtalkContactBindExecutor(contactBinds.dingtalk);
|
|
328
|
+
ipcServer.setFeishuContactBindExecutor(contactBinds.feishu);
|
|
329
|
+
ipcServer.setQQBotContactBindExecutor(contactBinds.qqbot);
|
|
330
|
+
ipcServer.setWecomContactBindExecutor(contactBinds.wecom);
|
|
331
|
+
ipcServer.setWechatContactBindExecutor(contactBinds.wechat);
|
|
332
|
+
ipcServer.setMenuExecutor((payload, auth) => cmdHandler.execMenuForEcweb(payload, auth));
|
|
333
|
+
ipcServer.setConfigOperationExecutor((argv, sessionId, delegationToken, delegationCommandHash) => cmdHandler.handleConfigOperation(argv, sessionId, delegationToken, delegationCommandHash));
|
|
334
|
+
ipcServer.setContactOperationExecutor((argv, sessionId, delegationToken, delegationCommandHash) => cmdHandler.handleContactOperation(argv, sessionId, delegationToken, delegationCommandHash));
|
|
335
|
+
ipcServer.setAidOperationExecutor((argv, sessionId, delegationToken, delegationCommandHash) => cmdHandler.handleAidOperation(argv, sessionId, delegationToken, delegationCommandHash));
|
|
336
|
+
ipcServer.setDiagExecutor(command => executeDiag(command));
|
|
337
|
+
ipcServer.setMenuClientExecutor(async (command) => {
|
|
338
|
+
if (!Array.isArray(command.argv)
|
|
339
|
+
|| command.argv.some((value) => typeof value !== 'string')
|
|
340
|
+
|| typeof command.sessionId !== 'string') {
|
|
341
|
+
return { ok: false, code: 'INVALID_ARGUMENT', error: 'A managed session and Menu argv are required' };
|
|
342
|
+
}
|
|
343
|
+
return cmdHandler.handleMenuClientOperation(command.argv, command.sessionId, command.delegationToken, command.delegationCommandHash, async (options) => {
|
|
344
|
+
const instance = channelInstances.find(item => (item.channelType === 'aun'
|
|
345
|
+
&& item.channel.getAidState()?.aid === options.fromAid));
|
|
346
|
+
if (!instance)
|
|
347
|
+
throw new Error('Current Agent AUN channel is unavailable');
|
|
348
|
+
return instance.channel.requestRemoteMenu(options);
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
ipcServer.setGroupOperationExecutor((argv, sessionId, delegationToken, delegationCommandHash) => cmdHandler.handleGroupOperation(argv, sessionId, delegationToken, delegationCommandHash));
|
|
352
|
+
ipcServer.setMsgOperationExecutor((argv, sessionId, delegationToken, delegationCommandHash) => cmdHandler.handleMsgOperation(argv, sessionId, delegationToken, delegationCommandHash));
|
|
353
|
+
ipcServer.setFsOperationExecutor((argv, sessionId, delegationToken, delegationCommandHash) => cmdHandler.handleFsOperation(argv, sessionId, delegationToken, delegationCommandHash));
|
|
354
|
+
cmdHandler.setDaemonStatusProvider(() => {
|
|
355
|
+
const aidState = getControlAidState();
|
|
356
|
+
return {
|
|
357
|
+
aid: daemonAid ?? null,
|
|
358
|
+
aun: aidState ? {
|
|
359
|
+
connected: aidState.status === 'connected',
|
|
360
|
+
status: aidState.status,
|
|
361
|
+
reconnectCount: aidState.reconnectCount ?? 0,
|
|
362
|
+
flapCount: aidState.flapCount ?? 0,
|
|
363
|
+
...(aidState.lastError ? { lastError: String(aidState.lastError).slice(0, 80) } : {}),
|
|
364
|
+
...(aidState.kickDetail?.reason ? { kickReason: String(aidState.kickDetail.reason).slice(0, 80) } : {}),
|
|
365
|
+
} : {
|
|
366
|
+
connected: false,
|
|
367
|
+
status: daemonAid ? 'disconnected' : 'disabled',
|
|
368
|
+
},
|
|
369
|
+
};
|
|
370
|
+
});
|
|
371
|
+
if (bindService) {
|
|
372
|
+
ipcServer.setBindExecutor({
|
|
373
|
+
begin: command => bindService.begin(command),
|
|
374
|
+
status: taskId => bindService.status(taskId),
|
|
375
|
+
cancel: taskId => bindService.cancel(taskId),
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
export function registerOperationIpcProviders({ ipcServer, sessionManager, messageQueue, agentRegistry, authorizeManagedAgentOperation, recoverTask, }) {
|
|
380
|
+
ipcServer.setTaskResumeExecutor(params => executeTaskResume(params, {
|
|
381
|
+
sessions: sessionManager,
|
|
382
|
+
authorizeManaged: authorizeManagedAgentOperation,
|
|
383
|
+
recover: recoverTask,
|
|
384
|
+
}));
|
|
385
|
+
ipcServer.setQueueOperationExecutor(async (params) => {
|
|
386
|
+
const operation = `ec.queue.${params.action ?? 'read'}`;
|
|
387
|
+
const authorization = await authorizeManagedAgentOperation(params, operation);
|
|
388
|
+
if (!authorization.ok)
|
|
389
|
+
return authorization;
|
|
390
|
+
const handle = agentRegistry.get(authorization.aid);
|
|
391
|
+
if (!handle?.name)
|
|
392
|
+
return { ok: false, code: 'AGENT_NOT_FOUND', error: 'current Agent not found' };
|
|
393
|
+
if (!params.action) {
|
|
394
|
+
return { ok: true, items: messageQueue.getQueueItemsByAgent(handle.name, {
|
|
395
|
+
after: params.after,
|
|
396
|
+
before: params.before,
|
|
397
|
+
}) };
|
|
398
|
+
}
|
|
399
|
+
if (params.action === 'clear')
|
|
400
|
+
return { ok: true, cleared: messageQueue.clearByAgent(handle.name) };
|
|
401
|
+
if (params.action === 'cancel') {
|
|
402
|
+
if (!params.messageId)
|
|
403
|
+
return { ok: false, code: 'INVALID_ARGUMENT', error: 'missing messageId' };
|
|
404
|
+
return { ok: true, cancelled: messageQueue.cancelMessageById(handle.name, params.messageId) };
|
|
405
|
+
}
|
|
406
|
+
if (!params.sessionKey)
|
|
407
|
+
return { ok: false, code: 'INVALID_ARGUMENT', error: 'missing sessionKey' };
|
|
408
|
+
const targetSessionId = messageQueue.findSessionIdBySessionKey(params.sessionKey);
|
|
409
|
+
if (!targetSessionId)
|
|
410
|
+
return { ok: false, code: 'SESSION_NOT_FOUND', error: `session not found: ${params.sessionKey}` };
|
|
411
|
+
const targetSession = await sessionManager.getSessionById(targetSessionId);
|
|
412
|
+
if (!targetSession || targetSession.selfAID !== authorization.aid) {
|
|
413
|
+
return { ok: false, code: 'SCOPE_MISMATCH', error: 'session does not belong to the current Agent' };
|
|
414
|
+
}
|
|
415
|
+
return { ok: true, interrupted: await messageQueue.interruptBySession(targetSessionId) };
|
|
416
|
+
});
|
|
417
|
+
ipcServer.setStatusAuthorizationExecutor(async (params) => {
|
|
418
|
+
const authorization = await authorizeManagedAgentOperation(params, 'system.status');
|
|
419
|
+
return authorization.ok ? { ok: true } : authorization;
|
|
420
|
+
});
|
|
421
|
+
ipcServer.setStorageAuthorizationExecutor(async (params) => {
|
|
422
|
+
const authorization = await authorizeManagedAgentOperation({ ...params, targetAid: params.aid }, params.operation);
|
|
423
|
+
return authorization.ok ? { ok: true } : authorization;
|
|
424
|
+
});
|
|
425
|
+
ipcServer.setStorageUploadExecutor(async (params) => {
|
|
426
|
+
const authorization = await authorizeManagedAgentOperation({ ...params, targetAid: params.aid }, 'storage.upload');
|
|
427
|
+
if (!authorization.ok)
|
|
428
|
+
return authorization;
|
|
429
|
+
const session = await sessionManager.getSessionById(params.sessionId);
|
|
430
|
+
if (!session)
|
|
431
|
+
return { ok: false, code: 'SESSION_NOT_FOUND', error: 'current session not found' };
|
|
432
|
+
try {
|
|
433
|
+
const projectPath = fs.realpathSync(path.resolve(session.projectPath));
|
|
434
|
+
const requestedFile = path.resolve(session.projectPath, params.localFile);
|
|
435
|
+
const requestedStat = fs.lstatSync(requestedFile);
|
|
436
|
+
if (requestedStat.isSymbolicLink()) {
|
|
437
|
+
return { ok: false, code: 'INVALID_LOCAL_FILE', error: 'Upload source must not be a symbolic link' };
|
|
438
|
+
}
|
|
439
|
+
const localFile = fs.realpathSync(requestedFile);
|
|
440
|
+
const stat = fs.lstatSync(localFile);
|
|
441
|
+
if (!isSameOrDescendant(localFile, projectPath) || isHClassPath(localFile)) {
|
|
442
|
+
return { ok: false, code: 'INVALID_LOCAL_PATH', error: 'Upload source must be an unprotected file inside the current session project' };
|
|
443
|
+
}
|
|
444
|
+
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
445
|
+
return { ok: false, code: 'INVALID_LOCAL_FILE', error: 'Upload source must be a regular non-symlink file' };
|
|
446
|
+
}
|
|
447
|
+
const { storageUpload } = await import('../aun/storage/index.js');
|
|
448
|
+
const result = await storageUpload(authorization.aid, localFile, params.remotePath, { isPublic: params.isPublic });
|
|
449
|
+
return result.ok
|
|
450
|
+
? { ok: true, objectKey: result.objectKey, publicUrl: result.publicUrl }
|
|
451
|
+
: { ok: false, code: 'STORAGE_UPLOAD_FAILED', error: result.error };
|
|
452
|
+
}
|
|
453
|
+
catch (error) {
|
|
454
|
+
return { ok: false, code: 'INVALID_LOCAL_FILE', error: error instanceof Error ? error.message : String(error) };
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
}
|
|
@@ -35,6 +35,14 @@ export const META_INDEX_THRESHOLD = 200;
|
|
|
35
35
|
const DEFAULT_CRON = '17 * * * *';
|
|
36
36
|
const SCRIPT_NAME = 'consolidation-check.cjs';
|
|
37
37
|
export const CONSOLIDATION_CHECK_TRIGGER_ID = '__memory-consolidation-check';
|
|
38
|
+
export function consolidationCheckCron(intervalHours) {
|
|
39
|
+
const hours = intervalHours && intervalHours > 0 ? Math.floor(intervalHours) : 1;
|
|
40
|
+
if (hours === 1)
|
|
41
|
+
return '17 * * * *';
|
|
42
|
+
if (hours >= 24)
|
|
43
|
+
return '17 3 * * *';
|
|
44
|
+
return `17 */${hours} * * *`;
|
|
45
|
+
}
|
|
38
46
|
/** Register the periodic consolidation candidate check trigger. */
|
|
39
47
|
export function seedConsolidationCheckTrigger(manager, owner, packageRoot = getPackageRoot()) {
|
|
40
48
|
const now = Date.now();
|