eacn3 0.3.5 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +224 -26
- package/dist/index.js.map +1 -1
- package/dist/server.js +571 -27
- package/dist/server.js.map +1 -1
- package/dist/src/a2a-server.js +2 -1
- package/dist/src/a2a-server.js.map +1 -1
- package/dist/src/event-transport.d.ts +31 -0
- package/dist/src/event-transport.js +178 -0
- package/dist/src/event-transport.js.map +1 -0
- package/dist/src/models.d.ts +55 -11
- package/dist/src/models.js +1 -1
- package/dist/src/models.js.map +1 -1
- package/dist/src/network-client.d.ts +1 -1
- package/dist/src/network-client.js +4 -5
- package/dist/src/network-client.js.map +1 -1
- package/dist/src/reverse-control.d.ts +74 -0
- package/dist/src/reverse-control.js +609 -0
- package/dist/src/reverse-control.js.map +1 -0
- package/dist/src/state.d.ts +17 -4
- package/dist/src/state.js +115 -14
- package/dist/src/state.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -6
- package/scripts/cli.cjs +3 -3
- package/skills/eacn3-bid/SKILL.md +2 -2
- package/skills/eacn3-bid-zh/SKILL.md +2 -2
- package/skills/eacn3-bounty/SKILL.md +7 -7
- package/skills/eacn3-bounty-zh/SKILL.md +7 -7
- package/skills/eacn3-budget/SKILL.md +1 -1
- package/skills/eacn3-budget-zh/SKILL.md +1 -1
- package/skills/eacn3-clarify/SKILL.md +1 -1
- package/skills/eacn3-clarify-zh/SKILL.md +1 -1
- package/skills/eacn3-collect/SKILL.md +1 -1
- package/skills/eacn3-collect-zh/SKILL.md +1 -1
- package/skills/eacn3-dashboard/SKILL.md +3 -3
- package/skills/eacn3-dashboard-zh/SKILL.md +3 -3
- package/skills/eacn3-delegate/SKILL.md +1 -1
- package/skills/eacn3-delegate-zh/SKILL.md +1 -1
- package/skills/eacn3-execute/SKILL.md +1 -1
- package/skills/eacn3-execute-zh/SKILL.md +1 -1
- package/skills/eacn3-invite/SKILL.md +1 -1
- package/skills/eacn3-invite-zh/SKILL.md +1 -1
- package/skills/eacn3-task/SKILL.md +1 -1
- package/skills/eacn3-task-zh/SKILL.md +1 -1
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Reverse Control Engine
|
|
3
|
+
*
|
|
4
|
+
* Enables the MCP Server to proactively drive the Host LLM via:
|
|
5
|
+
* 1. Sampling (sampling/createMessage) — ask LLM to reason and decide
|
|
6
|
+
* 2. Notifications — push state updates to Host
|
|
7
|
+
* 3. Enhanced tool results — inject pending events into any tool response (fallback)
|
|
8
|
+
*
|
|
9
|
+
* When push events arrive from the EACN3 network, instead of just buffering
|
|
10
|
+
* them for polling, this engine evaluates each event and may invoke the Host's LLM
|
|
11
|
+
* to make a decision (bid on a task, reply to a message, etc.).
|
|
12
|
+
*/
|
|
13
|
+
import * as state from "./state.js";
|
|
14
|
+
import * as net from "./network-client.js";
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Constants
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
const MAX_SAMPLING_PER_MINUTE = 10;
|
|
19
|
+
const SAMPLING_TIMEOUT_MS = 30_000;
|
|
20
|
+
const PROCESSED_EVENT_TTL_MS = 300_000; // 5 minutes
|
|
21
|
+
const RATE_WINDOW_MS = 60_000;
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// State
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
let mcpServer = null;
|
|
26
|
+
let samplingAvailable = false;
|
|
27
|
+
let configs = {}; // keyed by agent_id
|
|
28
|
+
const processedEvents = [];
|
|
29
|
+
const samplingTimestamps = [];
|
|
30
|
+
/** Pending directives for the enhanced tool result fallback. */
|
|
31
|
+
const pendingDirectives = [];
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Default policies
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
const DEFAULT_POLICIES = {
|
|
36
|
+
task_broadcast: { method: "sampling" },
|
|
37
|
+
bid_request_confirmation: { method: "sampling" },
|
|
38
|
+
bid_result: { method: "notification" },
|
|
39
|
+
discussion_update: { method: "sampling" },
|
|
40
|
+
subtask_completed: { method: "sampling" },
|
|
41
|
+
task_collected: { method: "notification" },
|
|
42
|
+
task_timeout: { method: "auto_action", autoAction: "report_and_close" },
|
|
43
|
+
adjudication_task: { method: "sampling" },
|
|
44
|
+
direct_message: { method: "sampling" },
|
|
45
|
+
};
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Initialization
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
/**
|
|
50
|
+
* Initialize the reverse control engine with the MCP server instance.
|
|
51
|
+
* Call this after the MCP server is connected and transport is ready.
|
|
52
|
+
*/
|
|
53
|
+
export function init(server) {
|
|
54
|
+
mcpServer = server;
|
|
55
|
+
detectCapabilities();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Detect whether the connected Client supports sampling.
|
|
59
|
+
* Called automatically on init; can be re-called if capabilities change.
|
|
60
|
+
*/
|
|
61
|
+
function detectCapabilities() {
|
|
62
|
+
if (!mcpServer)
|
|
63
|
+
return;
|
|
64
|
+
try {
|
|
65
|
+
// The MCP SDK exposes client capabilities after connection handshake.
|
|
66
|
+
// We check if sampling was declared by the client.
|
|
67
|
+
const clientCaps = mcpServer.getClientCapabilities?.()
|
|
68
|
+
?? mcpServer._clientCapabilities
|
|
69
|
+
?? mcpServer.clientCapabilities;
|
|
70
|
+
samplingAvailable = !!(clientCaps?.sampling);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
samplingAvailable = false;
|
|
74
|
+
}
|
|
75
|
+
console.error(`[ReverseControl] sampling available: ${samplingAvailable}`);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Register reverse control config for an agent.
|
|
79
|
+
* Merges with defaults — only override what you specify.
|
|
80
|
+
*/
|
|
81
|
+
export function configure(agentId, partial) {
|
|
82
|
+
configs[agentId] = {
|
|
83
|
+
enabled: partial?.enabled ?? true,
|
|
84
|
+
policies: { ...DEFAULT_POLICIES, ...(partial?.policies ?? {}) },
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Remove config when agent unregisters.
|
|
89
|
+
*/
|
|
90
|
+
export function unconfigure(agentId) {
|
|
91
|
+
delete configs[agentId];
|
|
92
|
+
}
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
// Core: Event Processing
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
/**
|
|
97
|
+
* Main entry point: process a WebSocket event through the reverse control engine.
|
|
98
|
+
* Called by event-transport's callback instead of directly buffering.
|
|
99
|
+
*
|
|
100
|
+
* Returns true if the event was handled (sampling/notification/auto-action).
|
|
101
|
+
* Returns false if it should fall through to normal event buffering.
|
|
102
|
+
*/
|
|
103
|
+
export async function handleEvent(agentId, event) {
|
|
104
|
+
const config = configs[agentId];
|
|
105
|
+
if (!config?.enabled)
|
|
106
|
+
return false;
|
|
107
|
+
// Dedup: skip already-processed events
|
|
108
|
+
if (event.msg_id && isAlreadyProcessed(event.msg_id)) {
|
|
109
|
+
return true; // silently skip duplicate
|
|
110
|
+
}
|
|
111
|
+
const policy = config.policies[event.type];
|
|
112
|
+
if (!policy || policy.method === "buffer_only")
|
|
113
|
+
return false;
|
|
114
|
+
switch (policy.method) {
|
|
115
|
+
case "sampling":
|
|
116
|
+
return await handleViaSampling(agentId, event);
|
|
117
|
+
case "notification":
|
|
118
|
+
return handleViaNotification(agentId, event);
|
|
119
|
+
case "auto_action":
|
|
120
|
+
return await handleViaAutoAction(agentId, event, policy.autoAction);
|
|
121
|
+
default:
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
// Sampling
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
async function handleViaSampling(agentId, event) {
|
|
129
|
+
// If sampling isn't available, queue as directive for tool-result injection
|
|
130
|
+
if (!samplingAvailable || !mcpServer) {
|
|
131
|
+
queueDirective(agentId, event);
|
|
132
|
+
return false; // still buffer the event
|
|
133
|
+
}
|
|
134
|
+
// Rate limiting
|
|
135
|
+
if (!checkRateLimit()) {
|
|
136
|
+
console.error(`[ReverseControl] sampling rate limit reached, queuing directive`);
|
|
137
|
+
queueDirective(agentId, event);
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
const agent = state.getAgent(agentId);
|
|
141
|
+
if (!agent)
|
|
142
|
+
return false;
|
|
143
|
+
const prompt = buildSamplingPrompt(agentId, agent, event);
|
|
144
|
+
if (!prompt)
|
|
145
|
+
return false;
|
|
146
|
+
try {
|
|
147
|
+
markProcessed(event.msg_id);
|
|
148
|
+
recordSamplingCall();
|
|
149
|
+
const result = await Promise.race([
|
|
150
|
+
requestSampling(prompt),
|
|
151
|
+
timeout(SAMPLING_TIMEOUT_MS),
|
|
152
|
+
]);
|
|
153
|
+
if (!result) {
|
|
154
|
+
console.error(`[ReverseControl] sampling timed out for ${event.type}`);
|
|
155
|
+
queueDirective(agentId, event);
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
const decision = parseSamplingResponse(event.type, result);
|
|
159
|
+
if (decision) {
|
|
160
|
+
await executeDecision(agentId, event, decision);
|
|
161
|
+
}
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
catch (e) {
|
|
165
|
+
console.error(`[ReverseControl] sampling error:`, e.message);
|
|
166
|
+
queueDirective(agentId, event);
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Build the prompt for a sampling request based on event type.
|
|
172
|
+
*/
|
|
173
|
+
function buildSamplingPrompt(agentId, agent, event) {
|
|
174
|
+
const payload = event.payload;
|
|
175
|
+
switch (event.type) {
|
|
176
|
+
case "task_broadcast":
|
|
177
|
+
return [
|
|
178
|
+
`You are agent "${agent.name}" (${agentId}) on the EACN3 network.`,
|
|
179
|
+
`Your domains: [${agent.domains.join(", ")}]`,
|
|
180
|
+
`Your tier: ${agent.tier}`,
|
|
181
|
+
``,
|
|
182
|
+
`A new task is available:`,
|
|
183
|
+
` Task ID: ${event.task_id}`,
|
|
184
|
+
` Domains: [${(payload.domains ?? []).join(", ")}]`,
|
|
185
|
+
` Budget: ${payload.budget ?? "unknown"} credits`,
|
|
186
|
+
` Description: ${payload.description ?? "No description"}`,
|
|
187
|
+
` Level: ${payload.level ?? "general"}`,
|
|
188
|
+
``,
|
|
189
|
+
`Should you bid on this task? If yes, respond in JSON:`,
|
|
190
|
+
`{"action":"bid","confidence":0.0-1.0,"price":number}`,
|
|
191
|
+
`If no, respond: {"action":"ignore","reason":"..."}`,
|
|
192
|
+
].join("\n");
|
|
193
|
+
case "direct_message":
|
|
194
|
+
return [
|
|
195
|
+
`You are agent "${agent.name}" (${agentId}) on the EACN3 network.`,
|
|
196
|
+
``,
|
|
197
|
+
`You received a direct message:`,
|
|
198
|
+
` From: ${payload.from ?? "unknown"}`,
|
|
199
|
+
` Content: ${typeof payload.content === "string" ? payload.content : JSON.stringify(payload.content)}`,
|
|
200
|
+
` Related task: ${event.task_id}`,
|
|
201
|
+
``,
|
|
202
|
+
`How should you respond? Reply in JSON:`,
|
|
203
|
+
`{"action":"reply","message":"your response here"}`,
|
|
204
|
+
`Or to ignore: {"action":"ignore","reason":"..."}`,
|
|
205
|
+
].join("\n");
|
|
206
|
+
case "subtask_completed":
|
|
207
|
+
return [
|
|
208
|
+
`You are agent "${agent.name}" (${agentId}) on the EACN3 network.`,
|
|
209
|
+
``,
|
|
210
|
+
`A subtask you created has completed:`,
|
|
211
|
+
` Parent task: ${event.task_id}`,
|
|
212
|
+
` Subtask ID: ${payload.subtask_id ?? "unknown"}`,
|
|
213
|
+
` Results: ${JSON.stringify(payload.results ?? {}).slice(0, 500)}`,
|
|
214
|
+
``,
|
|
215
|
+
`What should you do next? Options:`,
|
|
216
|
+
`- Submit your final result: {"action":"custom","tool":"eacn3_submit_result","params":{...}}`,
|
|
217
|
+
`- Create another subtask: {"action":"custom","tool":"eacn3_create_subtask","params":{...}}`,
|
|
218
|
+
`- Ignore for now: {"action":"ignore","reason":"..."}`,
|
|
219
|
+
].join("\n");
|
|
220
|
+
case "bid_request_confirmation":
|
|
221
|
+
return [
|
|
222
|
+
`You are agent "${agent.name}" (${agentId}) on the EACN3 network.`,
|
|
223
|
+
``,
|
|
224
|
+
`A bid on your task exceeded the budget:`,
|
|
225
|
+
` Task: ${event.task_id}`,
|
|
226
|
+
` Bidder: ${payload.agent_id ?? "unknown"}`,
|
|
227
|
+
` Bid price: ${payload.price ?? "unknown"} credits`,
|
|
228
|
+
` Excess: ${payload.excess_amount ?? "unknown"} credits`,
|
|
229
|
+
``,
|
|
230
|
+
`Approve this over-budget bid? Respond in JSON:`,
|
|
231
|
+
`{"action":"confirm"} or {"action":"decline","reason":"..."}`,
|
|
232
|
+
].join("\n");
|
|
233
|
+
case "discussion_update":
|
|
234
|
+
return [
|
|
235
|
+
`You are agent "${agent.name}" (${agentId}) on the EACN3 network.`,
|
|
236
|
+
``,
|
|
237
|
+
`The task initiator posted a discussion update:`,
|
|
238
|
+
` Task: ${event.task_id}`,
|
|
239
|
+
` Content: ${JSON.stringify(payload.discussions ?? payload.message ?? {}).slice(0, 500)}`,
|
|
240
|
+
``,
|
|
241
|
+
`How should you respond? Reply in JSON:`,
|
|
242
|
+
`{"action":"reply","message":"your response"}`,
|
|
243
|
+
`Or: {"action":"ignore"}`,
|
|
244
|
+
].join("\n");
|
|
245
|
+
case "adjudication_task":
|
|
246
|
+
return [
|
|
247
|
+
`You are agent "${agent.name}" (${agentId}) on the EACN3 network.`,
|
|
248
|
+
``,
|
|
249
|
+
`You have been asked to adjudicate a dispute:`,
|
|
250
|
+
` Task: ${event.task_id}`,
|
|
251
|
+
` Domains: [${(payload.domains ?? []).join(", ")}]`,
|
|
252
|
+
` Details: ${JSON.stringify(payload.content ?? {}).slice(0, 500)}`,
|
|
253
|
+
``,
|
|
254
|
+
`Evaluate and respond in JSON:`,
|
|
255
|
+
`{"action":"bid","confidence":0.0-1.0,"price":number}`,
|
|
256
|
+
`Or: {"action":"ignore","reason":"..."}`,
|
|
257
|
+
].join("\n");
|
|
258
|
+
default:
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Send a sampling/createMessage request to the Host's LLM.
|
|
264
|
+
*/
|
|
265
|
+
async function requestSampling(prompt) {
|
|
266
|
+
if (!mcpServer)
|
|
267
|
+
return null;
|
|
268
|
+
try {
|
|
269
|
+
// Use the MCP server's request method to send sampling/createMessage
|
|
270
|
+
// to the connected client. The client's LLM will process it.
|
|
271
|
+
const result = await mcpServer.createMessage({
|
|
272
|
+
messages: [
|
|
273
|
+
{
|
|
274
|
+
role: "user",
|
|
275
|
+
content: { type: "text", text: prompt },
|
|
276
|
+
},
|
|
277
|
+
],
|
|
278
|
+
maxTokens: 512,
|
|
279
|
+
});
|
|
280
|
+
// Extract text content from the response
|
|
281
|
+
if (result?.content?.type === "text") {
|
|
282
|
+
return result.content.text;
|
|
283
|
+
}
|
|
284
|
+
if (typeof result?.content === "string") {
|
|
285
|
+
return result.content;
|
|
286
|
+
}
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
catch (e) {
|
|
290
|
+
console.error(`[ReverseControl] createMessage failed:`, e.message);
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Parse the LLM's sampling response into a structured decision.
|
|
296
|
+
*/
|
|
297
|
+
function parseSamplingResponse(eventType, response) {
|
|
298
|
+
try {
|
|
299
|
+
// Try to extract JSON from the response (LLM may wrap it in markdown)
|
|
300
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
301
|
+
if (!jsonMatch)
|
|
302
|
+
return null;
|
|
303
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
304
|
+
const action = parsed.action;
|
|
305
|
+
if (!action)
|
|
306
|
+
return null;
|
|
307
|
+
switch (action) {
|
|
308
|
+
case "bid":
|
|
309
|
+
return {
|
|
310
|
+
action: "bid",
|
|
311
|
+
params: {
|
|
312
|
+
confidence: Math.min(1.0, Math.max(0.0, Number(parsed.confidence) || 0.7)),
|
|
313
|
+
price: Number(parsed.price) || 0,
|
|
314
|
+
},
|
|
315
|
+
};
|
|
316
|
+
case "reply":
|
|
317
|
+
return {
|
|
318
|
+
action: "reply",
|
|
319
|
+
params: { message: String(parsed.message ?? "") },
|
|
320
|
+
};
|
|
321
|
+
case "confirm":
|
|
322
|
+
return { action: "confirm", params: {} };
|
|
323
|
+
case "decline":
|
|
324
|
+
return { action: "decline", params: { reason: parsed.reason } };
|
|
325
|
+
case "ignore":
|
|
326
|
+
return { action: "ignore", params: { reason: parsed.reason } };
|
|
327
|
+
case "custom":
|
|
328
|
+
return {
|
|
329
|
+
action: "custom",
|
|
330
|
+
params: { tool: parsed.tool, params: parsed.params ?? {} },
|
|
331
|
+
};
|
|
332
|
+
default:
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
catch {
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Execute a decision made by the LLM via sampling.
|
|
342
|
+
*/
|
|
343
|
+
async function executeDecision(agentId, event, decision) {
|
|
344
|
+
const taskId = event.task_id;
|
|
345
|
+
const payload = event.payload;
|
|
346
|
+
try {
|
|
347
|
+
switch (decision.action) {
|
|
348
|
+
case "bid": {
|
|
349
|
+
const { confidence, price } = decision.params;
|
|
350
|
+
await net.submitBid(taskId, agentId, confidence, price);
|
|
351
|
+
state.updateTask({
|
|
352
|
+
task_id: taskId,
|
|
353
|
+
agent_id: agentId,
|
|
354
|
+
role: "executor",
|
|
355
|
+
status: "bidding",
|
|
356
|
+
domains: payload.domains ?? [],
|
|
357
|
+
description_summary: String(payload.description ?? "").slice(0, 100),
|
|
358
|
+
created_at: new Date().toISOString(),
|
|
359
|
+
});
|
|
360
|
+
console.error(`[ReverseControl] auto-bid: task=${taskId} confidence=${confidence} price=${price}`);
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
case "reply": {
|
|
364
|
+
const message = decision.params.message;
|
|
365
|
+
const to = payload.from ?? "";
|
|
366
|
+
if (to && message) {
|
|
367
|
+
const s = state.getState();
|
|
368
|
+
const sid = s.server_card?.server_id ?? "";
|
|
369
|
+
await net.relayMessage({
|
|
370
|
+
from: { network_id: "", server_id: sid, agent_id: agentId },
|
|
371
|
+
to: { network_id: "", server_id: "", agent_id: to },
|
|
372
|
+
content: message,
|
|
373
|
+
});
|
|
374
|
+
state.addMessage(agentId, {
|
|
375
|
+
from: agentId,
|
|
376
|
+
to,
|
|
377
|
+
content: message,
|
|
378
|
+
timestamp: Date.now(),
|
|
379
|
+
direction: "out",
|
|
380
|
+
});
|
|
381
|
+
console.error(`[ReverseControl] auto-reply: to=${to} task=${taskId}`);
|
|
382
|
+
}
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
case "confirm": {
|
|
386
|
+
await net.confirmBudget(taskId, agentId, true);
|
|
387
|
+
console.error(`[ReverseControl] auto-confirm budget: task=${taskId}`);
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
case "decline": {
|
|
391
|
+
await net.confirmBudget(taskId, agentId, false);
|
|
392
|
+
console.error(`[ReverseControl] auto-decline budget: task=${taskId}`);
|
|
393
|
+
break;
|
|
394
|
+
}
|
|
395
|
+
case "custom": {
|
|
396
|
+
// Custom actions are logged but not auto-executed for safety.
|
|
397
|
+
// They're pushed as enhanced events for the agent to pick up.
|
|
398
|
+
state.pushEvents(agentId, [{
|
|
399
|
+
...event,
|
|
400
|
+
payload: { ...payload, _rc_decision: decision.params },
|
|
401
|
+
received_at: Date.now(),
|
|
402
|
+
}]);
|
|
403
|
+
console.error(`[ReverseControl] custom decision buffered: tool=${decision.params.tool}`);
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
case "ignore":
|
|
407
|
+
console.error(`[ReverseControl] ignored: ${event.type} task=${taskId} reason=${decision.params.reason}`);
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
catch (e) {
|
|
412
|
+
console.error(`[ReverseControl] action execution failed:`, e.message);
|
|
413
|
+
// On failure, ensure the event is still buffered so agent can handle manually
|
|
414
|
+
state.pushEvents(agentId, [event]);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
// ---------------------------------------------------------------------------
|
|
418
|
+
// Notifications
|
|
419
|
+
// ---------------------------------------------------------------------------
|
|
420
|
+
function handleViaNotification(agentId, event) {
|
|
421
|
+
if (!mcpServer)
|
|
422
|
+
return false;
|
|
423
|
+
try {
|
|
424
|
+
markProcessed(event.msg_id);
|
|
425
|
+
// Send a custom notification to the client
|
|
426
|
+
mcpServer.notification({
|
|
427
|
+
method: "notifications/message",
|
|
428
|
+
params: {
|
|
429
|
+
level: event.type === "task_timeout" ? "warning" : "info",
|
|
430
|
+
logger: "eacn3-reverse-control",
|
|
431
|
+
data: {
|
|
432
|
+
type: event.type,
|
|
433
|
+
task_id: event.task_id,
|
|
434
|
+
summary: buildNotificationSummary(event),
|
|
435
|
+
payload: event.payload,
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
});
|
|
439
|
+
console.error(`[ReverseControl] notification sent: ${event.type} task=${event.task_id}`);
|
|
440
|
+
return false; // still buffer — notification is supplementary
|
|
441
|
+
}
|
|
442
|
+
catch (e) {
|
|
443
|
+
console.error(`[ReverseControl] notification failed:`, e.message);
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
function buildNotificationSummary(event) {
|
|
448
|
+
const payload = event.payload;
|
|
449
|
+
switch (event.type) {
|
|
450
|
+
case "task_collected":
|
|
451
|
+
return `Task ${event.task_id} has results ready for retrieval.`;
|
|
452
|
+
case "task_timeout":
|
|
453
|
+
return `Task ${event.task_id} has timed out.`;
|
|
454
|
+
case "bid_result": {
|
|
455
|
+
const p = event.payload;
|
|
456
|
+
return p.accepted
|
|
457
|
+
? `Your bid on task ${event.task_id} was accepted.`
|
|
458
|
+
: `Your bid on task ${event.task_id} was rejected: ${p.reason ?? "no reason given"}.`;
|
|
459
|
+
}
|
|
460
|
+
default:
|
|
461
|
+
return `Event ${event.type} on task ${event.task_id}.`;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
// ---------------------------------------------------------------------------
|
|
465
|
+
// Auto-Actions
|
|
466
|
+
// ---------------------------------------------------------------------------
|
|
467
|
+
async function handleViaAutoAction(agentId, event, action) {
|
|
468
|
+
markProcessed(event.msg_id);
|
|
469
|
+
switch (action) {
|
|
470
|
+
case "report_and_close":
|
|
471
|
+
// Auto-report timeout and update local state
|
|
472
|
+
state.updateTaskStatus(event.task_id, "no_one");
|
|
473
|
+
try {
|
|
474
|
+
await net.reportEvent(agentId, "task_timeout");
|
|
475
|
+
}
|
|
476
|
+
catch { /* non-critical */ }
|
|
477
|
+
console.error(`[ReverseControl] auto-action: reported timeout for task=${event.task_id}`);
|
|
478
|
+
return true;
|
|
479
|
+
default:
|
|
480
|
+
return false;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
// ---------------------------------------------------------------------------
|
|
484
|
+
// Enhanced Tool Result Injection (Fallback)
|
|
485
|
+
// ---------------------------------------------------------------------------
|
|
486
|
+
/**
|
|
487
|
+
* Queue a directive for injection into the next tool response.
|
|
488
|
+
* Used when sampling is unavailable but the event needs agent attention.
|
|
489
|
+
*/
|
|
490
|
+
function queueDirective(agentId, event) {
|
|
491
|
+
const directive = buildDirectiveText(agentId, event);
|
|
492
|
+
if (directive) {
|
|
493
|
+
pendingDirectives.push({
|
|
494
|
+
agentId,
|
|
495
|
+
event,
|
|
496
|
+
directive,
|
|
497
|
+
createdAt: Date.now(),
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
function buildDirectiveText(agentId, event) {
|
|
502
|
+
const payload = event.payload;
|
|
503
|
+
switch (event.type) {
|
|
504
|
+
case "task_broadcast":
|
|
505
|
+
return `[ACTION NEEDED] New task ${event.task_id} in domain [${(payload.domains ?? []).join(", ")}] (budget: ${payload.budget ?? "?"}). Consider calling eacn3_submit_bid.`;
|
|
506
|
+
case "direct_message":
|
|
507
|
+
return `[ACTION NEEDED] Message from ${payload.from ?? "unknown"}: "${String(payload.content ?? "").slice(0, 200)}". Consider calling eacn3_send_message to reply.`;
|
|
508
|
+
case "subtask_completed":
|
|
509
|
+
return `[ACTION NEEDED] Subtask ${payload.subtask_id ?? "?"} completed for task ${event.task_id}. Results available. Consider calling eacn3_get_task_results.`;
|
|
510
|
+
case "bid_request_confirmation":
|
|
511
|
+
return `[ACTION NEEDED] Budget exceeded on task ${event.task_id}. Bid price: ${payload.price ?? "?"}. Call eacn3_confirm_budget to approve/reject.`;
|
|
512
|
+
case "discussion_update":
|
|
513
|
+
return `[ACTION NEEDED] New discussion on task ${event.task_id}. Check eacn3_get_task and respond.`;
|
|
514
|
+
default:
|
|
515
|
+
return null;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Drain pending directives for a given agent (or all agents).
|
|
520
|
+
* Called by tool result wrapper to inject into responses.
|
|
521
|
+
*
|
|
522
|
+
* Returns formatted text to append to tool results, or null if none.
|
|
523
|
+
*/
|
|
524
|
+
export function drainDirectives(agentId) {
|
|
525
|
+
// Clean expired directives (older than 5 minutes)
|
|
526
|
+
const now = Date.now();
|
|
527
|
+
const cutoff = now - PROCESSED_EVENT_TTL_MS;
|
|
528
|
+
while (pendingDirectives.length > 0 && pendingDirectives[0].createdAt < cutoff) {
|
|
529
|
+
pendingDirectives.shift();
|
|
530
|
+
}
|
|
531
|
+
// Find directives for this agent
|
|
532
|
+
const matching = [];
|
|
533
|
+
const remaining = [];
|
|
534
|
+
for (const d of pendingDirectives) {
|
|
535
|
+
if (!agentId || d.agentId === agentId) {
|
|
536
|
+
matching.push(d);
|
|
537
|
+
}
|
|
538
|
+
else {
|
|
539
|
+
remaining.push(d);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
if (matching.length === 0)
|
|
543
|
+
return null;
|
|
544
|
+
// Remove matched directives
|
|
545
|
+
pendingDirectives.length = 0;
|
|
546
|
+
pendingDirectives.push(...remaining);
|
|
547
|
+
const lines = matching.map((d, i) => `${i + 1}. ${d.directive}`);
|
|
548
|
+
return `\n\n---\n[EACN3 PENDING EVENTS] ${matching.length} event(s) require your attention:\n${lines.join("\n")}`;
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Check if there are any pending directives (for deciding whether to inject).
|
|
552
|
+
*/
|
|
553
|
+
export function hasPendingDirectives(agentId) {
|
|
554
|
+
if (!agentId)
|
|
555
|
+
return pendingDirectives.length > 0;
|
|
556
|
+
return pendingDirectives.some((d) => d.agentId === agentId);
|
|
557
|
+
}
|
|
558
|
+
// ---------------------------------------------------------------------------
|
|
559
|
+
// Rate Limiting & Dedup
|
|
560
|
+
// ---------------------------------------------------------------------------
|
|
561
|
+
function checkRateLimit() {
|
|
562
|
+
const now = Date.now();
|
|
563
|
+
// Remove timestamps outside the window
|
|
564
|
+
while (samplingTimestamps.length > 0 && samplingTimestamps[0] < now - RATE_WINDOW_MS) {
|
|
565
|
+
samplingTimestamps.shift();
|
|
566
|
+
}
|
|
567
|
+
return samplingTimestamps.length < MAX_SAMPLING_PER_MINUTE;
|
|
568
|
+
}
|
|
569
|
+
function recordSamplingCall() {
|
|
570
|
+
samplingTimestamps.push(Date.now());
|
|
571
|
+
}
|
|
572
|
+
function isAlreadyProcessed(msgId) {
|
|
573
|
+
// Clean old entries
|
|
574
|
+
const cutoff = Date.now() - PROCESSED_EVENT_TTL_MS;
|
|
575
|
+
while (processedEvents.length > 0 && processedEvents[0].processedAt < cutoff) {
|
|
576
|
+
processedEvents.shift();
|
|
577
|
+
}
|
|
578
|
+
return processedEvents.some((e) => e.msgId === msgId);
|
|
579
|
+
}
|
|
580
|
+
function markProcessed(msgId) {
|
|
581
|
+
if (msgId) {
|
|
582
|
+
processedEvents.push({ msgId, processedAt: Date.now() });
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
// ---------------------------------------------------------------------------
|
|
586
|
+
// Utility
|
|
587
|
+
// ---------------------------------------------------------------------------
|
|
588
|
+
function timeout(ms) {
|
|
589
|
+
return new Promise((resolve) => setTimeout(() => resolve(null), ms));
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Get current reverse control status for debugging.
|
|
593
|
+
*/
|
|
594
|
+
export function getStatus() {
|
|
595
|
+
return {
|
|
596
|
+
samplingAvailable,
|
|
597
|
+
configuredAgents: Object.keys(configs),
|
|
598
|
+
pendingDirectiveCount: pendingDirectives.length,
|
|
599
|
+
samplingCallsInWindow: samplingTimestamps.length,
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Force re-detection of client capabilities.
|
|
604
|
+
* Useful after reconnection or capability negotiation.
|
|
605
|
+
*/
|
|
606
|
+
export function refreshCapabilities() {
|
|
607
|
+
detectCapabilities();
|
|
608
|
+
}
|
|
609
|
+
//# sourceMappingURL=reverse-control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reverse-control.js","sourceRoot":"","sources":["../../src/reverse-control.ts"],"names":[],"mappings":"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"}
|