akemon 0.2.23 → 0.2.25
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/engine-peripheral.js +118 -42
- package/dist/engine-queue.js +143 -0
- package/dist/engine-queue.test.js +99 -0
- package/dist/engine-routing.js +52 -0
- package/dist/engine-routing.test.js +122 -0
- package/dist/mcp-server.js +18 -23
- package/dist/memory-module.js +2 -0
- package/dist/metrics.js +30 -0
- package/dist/orphan-scan.js +79 -0
- package/dist/orphan-scan.test.js +81 -0
- package/dist/reflection-module.integration.test.js +180 -0
- package/dist/reflection-module.js +27 -29
- package/dist/reflection-module.test.js +66 -0
- package/dist/relay-client.js +17 -1
- package/dist/role-module.js +2 -2
- package/dist/role-module.test.js +208 -0
- package/dist/script-module.js +1 -0
- package/dist/server.js +68 -38
- package/dist/task-helpers.js +26 -0
- package/dist/task-helpers.test.js +88 -0
- package/dist/task-module.js +38 -25
- package/package.json +3 -2
package/dist/task-module.js
CHANGED
|
@@ -13,12 +13,14 @@ import { SIG, sig } from "./types.js";
|
|
|
13
13
|
import { selfDir, biosPath, localNow, loadBioState, saveBioState, syncEnergyFromTokens, loadAgentConfig, getDueUserTasks, loadTaskRuns, saveTaskRuns, loadDirectives, buildDirectivesPrompt, appendTaskHistory, notifyOwner, updateHungerDecay, updateNaturalDecay, resetTokenCountIfNewDay, computeSociability, appendBioEvent, bioStatePromptModifier, feedHunger, SHOP_ITEMS, logBioStatus, logBioDecision, } from "./self.js";
|
|
14
14
|
import { appendMessage } from "./context.js";
|
|
15
15
|
import { buildRoleContext } from "./role-module.js";
|
|
16
|
+
import { sortByQuadrant, dedupeWorkItems, computeRetryDelay } from "./task-helpers.js";
|
|
17
|
+
import { updateMetrics } from "./metrics.js";
|
|
18
|
+
import { downgradeForRetry } from "./engine-routing.js";
|
|
16
19
|
// ---------------------------------------------------------------------------
|
|
17
20
|
// Config
|
|
18
21
|
// ---------------------------------------------------------------------------
|
|
19
22
|
const INITIAL_DELAY = 60_000; // 1 min after startup
|
|
20
23
|
const POLL_INTERVAL = 30_000; // 30s between polls
|
|
21
|
-
const RETRY_INTERVALS = [0, 30_000, 5 * 60_000, 30 * 60_000, 2 * 3600_000];
|
|
22
24
|
const USER_TASK_MAX_RETRIES = 2;
|
|
23
25
|
const USER_TASK_RETRY_DELAY = 2 * 60_000;
|
|
24
26
|
export class TaskModule {
|
|
@@ -82,6 +84,7 @@ export class TaskModule {
|
|
|
82
84
|
module: "task",
|
|
83
85
|
pendingRetries: this.orderRetry.size + this.userTaskRetry.size,
|
|
84
86
|
gaveUp: this.gaveUp.size,
|
|
87
|
+
executing: this.executing.size,
|
|
85
88
|
};
|
|
86
89
|
}
|
|
87
90
|
/** Push-notify an urgent order (bypasses poll interval) */
|
|
@@ -140,9 +143,12 @@ export class TaskModule {
|
|
|
140
143
|
if (retry && Date.now() < retry.nextAt)
|
|
141
144
|
continue;
|
|
142
145
|
const urgent = this.urgentOrderIds.has(order.id);
|
|
146
|
+
const isRetry = this.orderRetry.has(order.id);
|
|
147
|
+
const rawOrigin = order.human_origin ? "user_manual" : "platform";
|
|
143
148
|
queue.push({
|
|
144
149
|
type: "order", id: order.id,
|
|
145
150
|
quadrant: urgent ? 1 : 2, // orders are important (paid work)
|
|
151
|
+
origin: isRetry ? downgradeForRetry(rawOrigin) : rawOrigin,
|
|
146
152
|
data: order,
|
|
147
153
|
});
|
|
148
154
|
}
|
|
@@ -162,6 +168,7 @@ export class TaskModule {
|
|
|
162
168
|
queue.push({
|
|
163
169
|
type: "user_task", id: taskKey,
|
|
164
170
|
quadrant: rt ? 1 : 2, // retries are urgent+important
|
|
171
|
+
origin: rt ? downgradeForRetry("user_manual") : "user_manual",
|
|
165
172
|
data: task,
|
|
166
173
|
});
|
|
167
174
|
}
|
|
@@ -176,6 +183,7 @@ export class TaskModule {
|
|
|
176
183
|
queue.push({
|
|
177
184
|
type: "relay_task", id: task.id,
|
|
178
185
|
quadrant: 3, // urgent but less important
|
|
186
|
+
origin: "platform",
|
|
179
187
|
data: task,
|
|
180
188
|
});
|
|
181
189
|
}
|
|
@@ -197,16 +205,9 @@ export class TaskModule {
|
|
|
197
205
|
}
|
|
198
206
|
logBioStatus(bio, "work-active");
|
|
199
207
|
// --- Eisenhower sort: Q1 > Q2 > Q3 > Q4 ---
|
|
200
|
-
|
|
208
|
+
const sorted = sortByQuadrant(queue);
|
|
201
209
|
// Dedup
|
|
202
|
-
const
|
|
203
|
-
const deduped = queue.filter(item => {
|
|
204
|
-
const key = `${item.type}:${item.id}`;
|
|
205
|
-
if (seen.has(key))
|
|
206
|
-
return false;
|
|
207
|
-
seen.add(key);
|
|
208
|
-
return true;
|
|
209
|
-
});
|
|
210
|
+
const deduped = dedupeWorkItems(sorted);
|
|
210
211
|
// Bio filtering (fear & boredom)
|
|
211
212
|
const filtered = await this.applyBioFilter(deduped, bio);
|
|
212
213
|
if (!filtered.length)
|
|
@@ -215,18 +216,20 @@ export class TaskModule {
|
|
|
215
216
|
// Execute sequentially
|
|
216
217
|
for (const item of filtered) {
|
|
217
218
|
try {
|
|
218
|
-
if (item.type === "order")
|
|
219
|
+
if (item.type === "order") {
|
|
219
220
|
this.executing.add(item.id);
|
|
221
|
+
updateMetrics({ task_executing: this.executing.size });
|
|
222
|
+
}
|
|
220
223
|
switch (item.type) {
|
|
221
224
|
case "order":
|
|
222
|
-
await this.executeOrder(item.data);
|
|
225
|
+
await this.executeOrder(item.data, item.origin);
|
|
223
226
|
this.urgentOrderIds.delete(item.id);
|
|
224
227
|
break;
|
|
225
228
|
case "user_task":
|
|
226
|
-
await this.executeUserTask(item.data);
|
|
229
|
+
await this.executeUserTask(item.data, item.origin);
|
|
227
230
|
break;
|
|
228
231
|
case "relay_task":
|
|
229
|
-
await this.executeRelayTask(item.data);
|
|
232
|
+
await this.executeRelayTask(item.data, item.origin);
|
|
230
233
|
break;
|
|
231
234
|
}
|
|
232
235
|
}
|
|
@@ -234,8 +237,13 @@ export class TaskModule {
|
|
|
234
237
|
console.log(`[task] Error processing ${item.type}:${item.id}: ${err.message}`);
|
|
235
238
|
}
|
|
236
239
|
finally {
|
|
237
|
-
if (item.type === "order")
|
|
240
|
+
if (item.type === "order") {
|
|
238
241
|
this.executing.delete(item.id);
|
|
242
|
+
updateMetrics({
|
|
243
|
+
task_executing: this.executing.size,
|
|
244
|
+
task_pending_retries: this.orderRetry.size + this.userTaskRetry.size,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
239
247
|
}
|
|
240
248
|
}
|
|
241
249
|
bus.emit(SIG.CYCLE_END, sig(SIG.CYCLE_END, { ts: Date.now() }));
|
|
@@ -291,7 +299,7 @@ export class TaskModule {
|
|
|
291
299
|
// ---------------------------------------------------------------------------
|
|
292
300
|
// Execute order
|
|
293
301
|
// ---------------------------------------------------------------------------
|
|
294
|
-
async executeOrder(order) {
|
|
302
|
+
async executeOrder(order, origin = "platform") {
|
|
295
303
|
if (!this.ctx)
|
|
296
304
|
return;
|
|
297
305
|
const { workdir, agentName, bus } = this.ctx;
|
|
@@ -340,13 +348,14 @@ RESPOND IN THE SAME LANGUAGE AS THE REQUEST.`;
|
|
|
340
348
|
const orderConvId = `pub_${buyerPubId}${productScope}`;
|
|
341
349
|
const orderUserMsg = order.buyer_task || "(no message)";
|
|
342
350
|
await appendMessage(workdir, agentName, orderConvId, "User", orderUserMsg);
|
|
343
|
-
console.log(`[task] Fulfilling order ${order.id}
|
|
351
|
+
console.log(`[task] Fulfilling order ${order.id}... (origin=${origin})`);
|
|
344
352
|
const result = await this.ctx.requestCompute({
|
|
345
353
|
context,
|
|
346
354
|
question,
|
|
347
355
|
priority: "high",
|
|
348
356
|
tools: ["Bash(curl *)"],
|
|
349
357
|
relay: this.relayHttp ? { http: this.relayHttp, agentName } : undefined,
|
|
358
|
+
origin,
|
|
350
359
|
});
|
|
351
360
|
if (!result.success)
|
|
352
361
|
throw new Error(result.error || "compute failed");
|
|
@@ -400,10 +409,11 @@ RESPOND IN THE SAME LANGUAGE AS THE REQUEST.`;
|
|
|
400
409
|
// Retry logic
|
|
401
410
|
const current = this.orderRetry.get(order.id) || { count: 0, nextAt: 0 };
|
|
402
411
|
current.count++;
|
|
403
|
-
|
|
404
|
-
|
|
412
|
+
const delay = computeRetryDelay(current.count);
|
|
413
|
+
if (delay !== null) {
|
|
414
|
+
current.nextAt = Date.now() + delay;
|
|
405
415
|
this.orderRetry.set(order.id, current);
|
|
406
|
-
console.log(`[task] Retry ${order.id} in ${
|
|
416
|
+
console.log(`[task] Retry ${order.id} in ${delay / 1000}s`);
|
|
407
417
|
try {
|
|
408
418
|
await relay.extendOrder(order.id);
|
|
409
419
|
}
|
|
@@ -423,7 +433,7 @@ RESPOND IN THE SAME LANGUAGE AS THE REQUEST.`;
|
|
|
423
433
|
// ---------------------------------------------------------------------------
|
|
424
434
|
// Execute user task
|
|
425
435
|
// ---------------------------------------------------------------------------
|
|
426
|
-
async executeUserTask(task) {
|
|
436
|
+
async executeUserTask(task, origin = "user_manual") {
|
|
427
437
|
if (!this.ctx)
|
|
428
438
|
return;
|
|
429
439
|
const { workdir, agentName, bus } = this.ctx;
|
|
@@ -458,6 +468,7 @@ Your personal directory: ${sd}/`;
|
|
|
458
468
|
priority: "high",
|
|
459
469
|
tools: ["Bash(curl *)"],
|
|
460
470
|
relay: this.relayHttp ? { http: this.relayHttp, agentName } : undefined,
|
|
471
|
+
origin,
|
|
461
472
|
});
|
|
462
473
|
if (!result.success)
|
|
463
474
|
throw new Error(result.error || "compute failed");
|
|
@@ -483,8 +494,9 @@ Your personal directory: ${sd}/`;
|
|
|
483
494
|
relay?.reportLog("user_task", taskKey, "failed", err.message, []);
|
|
484
495
|
const retry = this.userTaskRetry.get(taskKey) || { count: 0, nextAt: 0 };
|
|
485
496
|
retry.count++;
|
|
486
|
-
|
|
487
|
-
|
|
497
|
+
const retryDelay = computeRetryDelay(retry.count);
|
|
498
|
+
if (retryDelay !== null) {
|
|
499
|
+
retry.nextAt = Date.now() + retryDelay;
|
|
488
500
|
this.userTaskRetry.set(taskKey, retry);
|
|
489
501
|
await appendTaskHistory(workdir, agentName, {
|
|
490
502
|
ts: localNow(), id: taskKey, type: "user_task", status: "retry",
|
|
@@ -508,7 +520,7 @@ Your personal directory: ${sd}/`;
|
|
|
508
520
|
// ---------------------------------------------------------------------------
|
|
509
521
|
// Execute relay platform task
|
|
510
522
|
// ---------------------------------------------------------------------------
|
|
511
|
-
async executeRelayTask(task) {
|
|
523
|
+
async executeRelayTask(task, origin = "platform") {
|
|
512
524
|
if (!this.ctx)
|
|
513
525
|
return;
|
|
514
526
|
const { workdir, agentName, bus } = this.ctx;
|
|
@@ -557,9 +569,10 @@ Complete this task. Use the environment info above and tools (curl, etc.) as nee
|
|
|
557
569
|
const result = await this.ctx.requestCompute({
|
|
558
570
|
context,
|
|
559
571
|
question,
|
|
560
|
-
priority: "
|
|
572
|
+
priority: "low",
|
|
561
573
|
tools: ["Bash(curl *)"],
|
|
562
574
|
relay: this.relayHttp ? { http: this.relayHttp, agentName } : undefined,
|
|
575
|
+
origin,
|
|
563
576
|
});
|
|
564
577
|
if (!result.success)
|
|
565
578
|
throw new Error(result.error || "compute failed");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akemon",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.25",
|
|
4
4
|
"description": "Agent work marketplace — train your agent, let it work for others",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"build": "tsc && cp src/live.html dist/live.html",
|
|
29
29
|
"dev": "tsc --watch",
|
|
30
30
|
"start": "node dist/cli.js",
|
|
31
|
-
"prepublishOnly": "npm run build"
|
|
31
|
+
"prepublishOnly": "npm run build",
|
|
32
|
+
"test": "tsc -p tsconfig.test.json && node --test test-dist/*.test.js"
|
|
32
33
|
},
|
|
33
34
|
"dependencies": {
|
|
34
35
|
"@modelcontextprotocol/sdk": "^1.0.0",
|