eacn3 0.1.4 → 0.3.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.d.ts +2 -2
- package/dist/index.js +162 -106
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +117 -76
- package/dist/server.js.map +1 -1
- package/dist/src/models.d.ts +212 -3
- package/dist/src/models.js +4 -4
- package/dist/src/models.js.map +1 -1
- package/dist/src/network-client.d.ts +18 -2
- package/dist/src/network-client.js +74 -2
- package/dist/src/network-client.js.map +1 -1
- package/dist/src/state.d.ts +1 -1
- package/dist/src/state.js +4 -4
- package/dist/src/state.js.map +1 -1
- package/dist/src/ws-manager.d.ts +1 -1
- package/dist/src/ws-manager.js +1 -1
- package/openclaw.plugin.json +4 -4
- package/package.json +3 -5
- package/scripts/cli.cjs +105 -19
- package/scripts/postinstall.cjs +4 -4
- package/skills/{eacn-adjudicate → eacn3-adjudicate}/SKILL.md +11 -11
- package/skills/{eacn-bid → eacn3-bid}/SKILL.md +13 -13
- package/skills/{eacn-bounty → eacn3-bounty}/SKILL.md +19 -19
- package/skills/{eacn-browse → eacn3-browse}/SKILL.md +14 -14
- package/skills/{eacn-budget → eacn3-budget}/SKILL.md +13 -13
- package/skills/{eacn-clarify → eacn3-clarify}/SKILL.md +7 -7
- package/skills/{eacn-collect → eacn3-collect}/SKILL.md +5 -5
- package/skills/{eacn-dashboard → eacn3-dashboard}/SKILL.md +21 -21
- package/skills/{eacn-delegate → eacn3-delegate}/SKILL.md +20 -20
- package/skills/{eacn-execute → eacn3-execute}/SKILL.md +16 -16
- package/skills/eacn3-join/SKILL.md +54 -0
- package/skills/{eacn-leave → eacn3-leave}/SKILL.md +8 -8
- package/skills/{eacn-register → eacn3-register}/SKILL.md +21 -21
- package/skills/{eacn-task → eacn3-task}/SKILL.md +19 -19
- package/skills/eacn-join/SKILL.md +0 -54
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* EACN3 — Native OpenClaw plugin entry point.
|
|
3
3
|
*
|
|
4
|
-
* Registers the same
|
|
4
|
+
* Registers the same 34 tools as server.ts but via api.registerTool().
|
|
5
5
|
* All logic delegates to the same src/ modules.
|
|
6
6
|
*/
|
|
7
7
|
export default function (api: any): void;
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* EACN3 — Native OpenClaw plugin entry point.
|
|
3
3
|
*
|
|
4
|
-
* Registers the same
|
|
4
|
+
* Registers the same 34 tools as server.ts but via api.registerTool().
|
|
5
5
|
* All logic delegates to the same src/ modules.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { EACN3_DEFAULT_NETWORK_ENDPOINT } from "./src/models.js";
|
|
8
8
|
import * as state from "./src/state.js";
|
|
9
9
|
import * as net from "./src/network-client.js";
|
|
10
10
|
import * as ws from "./src/ws-manager.js";
|
|
@@ -48,7 +48,7 @@ function resolveAgentId(provided) {
|
|
|
48
48
|
if (agents.length === 1)
|
|
49
49
|
return agents[0].agent_id;
|
|
50
50
|
if (agents.length === 0)
|
|
51
|
-
throw new Error("No agents registered. Call
|
|
51
|
+
throw new Error("No agents registered. Call eacn3_register_agent first.");
|
|
52
52
|
throw new Error(`Multiple agents registered (${agents.map(a => a.agent_id).join(", ")}). Specify agent_id explicitly.`);
|
|
53
53
|
}
|
|
54
54
|
// ---------------------------------------------------------------------------
|
|
@@ -119,35 +119,91 @@ export default function (api) {
|
|
|
119
119
|
state.load();
|
|
120
120
|
registerEventCallbacks();
|
|
121
121
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
122
|
+
// Health / Cluster (2)
|
|
123
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
124
|
+
// #0a eacn3_health
|
|
125
|
+
api.registerTool({
|
|
126
|
+
name: "eacn3_health",
|
|
127
|
+
description: "Check if a network node is alive and responding. No prerequisites — works before eacn3_connect. Returns {status: 'ok'} on success. Use this to verify an endpoint before connecting.",
|
|
128
|
+
parameters: {
|
|
129
|
+
type: "object",
|
|
130
|
+
properties: {
|
|
131
|
+
endpoint: { type: "string", description: "Node URL to probe. Defaults to configured network endpoint." },
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
async execute(_id, params) {
|
|
135
|
+
const target = params.endpoint ?? state.getState().network_endpoint;
|
|
136
|
+
try {
|
|
137
|
+
const health = await net.checkHealth(target);
|
|
138
|
+
return ok({ endpoint: target, ...health });
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
return err(`Health check failed for ${target}: ${e.message}`);
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
// #0b eacn3_cluster_status
|
|
146
|
+
api.registerTool({
|
|
147
|
+
name: "eacn3_cluster_status",
|
|
148
|
+
description: "Retrieve the full cluster topology including all member nodes, their online/offline status, and seed URLs. No prerequisites — works before eacn3_connect. Returns array of node objects with status and endpoint fields. Useful for diagnostics and finding alternative endpoints if primary is down.",
|
|
149
|
+
parameters: {
|
|
150
|
+
type: "object",
|
|
151
|
+
properties: {
|
|
152
|
+
endpoint: { type: "string", description: "Node URL to query. Defaults to configured network endpoint." },
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
async execute(_id, params) {
|
|
156
|
+
const target = params.endpoint ?? state.getState().network_endpoint;
|
|
157
|
+
try {
|
|
158
|
+
const cluster = await net.getClusterStatus(target);
|
|
159
|
+
return ok(cluster);
|
|
160
|
+
}
|
|
161
|
+
catch (e) {
|
|
162
|
+
return err(`Cluster status failed for ${target}: ${e.message}`);
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
122
167
|
// Server Management (4)
|
|
123
168
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
124
|
-
// #1
|
|
169
|
+
// #1 eacn3_connect
|
|
125
170
|
api.registerTool({
|
|
126
|
-
name: "
|
|
127
|
-
description: "Connect to
|
|
171
|
+
name: "eacn3_connect",
|
|
172
|
+
description: "Connect to the EACN3 network — this must be your FIRST call. Health-probes the endpoint, falls back to seed nodes if unreachable, registers a server, and starts a background heartbeat every 60s. Returns {server_id, network_endpoint, fallback, agents_online}. Side effects: opens WebSocket connections for any previously registered agents. Call eacn3_register_agent next.",
|
|
128
173
|
parameters: {
|
|
129
174
|
type: "object",
|
|
130
175
|
properties: {
|
|
131
|
-
network_endpoint: { type: "string", description: `Network URL. Defaults to ${
|
|
176
|
+
network_endpoint: { type: "string", description: `Network URL. Defaults to ${EACN3_DEFAULT_NETWORK_ENDPOINT}` },
|
|
177
|
+
seed_nodes: { type: "array", items: { type: "string" }, description: "Additional seed node URLs for fallback" },
|
|
132
178
|
},
|
|
133
179
|
},
|
|
134
180
|
async execute(_id, params) {
|
|
135
|
-
const
|
|
181
|
+
const preferred = params.network_endpoint ?? EACN3_DEFAULT_NETWORK_ENDPOINT;
|
|
136
182
|
const s = state.getState();
|
|
183
|
+
// Health probe + fallback
|
|
184
|
+
let endpoint;
|
|
185
|
+
let fallback = false;
|
|
186
|
+
try {
|
|
187
|
+
endpoint = await net.findHealthyEndpoint(preferred, params.seed_nodes);
|
|
188
|
+
fallback = endpoint !== preferred;
|
|
189
|
+
}
|
|
190
|
+
catch (e) {
|
|
191
|
+
return err(`Cannot reach any network node: ${e.message}`);
|
|
192
|
+
}
|
|
137
193
|
s.network_endpoint = endpoint;
|
|
138
|
-
const res = await net.registerServer("0.
|
|
139
|
-
s.server_card = { server_id: res.server_id, version: "0.
|
|
194
|
+
const res = await net.registerServer("0.3.0", "plugin://local", "plugin-user");
|
|
195
|
+
s.server_card = { server_id: res.server_id, version: "0.3.0", endpoint: "plugin://local", owner: "plugin-user", status: "online" };
|
|
140
196
|
state.save();
|
|
141
197
|
startHeartbeat();
|
|
142
198
|
for (const agentId of Object.keys(s.agents))
|
|
143
199
|
ws.connect(agentId);
|
|
144
|
-
return ok({ connected: true, server_id: res.server_id, network_endpoint: endpoint, agents_online: Object.keys(s.agents).length });
|
|
200
|
+
return ok({ connected: true, server_id: res.server_id, network_endpoint: endpoint, fallback, agents_online: Object.keys(s.agents).length });
|
|
145
201
|
},
|
|
146
202
|
});
|
|
147
|
-
// #2
|
|
203
|
+
// #2 eacn3_disconnect
|
|
148
204
|
api.registerTool({
|
|
149
|
-
name: "
|
|
150
|
-
description: "Disconnect from
|
|
205
|
+
name: "eacn3_disconnect",
|
|
206
|
+
description: "Disconnect from the EACN3 network, unregister the server, and close all WebSocket connections. Requires: eacn3_connect first. Side effects: clears all local agent state; active tasks will timeout and hurt reputation. Returns {disconnected: true}. Only call at end of session.",
|
|
151
207
|
parameters: { type: "object", properties: {} },
|
|
152
208
|
async execute() {
|
|
153
209
|
stopHeartbeat();
|
|
@@ -163,17 +219,17 @@ export default function (api) {
|
|
|
163
219
|
return ok({ disconnected: true });
|
|
164
220
|
},
|
|
165
221
|
});
|
|
166
|
-
// #3
|
|
222
|
+
// #3 eacn3_heartbeat
|
|
167
223
|
api.registerTool({
|
|
168
|
-
name: "
|
|
169
|
-
description: "
|
|
224
|
+
name: "eacn3_heartbeat",
|
|
225
|
+
description: "Manually send a heartbeat to the network to signal this server is still alive. Requires: eacn3_connect first. Usually unnecessary — a background interval auto-sends every 60s. Only use if you suspect the connection may have gone stale.",
|
|
170
226
|
parameters: { type: "object", properties: {} },
|
|
171
227
|
async execute() { return ok(await net.heartbeat()); },
|
|
172
228
|
});
|
|
173
|
-
// #4
|
|
229
|
+
// #4 eacn3_server_info
|
|
174
230
|
api.registerTool({
|
|
175
|
-
name: "
|
|
176
|
-
description: "Get current server
|
|
231
|
+
name: "eacn3_server_info",
|
|
232
|
+
description: "Get current server connection state, including server_card, network_endpoint, registered agent IDs, task count, and remote status. Requires: eacn3_connect first. Returns {server_card, network_endpoint, agents_count, agents[], tasks_count, remote_status}. No side effects — read-only diagnostic.",
|
|
177
233
|
parameters: { type: "object", properties: {} },
|
|
178
234
|
async execute() {
|
|
179
235
|
const s = state.getState();
|
|
@@ -192,10 +248,10 @@ export default function (api) {
|
|
|
192
248
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
193
249
|
// Agent Management (7)
|
|
194
250
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
195
|
-
// #5
|
|
251
|
+
// #5 eacn3_register_agent
|
|
196
252
|
api.registerTool({
|
|
197
|
-
name: "
|
|
198
|
-
description: "
|
|
253
|
+
name: "eacn3_register_agent",
|
|
254
|
+
description: "Create and register an agent identity on the EACN3 network. Requires: eacn3_connect first. Assembles an AgentCard, registers it with the network, persists it locally, and opens a WebSocket for real-time event push (task_broadcast, subtask_completed, etc.). Returns {agent_id, seeds, domains}. Domains control which task broadcasts you receive — be specific (e.g. 'python-coding' not 'coding').",
|
|
199
255
|
parameters: {
|
|
200
256
|
type: "object",
|
|
201
257
|
properties: {
|
|
@@ -212,7 +268,7 @@ export default function (api) {
|
|
|
212
268
|
async execute(_id, params) {
|
|
213
269
|
const s = state.getState();
|
|
214
270
|
if (!s.server_card)
|
|
215
|
-
return err("Not connected. Call
|
|
271
|
+
return err("Not connected. Call eacn3_connect first.");
|
|
216
272
|
if (!params.name?.trim())
|
|
217
273
|
return err("name cannot be empty");
|
|
218
274
|
if (!params.domains?.length)
|
|
@@ -230,10 +286,10 @@ export default function (api) {
|
|
|
230
286
|
return ok({ registered: true, agent_id: agentId, seeds: res.seeds, domains: params.domains });
|
|
231
287
|
},
|
|
232
288
|
});
|
|
233
|
-
// #6
|
|
289
|
+
// #6 eacn3_get_agent
|
|
234
290
|
api.registerTool({
|
|
235
|
-
name: "
|
|
236
|
-
description: "
|
|
291
|
+
name: "eacn3_get_agent",
|
|
292
|
+
description: "Fetch the full AgentCard for any agent by ID — checks local state first, then queries the network. Returns {agent_id, name, agent_type, domains, skills, capabilities, url, server_id, description}. No side effects. Use to inspect an agent before sending messages or evaluating bids.",
|
|
237
293
|
parameters: { type: "object", properties: { agent_id: { type: "string" } }, required: ["agent_id"] },
|
|
238
294
|
async execute(_id, params) {
|
|
239
295
|
const local = state.getAgent(params.agent_id);
|
|
@@ -242,10 +298,10 @@ export default function (api) {
|
|
|
242
298
|
return ok(await net.getAgentInfo(params.agent_id));
|
|
243
299
|
},
|
|
244
300
|
});
|
|
245
|
-
// #7
|
|
301
|
+
// #7 eacn3_update_agent
|
|
246
302
|
api.registerTool({
|
|
247
|
-
name: "
|
|
248
|
-
description: "Update
|
|
303
|
+
name: "eacn3_update_agent",
|
|
304
|
+
description: "Update a registered agent's mutable fields: name, domains, skills, and/or description. Requires: the agent must be registered (eacn3_register_agent). Updates both network and local state. Changing domains affects which task broadcasts you receive going forward.",
|
|
249
305
|
parameters: {
|
|
250
306
|
type: "object",
|
|
251
307
|
properties: {
|
|
@@ -274,10 +330,10 @@ export default function (api) {
|
|
|
274
330
|
return ok({ updated: true, agent_id, ...res });
|
|
275
331
|
},
|
|
276
332
|
});
|
|
277
|
-
// #8
|
|
333
|
+
// #8 eacn3_unregister_agent
|
|
278
334
|
api.registerTool({
|
|
279
|
-
name: "
|
|
280
|
-
description: "
|
|
335
|
+
name: "eacn3_unregister_agent",
|
|
336
|
+
description: "Remove an agent from the network and close its WebSocket connection. Side effects: deletes agent from local state, stops receiving events for this agent. Active tasks assigned to this agent will timeout and hurt reputation. Returns {unregistered: true, agent_id}.",
|
|
281
337
|
parameters: { type: "object", properties: { agent_id: { type: "string" } }, required: ["agent_id"] },
|
|
282
338
|
async execute(_id, params) {
|
|
283
339
|
const res = await net.unregisterAgent(params.agent_id);
|
|
@@ -286,29 +342,29 @@ export default function (api) {
|
|
|
286
342
|
return ok({ unregistered: true, agent_id: params.agent_id, ...res });
|
|
287
343
|
},
|
|
288
344
|
});
|
|
289
|
-
// #9
|
|
345
|
+
// #9 eacn3_list_my_agents
|
|
290
346
|
api.registerTool({
|
|
291
|
-
name: "
|
|
292
|
-
description: "List all
|
|
347
|
+
name: "eacn3_list_my_agents",
|
|
348
|
+
description: "List all agents registered on this local server instance. Returns {count, agents[]} where each agent includes agent_id, name, agent_type, domains, and ws_connected (WebSocket status). No network call — reads local state only. Use to check which agents are active and receiving events.",
|
|
293
349
|
parameters: { type: "object", properties: {} },
|
|
294
350
|
async execute() {
|
|
295
351
|
const agents = state.listAgents();
|
|
296
352
|
return ok({ count: agents.length, agents: agents.map((a) => ({ agent_id: a.agent_id, name: a.name, agent_type: a.agent_type, domains: a.domains, ws_connected: ws.isConnected(a.agent_id) })) });
|
|
297
353
|
},
|
|
298
354
|
});
|
|
299
|
-
// #10
|
|
355
|
+
// #10 eacn3_discover_agents
|
|
300
356
|
api.registerTool({
|
|
301
|
-
name: "
|
|
302
|
-
description: "
|
|
357
|
+
name: "eacn3_discover_agents",
|
|
358
|
+
description: "Search for agents matching a specific domain using the network's discovery protocol (Gossip, then DHT, then Bootstrap fallback). Requires: eacn3_connect first. Returns a list of matching AgentCards. Use before creating a task to verify executors exist for your domains.",
|
|
303
359
|
parameters: { type: "object", properties: { domain: { type: "string" }, requester_id: { type: "string" } }, required: ["domain"] },
|
|
304
360
|
async execute(_id, params) {
|
|
305
361
|
return ok(await net.discoverAgents(params.domain, params.requester_id));
|
|
306
362
|
},
|
|
307
363
|
});
|
|
308
|
-
// #11
|
|
364
|
+
// #11 eacn3_list_agents
|
|
309
365
|
api.registerTool({
|
|
310
|
-
name: "
|
|
311
|
-
description: "
|
|
366
|
+
name: "eacn3_list_agents",
|
|
367
|
+
description: "Browse and paginate all agents registered on the network with optional filters by domain or server_id. Returns {count, agents[]}. Default page size is 20. Unlike eacn3_discover_agents, this is a direct registry query without Gossip/DHT discovery — faster but only returns agents already indexed.",
|
|
312
368
|
parameters: {
|
|
313
369
|
type: "object",
|
|
314
370
|
properties: {
|
|
@@ -324,34 +380,34 @@ export default function (api) {
|
|
|
324
380
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
325
381
|
// Task Query (4)
|
|
326
382
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
327
|
-
// #12
|
|
383
|
+
// #12 eacn3_get_task
|
|
328
384
|
api.registerTool({
|
|
329
|
-
name: "
|
|
330
|
-
description: "
|
|
385
|
+
name: "eacn3_get_task",
|
|
386
|
+
description: "Fetch complete task details from the network including description, content, bids[], results[], status, budget, deadline, and domains. No side effects — read-only. Use to inspect a task before bidding or to review submitted results. Works for any task ID regardless of your role.",
|
|
331
387
|
parameters: { type: "object", properties: { task_id: { type: "string" } }, required: ["task_id"] },
|
|
332
388
|
async execute(_id, params) { return ok(await net.getTask(params.task_id)); },
|
|
333
389
|
});
|
|
334
|
-
// #13
|
|
390
|
+
// #13 eacn3_get_task_status
|
|
335
391
|
api.registerTool({
|
|
336
|
-
name: "
|
|
337
|
-
description: "
|
|
392
|
+
name: "eacn3_get_task_status",
|
|
393
|
+
description: "Lightweight task query returning only status and bid list — no result content. Intended for initiators monitoring their tasks. Requires: agent_id must be the task initiator (auto-injected if only one agent registered). Returns {status, bids[]}. Cheaper than eacn3_get_task when you only need status.",
|
|
338
394
|
parameters: { type: "object", properties: { task_id: { type: "string" }, agent_id: { type: "string", description: "Initiator agent ID (auto-injected if omitted)" } }, required: ["task_id"] },
|
|
339
395
|
async execute(_id, params) { const agentId = resolveAgentId(params.agent_id); return ok(await net.getTaskStatus(params.task_id, agentId)); },
|
|
340
396
|
});
|
|
341
|
-
// #14
|
|
397
|
+
// #14 eacn3_list_open_tasks
|
|
342
398
|
api.registerTool({
|
|
343
|
-
name: "
|
|
344
|
-
description: "
|
|
399
|
+
name: "eacn3_list_open_tasks",
|
|
400
|
+
description: "Browse tasks currently accepting bids (status: unclaimed or bidding). Returns {count, tasks[]} with pagination. Filter by comma-separated domains to find relevant work. Use this in your main loop to discover tasks to bid on after checking events.",
|
|
345
401
|
parameters: { type: "object", properties: { domains: { type: "string", description: "Comma-separated domain filter" }, limit: { type: "number" }, offset: { type: "number" } } },
|
|
346
402
|
async execute(_id, params) {
|
|
347
403
|
const tasks = await net.getOpenTasks(params);
|
|
348
404
|
return ok({ count: tasks.length, tasks });
|
|
349
405
|
},
|
|
350
406
|
});
|
|
351
|
-
// #15
|
|
407
|
+
// #15 eacn3_list_tasks
|
|
352
408
|
api.registerTool({
|
|
353
|
-
name: "
|
|
354
|
-
description: "
|
|
409
|
+
name: "eacn3_list_tasks",
|
|
410
|
+
description: "Browse all tasks on the network with optional filters by status (unclaimed, bidding, awaiting_retrieval, completed, no_one) and/or initiator_id. Returns {count, tasks[]} with pagination. Unlike eacn3_list_open_tasks, this includes tasks in all states.",
|
|
355
411
|
parameters: { type: "object", properties: { status: { type: "string" }, initiator_id: { type: "string" }, limit: { type: "number" }, offset: { type: "number" } } },
|
|
356
412
|
async execute(_id, params) {
|
|
357
413
|
const tasks = await net.listTasks(params);
|
|
@@ -361,10 +417,10 @@ export default function (api) {
|
|
|
361
417
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
362
418
|
// Task Operations — Initiator (7)
|
|
363
419
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
364
|
-
// #16
|
|
420
|
+
// #16 eacn3_create_task
|
|
365
421
|
api.registerTool({
|
|
366
|
-
name: "
|
|
367
|
-
description: "
|
|
422
|
+
name: "eacn3_create_task",
|
|
423
|
+
description: "Publish a new task to the EACN3 network for other agents to bid on. Side effects: freezes 'budget' credits from your available balance into escrow; broadcasts task to agents with matching domains. Returns {task_id, status, budget, local_matches[]}. Requires: sufficient balance (use eacn3_deposit first if needed). Task starts in 'unclaimed' status, transitions to 'bidding' when first bid arrives.",
|
|
368
424
|
parameters: {
|
|
369
425
|
type: "object",
|
|
370
426
|
properties: {
|
|
@@ -413,55 +469,55 @@ export default function (api) {
|
|
|
413
469
|
return ok({ task_id: taskId, status: task.status, budget: params.budget, local_matches: matchedLocal.map((a) => a.agent_id) });
|
|
414
470
|
},
|
|
415
471
|
});
|
|
416
|
-
// #17
|
|
472
|
+
// #17 eacn3_get_task_results
|
|
417
473
|
api.registerTool({
|
|
418
|
-
name: "
|
|
419
|
-
description: "Retrieve
|
|
474
|
+
name: "eacn3_get_task_results",
|
|
475
|
+
description: "Retrieve submitted results and adjudications for a task you initiated. IMPORTANT side effect: the first call transitions the task from 'awaiting_retrieval' to 'completed' permanently. Returns {results[], adjudications[]}. After reviewing results, call eacn3_select_result to pick a winner and trigger payment.",
|
|
420
476
|
parameters: { type: "object", properties: { task_id: { type: "string" }, initiator_id: { type: "string", description: "Initiator agent ID (auto-injected if omitted)" } }, required: ["task_id"] },
|
|
421
477
|
async execute(_id, params) { const initiatorId = resolveAgentId(params.initiator_id); return ok(await net.getTaskResults(params.task_id, initiatorId)); },
|
|
422
478
|
});
|
|
423
|
-
// #18
|
|
479
|
+
// #18 eacn3_select_result
|
|
424
480
|
api.registerTool({
|
|
425
|
-
name: "
|
|
426
|
-
description: "
|
|
481
|
+
name: "eacn3_select_result",
|
|
482
|
+
description: "Pick the winning result for a task, triggering credit transfer from escrow to the selected executor agent. Requires: call eacn3_get_task_results first to review results. Side effects: transfers escrowed credits to the winning agent's balance, finalizes the task. The agent_id param is the executor whose result you select, not your own ID.",
|
|
427
483
|
parameters: { type: "object", properties: { task_id: { type: "string" }, agent_id: { type: "string", description: "ID of the agent whose result to select" }, initiator_id: { type: "string", description: "Initiator agent ID (auto-injected if omitted)" } }, required: ["task_id", "agent_id"] },
|
|
428
484
|
async execute(_id, params) { const initiatorId = resolveAgentId(params.initiator_id); return ok(await net.selectResult(params.task_id, initiatorId, params.agent_id)); },
|
|
429
485
|
});
|
|
430
|
-
// #19
|
|
486
|
+
// #19 eacn3_close_task
|
|
431
487
|
api.registerTool({
|
|
432
|
-
name: "
|
|
433
|
-
description: "
|
|
488
|
+
name: "eacn3_close_task",
|
|
489
|
+
description: "Stop accepting bids and results for a task you initiated, moving it to closed status. Requires: you must be the task initiator. Side effects: no new bids or results will be accepted; escrowed credits are returned if no result was selected. Returns confirmation with updated task status.",
|
|
434
490
|
parameters: { type: "object", properties: { task_id: { type: "string" }, initiator_id: { type: "string", description: "Initiator agent ID (auto-injected if omitted)" } }, required: ["task_id"] },
|
|
435
491
|
async execute(_id, params) { const initiatorId = resolveAgentId(params.initiator_id); return ok(await net.closeTask(params.task_id, initiatorId)); },
|
|
436
492
|
});
|
|
437
|
-
// #20
|
|
493
|
+
// #20 eacn3_update_deadline
|
|
438
494
|
api.registerTool({
|
|
439
|
-
name: "
|
|
440
|
-
description: "
|
|
495
|
+
name: "eacn3_update_deadline",
|
|
496
|
+
description: "Extend or shorten a task's deadline. Requires: you must be the task initiator; new_deadline must be an ISO 8601 timestamp in the future. Returns confirmation with updated deadline. Use to give executors more time or to accelerate a slow task.",
|
|
441
497
|
parameters: { type: "object", properties: { task_id: { type: "string" }, new_deadline: { type: "string", description: "New ISO 8601 deadline" }, initiator_id: { type: "string", description: "Initiator agent ID (auto-injected if omitted)" } }, required: ["task_id", "new_deadline"] },
|
|
442
498
|
async execute(_id, params) { const initiatorId = resolveAgentId(params.initiator_id); return ok(await net.updateDeadline(params.task_id, initiatorId, params.new_deadline)); },
|
|
443
499
|
});
|
|
444
|
-
// #21
|
|
500
|
+
// #21 eacn3_update_discussions
|
|
445
501
|
api.registerTool({
|
|
446
|
-
name: "
|
|
447
|
-
description: "
|
|
502
|
+
name: "eacn3_update_discussions",
|
|
503
|
+
description: "Post a clarification or discussion message on a task visible to all bidders. Requires: you must be the task initiator. Side effects: triggers a 'discussions_updated' WebSocket event to all bidding agents. Returns confirmation. Use to provide additional context or answer bidder questions.",
|
|
448
504
|
parameters: { type: "object", properties: { task_id: { type: "string" }, message: { type: "string" }, initiator_id: { type: "string", description: "Initiator agent ID (auto-injected if omitted)" } }, required: ["task_id", "message"] },
|
|
449
505
|
async execute(_id, params) { const initiatorId = resolveAgentId(params.initiator_id); return ok(await net.updateDiscussions(params.task_id, initiatorId, params.message)); },
|
|
450
506
|
});
|
|
451
|
-
// #22
|
|
507
|
+
// #22 eacn3_confirm_budget
|
|
452
508
|
api.registerTool({
|
|
453
|
-
name: "
|
|
454
|
-
description: "
|
|
509
|
+
name: "eacn3_confirm_budget",
|
|
510
|
+
description: "Approve or reject a bid that exceeded your task's budget, triggered by a 'budget_confirmation' event. Set approved=true to accept (optionally raising the budget with new_budget); approved=false to reject the bid. Side effects: if approved, additional credits are frozen from your balance; the bid transitions from 'pending_confirmation' to 'accepted'. Returns updated task status.",
|
|
455
511
|
parameters: { type: "object", properties: { task_id: { type: "string" }, approved: { type: "boolean" }, new_budget: { type: "number" }, initiator_id: { type: "string", description: "Initiator agent ID (auto-injected if omitted)" } }, required: ["task_id", "approved"] },
|
|
456
512
|
async execute(_id, params) { const initiatorId = resolveAgentId(params.initiator_id); return ok(await net.confirmBudget(params.task_id, initiatorId, params.approved, params.new_budget)); },
|
|
457
513
|
});
|
|
458
514
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
459
515
|
// Task Operations — Executor (5)
|
|
460
516
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
461
|
-
// #23
|
|
517
|
+
// #23 eacn3_submit_bid
|
|
462
518
|
api.registerTool({
|
|
463
|
-
name: "
|
|
464
|
-
description: "
|
|
519
|
+
name: "eacn3_submit_bid",
|
|
520
|
+
description: "Bid on an open task by specifying your confidence (0.0-1.0 honest ability estimate) and price in credits. Server evaluates: confidence * reputation must meet threshold or bid is rejected. Returns {status} which is one of: 'executing' (start work now), 'waiting_execution' (queued, slots full), 'rejected' (threshold not met), or 'pending_confirmation' (price > budget, awaiting initiator approval). Side effects: if accepted, tracks task locally as executor role. If price > budget, initiator gets a 'budget_confirmation' event.",
|
|
465
521
|
parameters: { type: "object", properties: { task_id: { type: "string" }, confidence: { type: "number", description: "0.0-1.0 confidence in ability to complete" }, price: { type: "number", description: "Bid price" }, agent_id: { type: "string", description: "Bidder agent ID (auto-injected if omitted)" } }, required: ["task_id", "confidence", "price"] },
|
|
466
522
|
async execute(_id, params) {
|
|
467
523
|
const agentId = resolveAgentId(params.agent_id);
|
|
@@ -472,10 +528,10 @@ export default function (api) {
|
|
|
472
528
|
return ok(res);
|
|
473
529
|
},
|
|
474
530
|
});
|
|
475
|
-
// #24
|
|
531
|
+
// #24 eacn3_submit_result
|
|
476
532
|
api.registerTool({
|
|
477
|
-
name: "
|
|
478
|
-
description: "Submit
|
|
533
|
+
name: "eacn3_submit_result",
|
|
534
|
+
description: "Submit your completed work for a task you are executing. Content should be a JSON object matching the task's expected_output format if specified. Side effects: automatically reports a 'task_completed' reputation event (increases your score); transitions task to 'awaiting_retrieval' so the initiator can review. Returns confirmation with submission status.",
|
|
479
535
|
parameters: { type: "object", properties: { task_id: { type: "string" }, content: { type: "object", description: "Result content object" }, agent_id: { type: "string", description: "Executor agent ID (auto-injected if omitted)" } }, required: ["task_id", "content"] },
|
|
480
536
|
async execute(_id, params) {
|
|
481
537
|
const agentId = resolveAgentId(params.agent_id);
|
|
@@ -487,10 +543,10 @@ export default function (api) {
|
|
|
487
543
|
return ok(res);
|
|
488
544
|
},
|
|
489
545
|
});
|
|
490
|
-
// #25
|
|
546
|
+
// #25 eacn3_reject_task
|
|
491
547
|
api.registerTool({
|
|
492
|
-
name: "
|
|
493
|
-
description: "
|
|
548
|
+
name: "eacn3_reject_task",
|
|
549
|
+
description: "Abandon a task you accepted, freeing your execution slot for another agent. WARNING: automatically reports a 'task_rejected' reputation event which decreases your score. Only use when you genuinely cannot complete the task. Returns confirmation. Provide a reason string to explain why.",
|
|
494
550
|
parameters: { type: "object", properties: { task_id: { type: "string" }, reason: { type: "string" }, agent_id: { type: "string", description: "Executor agent ID (auto-injected if omitted)" } }, required: ["task_id"] },
|
|
495
551
|
async execute(_id, params) {
|
|
496
552
|
const agentId = resolveAgentId(params.agent_id);
|
|
@@ -502,10 +558,10 @@ export default function (api) {
|
|
|
502
558
|
return ok(res);
|
|
503
559
|
},
|
|
504
560
|
});
|
|
505
|
-
// #26
|
|
561
|
+
// #26 eacn3_create_subtask
|
|
506
562
|
api.registerTool({
|
|
507
|
-
name: "
|
|
508
|
-
description: "
|
|
563
|
+
name: "eacn3_create_subtask",
|
|
564
|
+
description: "Delegate part of your work by creating a child task under a parent task you are executing. Budget is carved from the parent task's escrow (not your balance). Returns {subtask_id, parent_task_id, status, depth}. Depth auto-increments (max 3 levels). Side effects: broadcasts subtask to agents with matching domains; when the subtask completes, you receive a 'subtask_completed' event with auto-fetched results in the payload.",
|
|
509
565
|
parameters: {
|
|
510
566
|
type: "object",
|
|
511
567
|
properties: {
|
|
@@ -522,11 +578,11 @@ export default function (api) {
|
|
|
522
578
|
return ok({ subtask_id: task.id, parent_task_id: params.parent_task_id, status: task.status, depth: task.depth });
|
|
523
579
|
},
|
|
524
580
|
});
|
|
525
|
-
// #27
|
|
581
|
+
// #27 eacn3_send_message
|
|
526
582
|
// A2A direct — agent.md:358-362: 点对点,不经过 Network
|
|
527
583
|
api.registerTool({
|
|
528
|
-
name: "
|
|
529
|
-
description: "Send a direct message
|
|
584
|
+
name: "eacn3_send_message",
|
|
585
|
+
description: "Send a direct agent-to-agent message bypassing the task system. Local agents receive it instantly in their event buffer; remote agents receive it via HTTP POST to their /events endpoint. Returns {sent, to, from, local}. The recipient sees a 'direct_message' event with payload.from and payload.content. Will fail if the remote agent has no reachable URL or is offline.",
|
|
530
586
|
parameters: { type: "object", properties: { agent_id: { type: "string", description: "Target agent ID" }, content: { type: "string" }, sender_id: { type: "string", description: "Your agent ID (auto-injected if omitted)" } }, required: ["agent_id", "content"] },
|
|
531
587
|
async execute(_id, params) {
|
|
532
588
|
const senderId = resolveAgentId(params.sender_id);
|
|
@@ -578,10 +634,10 @@ export default function (api) {
|
|
|
578
634
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
579
635
|
// Reputation (2)
|
|
580
636
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
581
|
-
// #28
|
|
637
|
+
// #28 eacn3_report_event
|
|
582
638
|
api.registerTool({
|
|
583
|
-
name: "
|
|
584
|
-
description: "
|
|
639
|
+
name: "eacn3_report_event",
|
|
640
|
+
description: "Manually report a reputation event for an agent. Valid event_type values: 'task_completed' (score up), 'task_rejected' (score down), 'task_timeout' (score down), 'bid_declined' (score down). Usually auto-called by eacn3_submit_result and eacn3_reject_task — only call manually for edge cases. Returns {agent_id, score} with updated reputation. Side effects: updates local reputation cache.",
|
|
585
641
|
parameters: { type: "object", properties: { agent_id: { type: "string" }, event_type: { type: "string", description: "task_completed | task_rejected | task_timeout | bid_declined" } }, required: ["agent_id", "event_type"] },
|
|
586
642
|
async execute(_id, params) {
|
|
587
643
|
const res = await net.reportEvent(params.agent_id, params.event_type);
|
|
@@ -589,10 +645,10 @@ export default function (api) {
|
|
|
589
645
|
return ok(res);
|
|
590
646
|
},
|
|
591
647
|
});
|
|
592
|
-
// #29
|
|
648
|
+
// #29 eacn3_get_reputation
|
|
593
649
|
api.registerTool({
|
|
594
|
-
name: "
|
|
595
|
-
description: "Query an
|
|
650
|
+
name: "eacn3_get_reputation",
|
|
651
|
+
description: "Query an agent's global reputation score (0.0-1.0, starts at 0.5 for new agents). Returns {agent_id, score}. Score affects bid acceptance: confidence * reputation must meet the task's threshold. No side effects besides updating local reputation cache. Works for any agent ID, not just your own.",
|
|
596
652
|
parameters: { type: "object", properties: { agent_id: { type: "string" } }, required: ["agent_id"] },
|
|
597
653
|
async execute(_id, params) {
|
|
598
654
|
const res = await net.getReputation(params.agent_id);
|
|
@@ -603,19 +659,19 @@ export default function (api) {
|
|
|
603
659
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
604
660
|
// Economy (2)
|
|
605
661
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
606
|
-
// #30
|
|
662
|
+
// #30 eacn3_get_balance
|
|
607
663
|
api.registerTool({
|
|
608
|
-
name: "
|
|
609
|
-
description: "
|
|
664
|
+
name: "eacn3_get_balance",
|
|
665
|
+
description: "Check an agent's credit balance. Returns {agent_id, available, frozen} where 'available' is spendable credits and 'frozen' is credits locked in escrow for active tasks. No side effects. Check before creating tasks to ensure sufficient funds; use eacn3_deposit to add credits if needed.",
|
|
610
666
|
parameters: { type: "object", properties: { agent_id: { type: "string", description: "Agent ID to check balance for" } }, required: ["agent_id"] },
|
|
611
667
|
async execute(_id, params) {
|
|
612
668
|
return ok(await net.getBalance(params.agent_id));
|
|
613
669
|
},
|
|
614
670
|
});
|
|
615
|
-
// #31
|
|
671
|
+
// #31 eacn3_deposit
|
|
616
672
|
api.registerTool({
|
|
617
|
-
name: "
|
|
618
|
-
description: "
|
|
673
|
+
name: "eacn3_deposit",
|
|
674
|
+
description: "Add EACN credits to an agent's available balance. Amount must be > 0. Returns updated balance {agent_id, available, frozen}. Deposit before creating tasks if your balance is insufficient to cover the task budget.",
|
|
619
675
|
parameters: { type: "object", properties: { agent_id: { type: "string", description: "Agent ID to deposit funds for" }, amount: { type: "number", description: "Amount to deposit (must be > 0)" } }, required: ["agent_id", "amount"] },
|
|
620
676
|
async execute(_id, params) {
|
|
621
677
|
return ok(await net.deposit(params.agent_id, params.amount));
|
|
@@ -624,10 +680,10 @@ export default function (api) {
|
|
|
624
680
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
625
681
|
// Events (1)
|
|
626
682
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
627
|
-
// #32
|
|
683
|
+
// #32 eacn3_get_events
|
|
628
684
|
api.registerTool({
|
|
629
|
-
name: "
|
|
630
|
-
description: "
|
|
685
|
+
name: "eacn3_get_events",
|
|
686
|
+
description: "Drain the in-memory event buffer, returning all pending events and clearing them. Returns {count, events[]} where event types include: task_broadcast, discussions_updated, subtask_completed, awaiting_retrieval, budget_confirmation, timeout, direct_message. Call periodically in your main loop. Events arrive via WebSocket and accumulate until drained — missing events means missed tasks and messages.",
|
|
631
687
|
parameters: { type: "object", properties: {} },
|
|
632
688
|
async execute() {
|
|
633
689
|
const events = state.drainEvents();
|