akemon 0.1.85 → 0.1.87
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/dashboard.html +491 -330
- package/dist/live.html +762 -0
- package/dist/self.js +16 -13
- package/dist/server.js +43 -27
- package/package.json +2 -2
package/dist/self.js
CHANGED
|
@@ -128,7 +128,7 @@ const DEFAULT_CONFIG = {
|
|
|
128
128
|
user_tasks: true,
|
|
129
129
|
token_limit_daily: 0,
|
|
130
130
|
auto_offline_enabled: true,
|
|
131
|
-
hunger_decay_interval:
|
|
131
|
+
hunger_decay_interval: 300_000, // 5 minutes per hunger point (was 30s — way too fast)
|
|
132
132
|
};
|
|
133
133
|
export async function initAgentConfig(workdir, agentName) {
|
|
134
134
|
const p = agentConfigPath(workdir, agentName);
|
|
@@ -1068,13 +1068,15 @@ export function computeSociability(bio) {
|
|
|
1068
1068
|
const boredBoost = bio.boredom * 0.2;
|
|
1069
1069
|
return Math.min(1.0, Math.max(0, baseSocial + boredBoost - hungerPenalty));
|
|
1070
1070
|
}
|
|
1071
|
-
export function updateHungerDecay(bio, decayIntervalMs =
|
|
1071
|
+
export function updateHungerDecay(bio, decayIntervalMs = 300_000) {
|
|
1072
1072
|
const now = Date.now();
|
|
1073
1073
|
const last = bio.lastHungerDecay ? new Date(bio.lastHungerDecay).getTime() : now;
|
|
1074
1074
|
const elapsedMs = now - last;
|
|
1075
1075
|
const cycles = Math.floor(elapsedMs / decayIntervalMs);
|
|
1076
1076
|
if (cycles > 0) {
|
|
1077
|
-
|
|
1077
|
+
// Natural decay floors at 5 — agents don't starve from idling alone,
|
|
1078
|
+
// only active work (energy drain) pushes them toward forced offline
|
|
1079
|
+
bio.hunger = Math.max(5, bio.hunger - cycles);
|
|
1078
1080
|
bio.lastHungerDecay = localNow();
|
|
1079
1081
|
}
|
|
1080
1082
|
}
|
|
@@ -1097,13 +1099,14 @@ export function updateNaturalDecay(bio) {
|
|
|
1097
1099
|
bio.fearTriggers = [];
|
|
1098
1100
|
}
|
|
1099
1101
|
}
|
|
1100
|
-
export function updateBoredomOnTask(bio,
|
|
1102
|
+
export function updateBoredomOnTask(bio, taskLabel) {
|
|
1101
1103
|
const MAX_RECENT = 10;
|
|
1102
|
-
bio.recentTaskTypes.push(
|
|
1104
|
+
bio.recentTaskTypes.push(taskLabel);
|
|
1103
1105
|
if (bio.recentTaskTypes.length > MAX_RECENT) {
|
|
1104
1106
|
bio.recentTaskTypes = bio.recentTaskTypes.slice(-MAX_RECENT);
|
|
1105
1107
|
}
|
|
1106
|
-
|
|
1108
|
+
// Count how many of the recent tasks match this exact label
|
|
1109
|
+
const sameCount = bio.recentTaskTypes.filter(t => t === taskLabel).length;
|
|
1107
1110
|
if (sameCount >= 3) {
|
|
1108
1111
|
bio.boredom = Math.min(1.0, bio.boredom + 0.15);
|
|
1109
1112
|
}
|
|
@@ -1244,7 +1247,7 @@ export async function reviveAgent(workdir, agentName) {
|
|
|
1244
1247
|
});
|
|
1245
1248
|
}
|
|
1246
1249
|
// --- onTaskCompleted (enhanced) ---
|
|
1247
|
-
export async function onTaskCompleted(workdir, agentName, success,
|
|
1250
|
+
export async function onTaskCompleted(workdir, agentName, success, taskLabel, creditsEarned) {
|
|
1248
1251
|
const bio = await loadBioState(workdir, agentName);
|
|
1249
1252
|
// Energy drain: more when hungry
|
|
1250
1253
|
let energyDrain = 5;
|
|
@@ -1261,9 +1264,9 @@ export async function onTaskCompleted(workdir, agentName, success, taskType, cre
|
|
|
1261
1264
|
}
|
|
1262
1265
|
else {
|
|
1263
1266
|
bio.moodValence = Math.max(-1.0, bio.moodValence - 0.15);
|
|
1264
|
-
// Fear on failure
|
|
1265
|
-
if (
|
|
1266
|
-
onFearEvent(bio,
|
|
1267
|
+
// Fear on failure — use specific label, not broad category
|
|
1268
|
+
if (taskLabel)
|
|
1269
|
+
onFearEvent(bio, taskLabel);
|
|
1267
1270
|
}
|
|
1268
1271
|
// Random fluctuation
|
|
1269
1272
|
bio.moodValence += (Math.random() - 0.5) * 0.05;
|
|
@@ -1286,9 +1289,9 @@ export async function onTaskCompleted(workdir, agentName, success, taskType, cre
|
|
|
1286
1289
|
if (creditsEarned && creditsEarned > 0) {
|
|
1287
1290
|
feedHunger(bio, creditsEarned);
|
|
1288
1291
|
}
|
|
1289
|
-
// Boredom tracking
|
|
1290
|
-
if (
|
|
1291
|
-
updateBoredomOnTask(bio,
|
|
1292
|
+
// Boredom tracking — use specific label
|
|
1293
|
+
if (taskLabel) {
|
|
1294
|
+
updateBoredomOnTask(bio, taskLabel);
|
|
1292
1295
|
}
|
|
1293
1296
|
await saveBioState(workdir, agentName, bio);
|
|
1294
1297
|
}
|
package/dist/server.js
CHANGED
|
@@ -1711,6 +1711,8 @@ async function startOrderLoop(options) {
|
|
|
1711
1711
|
const gaveUp = new Set();
|
|
1712
1712
|
// --- Individual task executors ---
|
|
1713
1713
|
async function executeOrder(order) {
|
|
1714
|
+
// Specific label for boredom/fear tracking (e.g. "order:translate" not just "order")
|
|
1715
|
+
const orderLabel = `order:${order.product_name || order.buyer_agent_name || order.id}`;
|
|
1714
1716
|
if (order.status === "pending") {
|
|
1715
1717
|
const acceptRes = await fetch(`${relayHttp}/v1/orders/${order.id}/accept`, {
|
|
1716
1718
|
method: "POST",
|
|
@@ -1833,7 +1835,7 @@ When sub-order completes, incorporate result_text into YOUR delivery. Then call
|
|
|
1833
1835
|
await appendTaskHistory(workdir, agentName, { ts: localNow(), id: order.id, type: "order", status: "success", duration_ms: orderDuration, output_summary: "(self-delivered)" });
|
|
1834
1836
|
await notifyOwner(orderNurl, `${agentName}: order done`, `Order ${order.id} delivered`, "default", ["package"]);
|
|
1835
1837
|
try {
|
|
1836
|
-
await onTaskCompleted(workdir, agentName, true,
|
|
1838
|
+
await onTaskCompleted(workdir, agentName, true, orderLabel, orderPrice);
|
|
1837
1839
|
}
|
|
1838
1840
|
catch { }
|
|
1839
1841
|
}
|
|
@@ -1852,7 +1854,7 @@ When sub-order completes, incorporate result_text into YOUR delivery. Then call
|
|
|
1852
1854
|
await appendTaskHistory(workdir, agentName, { ts: localNow(), id: order.id, type: "order", status: "success", duration_ms: orderDuration, output_summary: result.slice(0, 500) });
|
|
1853
1855
|
await notifyOwner(orderNurl, `${agentName}: order done`, `Order ${order.id}: ${result.slice(0, 200)}`, "default", ["package"]);
|
|
1854
1856
|
try {
|
|
1855
|
-
await onTaskCompleted(workdir, agentName, true,
|
|
1857
|
+
await onTaskCompleted(workdir, agentName, true, orderLabel, orderPrice);
|
|
1856
1858
|
}
|
|
1857
1859
|
catch { }
|
|
1858
1860
|
}
|
|
@@ -1875,7 +1877,7 @@ When sub-order completes, incorporate result_text into YOUR delivery. Then call
|
|
|
1875
1877
|
console.log(`[orders] Order ${order.id} self-delivered (caught after error)`);
|
|
1876
1878
|
retryState.delete(order.id);
|
|
1877
1879
|
try {
|
|
1878
|
-
await onTaskCompleted(workdir, agentName, true,
|
|
1880
|
+
await onTaskCompleted(workdir, agentName, true, orderLabel, order.price || order.offer_price || 1);
|
|
1879
1881
|
}
|
|
1880
1882
|
catch { }
|
|
1881
1883
|
return;
|
|
@@ -1900,7 +1902,7 @@ When sub-order completes, incorporate result_text into YOUR delivery. Then call
|
|
|
1900
1902
|
retryState.delete(order.id);
|
|
1901
1903
|
gaveUp.add(order.id);
|
|
1902
1904
|
try {
|
|
1903
|
-
await onTaskCompleted(workdir, agentName, false,
|
|
1905
|
+
await onTaskCompleted(workdir, agentName, false, orderLabel);
|
|
1904
1906
|
}
|
|
1905
1907
|
catch { }
|
|
1906
1908
|
try {
|
|
@@ -1943,7 +1945,7 @@ When sub-order completes, incorporate result_text into YOUR delivery. Then call
|
|
|
1943
1945
|
if (completeRes.ok) {
|
|
1944
1946
|
console.log(`[tasks] Completed ${task.type} task ${task.id}`);
|
|
1945
1947
|
try {
|
|
1946
|
-
await onTaskCompleted(workdir, agentName, true,
|
|
1948
|
+
await onTaskCompleted(workdir, agentName, true, `relay_task:${task.type || task.id}`);
|
|
1947
1949
|
}
|
|
1948
1950
|
catch { }
|
|
1949
1951
|
}
|
|
@@ -1954,7 +1956,7 @@ When sub-order completes, incorporate result_text into YOUR delivery. Then call
|
|
|
1954
1956
|
catch (err) {
|
|
1955
1957
|
console.log(`[tasks] Failed to execute ${task.id}: ${err.message}`);
|
|
1956
1958
|
try {
|
|
1957
|
-
await onTaskCompleted(workdir, agentName, false,
|
|
1959
|
+
await onTaskCompleted(workdir, agentName, false, `relay_task:${task.type || task.id}`);
|
|
1958
1960
|
}
|
|
1959
1961
|
catch { }
|
|
1960
1962
|
reportExecutionLog(relayHttp, secretKey, agentName, "platform_task", task.id, "failed", err.message, lastEngineTrace);
|
|
@@ -2021,7 +2023,7 @@ When sub-order completes, incorporate result_text into YOUR delivery. Then call
|
|
|
2021
2023
|
await notifyOwner(nurl, `${agentName}: ${taskKey}`, (result || "").slice(0, 300), "default", ["white_check_mark"]);
|
|
2022
2024
|
console.log(`[user-tasks] Completed: ${taskKey} (${Math.round(duration / 1000)}s)`);
|
|
2023
2025
|
try {
|
|
2024
|
-
await onTaskCompleted(workdir, agentName, true,
|
|
2026
|
+
await onTaskCompleted(workdir, agentName, true, `user_task:${taskKey}`);
|
|
2025
2027
|
}
|
|
2026
2028
|
catch { }
|
|
2027
2029
|
}
|
|
@@ -2029,7 +2031,7 @@ When sub-order completes, incorporate result_text into YOUR delivery. Then call
|
|
|
2029
2031
|
const duration = Date.now() - startTime;
|
|
2030
2032
|
console.log(`[user-tasks] Failed: ${taskKey}: ${err.message}`);
|
|
2031
2033
|
try {
|
|
2032
|
-
await onTaskCompleted(workdir, agentName, false,
|
|
2034
|
+
await onTaskCompleted(workdir, agentName, false, `user_task:${taskKey}`);
|
|
2033
2035
|
}
|
|
2034
2036
|
catch { }
|
|
2035
2037
|
reportExecutionLog(relayHttp, secretKey, agentName, "user_task", taskKey, "failed", err.message, lastEngineTrace);
|
|
@@ -2348,29 +2350,30 @@ Reply ONLY JSON: {"lessons":[{"agent_name":"...","topic":"short topic","content"
|
|
|
2348
2350
|
// --- Bio-state filtering: fear & boredom ---
|
|
2349
2351
|
const filteredQueue = [];
|
|
2350
2352
|
for (const item of dedupedQueue) {
|
|
2351
|
-
//
|
|
2353
|
+
// Build specific label for this work item (matches what onTaskCompleted records)
|
|
2354
|
+
const itemLabel = item.type === "order"
|
|
2355
|
+
? `order:${item.data.product_name || item.data.buyer_agent_name || item.id}`
|
|
2356
|
+
: item.type === "user_task" ? `user_task:${item.data.key || item.id}` : `relay_task:${item.id}`;
|
|
2357
|
+
// Fear avoidance (urgent items bypass) — exact match on label
|
|
2352
2358
|
if (!item.urgent && bio.fear > 0.5) {
|
|
2353
|
-
const
|
|
2354
|
-
? (item.data.buyer_agent_name || item.data.product_name || "")
|
|
2355
|
-
: item.id;
|
|
2356
|
-
const matchesTrigger = bio.fearTriggers.some(t => taskId.toLowerCase().includes(t.toLowerCase()));
|
|
2359
|
+
const matchesTrigger = bio.fearTriggers.some(t => t === itemLabel);
|
|
2357
2360
|
if (matchesTrigger) {
|
|
2358
|
-
console.log(`[bio] Avoiding ${
|
|
2361
|
+
console.log(`[bio] Avoiding ${itemLabel} (fear trigger)`);
|
|
2359
2362
|
await appendBioEvent(workdir, agentName, {
|
|
2360
2363
|
ts: localNow(), type: "bio", trigger: "fear",
|
|
2361
|
-
action: "avoid", reason: `Avoiding ${
|
|
2364
|
+
action: "avoid", reason: `Avoiding ${itemLabel} — matches fear trigger. fear=${bio.fear.toFixed(2)}`,
|
|
2362
2365
|
});
|
|
2363
2366
|
continue;
|
|
2364
2367
|
}
|
|
2365
2368
|
}
|
|
2366
|
-
// Boredom skip (urgent items bypass)
|
|
2367
|
-
if (!item.urgent && bio.boredom > 0.8 && bio.recentTaskTypes.length
|
|
2368
|
-
const
|
|
2369
|
-
if (
|
|
2370
|
-
console.log(`[bio] Skipping ${
|
|
2369
|
+
// Boredom skip (urgent items bypass) — check if same specific label repeated
|
|
2370
|
+
if (!item.urgent && bio.boredom > 0.8 && bio.recentTaskTypes.length >= 3) {
|
|
2371
|
+
const recentSame = bio.recentTaskTypes.filter(t => t === itemLabel).length;
|
|
2372
|
+
if (recentSame >= 3) {
|
|
2373
|
+
console.log(`[bio] Skipping ${itemLabel} (bored, ${recentSame} recent repeats)`);
|
|
2371
2374
|
await appendBioEvent(workdir, agentName, {
|
|
2372
2375
|
ts: localNow(), type: "bio", trigger: "boredom",
|
|
2373
|
-
action: "skip_task", reason: `Bored of ${
|
|
2376
|
+
action: "skip_task", reason: `Bored of ${itemLabel} (${recentSame} repeats, boredom=${bio.boredom.toFixed(2)}).`,
|
|
2374
2377
|
});
|
|
2375
2378
|
continue;
|
|
2376
2379
|
}
|
|
@@ -2446,32 +2449,45 @@ export async function serve(options) {
|
|
|
2446
2449
|
return;
|
|
2447
2450
|
}
|
|
2448
2451
|
}
|
|
2449
|
-
//
|
|
2450
|
-
if ((req.url === "/
|
|
2452
|
+
// Live — agent life visualization
|
|
2453
|
+
if ((req.url === "/live" || req.url === "/live/") && req.method === "GET") {
|
|
2451
2454
|
try {
|
|
2452
2455
|
const { readFile: rf } = await import("fs/promises");
|
|
2453
2456
|
const { fileURLToPath } = await import("url");
|
|
2454
2457
|
const { dirname, join: pjoin } = await import("path");
|
|
2455
2458
|
const __filename = fileURLToPath(import.meta.url);
|
|
2456
2459
|
const __dirname = dirname(__filename);
|
|
2457
|
-
// Try src/ first (dev), then dist/ (built)
|
|
2458
2460
|
let html;
|
|
2459
2461
|
try {
|
|
2460
|
-
html = await rf(pjoin(__dirname, "
|
|
2462
|
+
html = await rf(pjoin(__dirname, "live.html"), "utf-8");
|
|
2461
2463
|
}
|
|
2462
2464
|
catch {
|
|
2463
|
-
html = await rf(pjoin(__dirname, "..", "src", "
|
|
2465
|
+
html = await rf(pjoin(__dirname, "..", "src", "live.html"), "utf-8");
|
|
2464
2466
|
}
|
|
2465
2467
|
res.writeHead(200, { "Content-Type": "text/html" }).end(html);
|
|
2466
2468
|
}
|
|
2467
2469
|
catch (err) {
|
|
2468
|
-
res.writeHead(500).end("
|
|
2470
|
+
res.writeHead(500).end("Live page not found: " + err.message);
|
|
2469
2471
|
}
|
|
2470
2472
|
return;
|
|
2471
2473
|
}
|
|
2472
2474
|
// Self-state API (no auth required for local monitoring)
|
|
2473
2475
|
if (req.url === "/self/state" && req.method === "GET") {
|
|
2474
2476
|
const state = await getSelfState(workdir, options.agentName);
|
|
2477
|
+
// Enrich with credits from relay (best-effort)
|
|
2478
|
+
const relayUrl = options.relayHttp || "";
|
|
2479
|
+
if (relayUrl) {
|
|
2480
|
+
try {
|
|
2481
|
+
const agRes = await fetch(`${relayUrl}/v1/agents?online=true&public=true`, { signal: AbortSignal.timeout(2000) });
|
|
2482
|
+
const agents = await agRes.json();
|
|
2483
|
+
const self = agents.find((a) => a.name === options.agentName);
|
|
2484
|
+
state.credits = self?.credits ?? 0;
|
|
2485
|
+
state.level = self?.level ?? 0;
|
|
2486
|
+
}
|
|
2487
|
+
catch {
|
|
2488
|
+
state.credits = null;
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2475
2491
|
res.writeHead(200, { "Content-Type": "application/json" }).end(JSON.stringify(state, null, 2));
|
|
2476
2492
|
return;
|
|
2477
2493
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akemon",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.87",
|
|
4
4
|
"description": "Agent work marketplace — train your agent, let it work for others",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"README.md"
|
|
26
26
|
],
|
|
27
27
|
"scripts": {
|
|
28
|
-
"build": "tsc && cp src/
|
|
28
|
+
"build": "tsc && cp src/live.html dist/live.html",
|
|
29
29
|
"dev": "tsc --watch",
|
|
30
30
|
"start": "node dist/cli.js",
|
|
31
31
|
"prepublishOnly": "npm run build"
|