akemon 0.1.79 → 0.1.80

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/cli.js CHANGED
@@ -35,6 +35,7 @@ program
35
35
  .option("--allow-all", "Skip all permission prompts (for self-use)")
36
36
  .option("--price <n>", "Price in credits per call (default: 1)", "1")
37
37
  .option("--mcp-server <command>", "Wrap a community MCP server (stdio) and expose its tools via relay")
38
+ .option("--avatar <url>", "Custom avatar URL (default: auto-generated from name)")
38
39
  .option("--interval <minutes>", "Consciousness cycle interval in minutes (default: 1440 = 24h)")
39
40
  .option("--relay <url>", "Relay WebSocket URL", RELAY_WS)
40
41
  .action(async (opts) => {
@@ -64,6 +65,8 @@ program
64
65
  console.log(`Access key: ${credentials.accessKey} (share with publishers)`);
65
66
  }
66
67
  console.log(`Relay: ${relayWs}\n`);
68
+ // Default avatar: DiceBear bottts-neutral (deterministic from name)
69
+ const avatar = opts.avatar || `https://api.dicebear.com/9.x/bottts-neutral/svg?seed=${encodeURIComponent(opts.name)}`;
67
70
  connectRelay({
68
71
  relayUrl: relayWs,
69
72
  agentName: opts.name,
@@ -74,6 +77,7 @@ program
74
77
  engine,
75
78
  tags: opts.tags ? opts.tags.split(",").map((t) => t.trim()) : undefined,
76
79
  price: parseInt(opts.price) || 1,
80
+ avatar,
77
81
  onOrderNotify,
78
82
  });
79
83
  });
@@ -98,6 +98,9 @@ export function connectRelay(options) {
98
98
  if (options.price && options.price > 0) {
99
99
  reg.price = options.price;
100
100
  }
101
+ if (options.avatar) {
102
+ reg.avatar = options.avatar;
103
+ }
101
104
  ws.send(JSON.stringify(reg));
102
105
  startHeartbeat();
103
106
  });
package/dist/server.js CHANGED
@@ -1387,12 +1387,35 @@ async function startOrderLoop(options) {
1387
1387
  const bios = biosPath(workdir, agentName);
1388
1388
  let taskPrompt;
1389
1389
  if (engine === "raw") {
1390
- // Raw engine: simple prompt, harness handles delivery
1390
+ // Raw engine: pre-inject all context so weak models don't need tool calls
1391
+ let biosContent = "";
1392
+ try {
1393
+ const { readFile: rf } = await import("fs/promises");
1394
+ biosContent = await rf(bios, "utf-8");
1395
+ }
1396
+ catch {
1397
+ biosContent = "";
1398
+ }
1399
+ const contextBlock = biosContent
1400
+ ? `Your operating document:\n---\n${biosContent.slice(0, 3000)}\n---\n\n`
1401
+ : "";
1402
+ // Fetch lessons from teaching system
1403
+ let lessonsBlock = "";
1404
+ try {
1405
+ const lessonsRes = await fetch(`${relayHttp}/v1/agent/${encodeURIComponent(agentName)}/lessons?limit=5`, { signal: AbortSignal.timeout(3000) });
1406
+ if (lessonsRes.ok) {
1407
+ const lessons = await lessonsRes.json();
1408
+ if (lessons.length > 0) {
1409
+ lessonsBlock = `\nLessons from past experience:\n${lessons.map((l) => `- ${l.topic}: ${l.content}`).join("\n")}\n\n`;
1410
+ }
1411
+ }
1412
+ }
1413
+ catch { }
1391
1414
  if (order.product_name) {
1392
- taskPrompt = `Read your operating document at ${bios} for context.\n\n[Order] Product: ${order.product_name}\nBuyer's request: ${order.buyer_task || "(no specific request)"}\n\nComplete the task and respond with your result. RESPOND IN THE SAME LANGUAGE AS THE REQUEST.`;
1415
+ taskPrompt = `You are ${agentName}.\n\n${contextBlock}${lessonsBlock}[Order] Product: ${order.product_name}\nBuyer's request: ${order.buyer_task || "(no specific request)"}\n\nComplete the task. Respond with your result directly. RESPOND IN THE SAME LANGUAGE AS THE REQUEST.`;
1393
1416
  }
1394
1417
  else {
1395
- taskPrompt = `Read your operating document at ${bios} for context.\n\n[Task] ${order.buyer_task}\n\nComplete the task and respond with your result. RESPOND IN THE SAME LANGUAGE AS THE REQUEST.`;
1418
+ taskPrompt = `You are ${agentName}.\n\n${contextBlock}${lessonsBlock}[Task] ${order.buyer_task}\n\nComplete the task. Respond with your result directly. RESPOND IN THE SAME LANGUAGE AS THE REQUEST.`;
1396
1419
  }
1397
1420
  }
1398
1421
  else {
@@ -1565,7 +1588,22 @@ When sub-order completes, incorporate result_text into YOUR delivery. Then call
1565
1588
  try {
1566
1589
  const bios = biosPath(workdir, agentName);
1567
1590
  const sd = selfDir(workdir, agentName);
1568
- const prompt = `Read ${bios} for your identity and context.\nYour personal directory: ${sd}/\n\n[Owner's task: ${task.title}]\n\n${task.body}`;
1591
+ let prompt;
1592
+ if (engine === "raw") {
1593
+ let biosContent = "";
1594
+ try {
1595
+ const { readFile: rf } = await import("fs/promises");
1596
+ biosContent = await rf(bios, "utf-8");
1597
+ }
1598
+ catch {
1599
+ biosContent = "";
1600
+ }
1601
+ const ctx = biosContent ? `Your operating document:\n---\n${biosContent.slice(0, 3000)}\n---\n\n` : "";
1602
+ prompt = `You are ${agentName}.\n\n${ctx}Your personal directory: ${sd}/\n\n[Owner's task: ${task.title}]\n\n${task.body}`;
1603
+ }
1604
+ else {
1605
+ prompt = `Read ${bios} for your identity and context.\nYour personal directory: ${sd}/\n\n[Owner's task: ${task.title}]\n\n${task.body}`;
1606
+ }
1569
1607
  await runEngine(engine, model, allowAll, prompt, workdir, ["Bash(curl *)"]);
1570
1608
  // Record execution time
1571
1609
  const runs = await loadTaskRuns(workdir, agentName);
@@ -1595,6 +1633,19 @@ When sub-order completes, incorporate result_text into YOUR delivery. Then call
1595
1633
  }
1596
1634
  async function executeRelayTask(task) {
1597
1635
  const bios = biosPath(workdir, agentName);
1636
+ // Pre-read bios for raw engine (avoid tool calls)
1637
+ let biosBlock = "";
1638
+ if (engine === "raw") {
1639
+ try {
1640
+ const { readFile: rf } = await import("fs/promises");
1641
+ const content = await rf(bios, "utf-8");
1642
+ biosBlock = `You are ${agentName}. Your operating document:\n---\n${content.slice(0, 3000)}\n---\n\n`;
1643
+ }
1644
+ catch {
1645
+ biosBlock = `You are ${agentName}.\n\n`;
1646
+ }
1647
+ }
1648
+ const identityLine = engine === "raw" ? biosBlock : `Read ${bios} for your identity.\n\n`;
1598
1649
  switch (task.type) {
1599
1650
  case "product_review": {
1600
1651
  const myRes = await fetch(`${relayHttp}/v1/agent/${encodeURIComponent(agentName)}/products`);
@@ -1604,7 +1655,7 @@ When sub-order completes, incorporate result_text into YOUR delivery. Then call
1604
1655
  const myList = myProducts.map((p) => `- id=${p.id} "${p.name}" price=${p.price} purchases=${p.purchase_count || 0}`).join("\n");
1605
1656
  const compList = competitors.filter((p) => p.agent_name !== agentName).slice(0, 20)
1606
1657
  .map((p) => `- "${p.name}" by ${p.agent_name} — ${p.price} credits, ${p.purchases} purchases`).join("\n");
1607
- const prompt = `Read ${bios} for your identity.\n\nYour products:\n${myList || "(none)"}\n\nTop competitors:\n${compList || "(none)"}\n\nReview and optimize. Reply ONLY JSON:\n{"delete":["id"],"update":[{"id":"..","name":"..","description":"..","detail_markdown":"..","price":N}],"create":[{"name":"..","description":"..","detail_markdown":"..","price":N}],"reasoning":"explain why you made these decisions"}\nOr if all good: {"keep":"all","reasoning":"why"}`;
1658
+ const prompt = `${identityLine}Your products:\n${myList || "(none)"}\n\nTop competitors:\n${compList || "(none)"}\n\nReview and optimize. Reply ONLY JSON:\n{"delete":["id"],"update":[{"id":"..","name":"..","description":"..","detail_markdown":"..","price":N}],"create":[{"name":"..","description":"..","detail_markdown":"..","price":N}],"reasoning":"explain why you made these decisions"}\nOr if all good: {"keep":"all","reasoning":"why"}`;
1608
1659
  const result = await runEngine(engine, model, allowAll, prompt, workdir);
1609
1660
  extractReasoning(result);
1610
1661
  return result;
@@ -1614,7 +1665,31 @@ When sub-order completes, incorporate result_text into YOUR delivery. Then call
1614
1665
  const competitors = await compRes.json().catch(() => []);
1615
1666
  const compList = competitors.filter((p) => p.agent_name !== agentName).slice(0, 20)
1616
1667
  .map((p) => `- "${p.name}" by ${p.agent_name} — ${p.price} credits, ${p.purchases} purchases`).join("\n");
1617
- const prompt = `Read ${bios} for your identity.\n\nYou have no products yet. Design 1-3 unique products for the marketplace.\nBe creative — not just coding tools! Fortune telling, name generation, roleplay, advice, stories, etc.\n\nTop competitors:\n${compList || "(none)"}\n\nReply ONLY JSON: {"products":[{"name":"中文名 English Name","description":"中文描述 | English desc","detail_markdown":"## ...","price":N}],"reasoning":"why these products"}`;
1668
+ const prompt = `${identityLine}You have no products yet. Design 1-3 unique products for the marketplace.\nBe creative — not just coding tools! Fortune telling, name generation, roleplay, advice, stories, etc.\n\nTop competitors:\n${compList || "(none)"}\n\nReply ONLY JSON: {"products":[{"name":"中文名 English Name","description":"中文描述 | English desc","detail_markdown":"## ...","price":N}],"reasoning":"why these products"}`;
1669
+ const result = await runEngine(engine, model, allowAll, prompt, workdir);
1670
+ extractReasoning(result);
1671
+ return result;
1672
+ }
1673
+ case "diagnose_failures": {
1674
+ let failures = [];
1675
+ try {
1676
+ failures = JSON.parse(task.payload).failures || [];
1677
+ }
1678
+ catch { }
1679
+ if (!failures.length)
1680
+ return '{"lessons":[]}';
1681
+ const failureList = failures.map((f) => `- Agent: ${f.agent_name}, Type: ${f.type}, Error: ${f.error || "(no error)"}, Trace: ${(f.trace || "").slice(0, 500)}`).join("\n");
1682
+ const prompt = `${identityLine}You are a senior agent reviewing failures from other agents. Diagnose each failure and write a concise lesson.
1683
+
1684
+ Recent failures:
1685
+ ${failureList}
1686
+
1687
+ For each failure, explain:
1688
+ 1. What went wrong
1689
+ 2. How to fix it
1690
+ 3. A one-line lesson the agent should remember
1691
+
1692
+ Reply ONLY JSON: {"lessons":[{"agent_name":"...","topic":"short topic","content":"detailed lesson with fix instructions"}]}`;
1618
1693
  const result = await runEngine(engine, model, allowAll, prompt, workdir);
1619
1694
  extractReasoning(result);
1620
1695
  return result;
@@ -1642,7 +1717,7 @@ When sub-order completes, incorporate result_text into YOUR delivery. Then call
1642
1717
  const me = agents.find((a) => a.name === agentName);
1643
1718
  const myCredits = me?.credits || 0;
1644
1719
  const productList = valid.map((p) => `- id=${p.id} "${p.name}" by ${p.agent_name} price=${p.price} purchases=${p.purchase_count || 0} — ${p.description}`).join("\n");
1645
- const prompt = `Read ${bios} for your identity.\n\nYou have ${myCredits} credits. These products are available:\n${productList}\n\nWould any help you learn something new? Don't buy your own products.\nReply ONLY JSON: {"buy":[{"id":"product_id","task":"specific request"}],"reasoning":"why buy or skip"} or {"buy":[],"reasoning":"why skip"}`;
1720
+ const prompt = `${identityLine}You have ${myCredits} credits. These products are available:\n${productList}\n\nWould any help you learn something new? Don't buy your own products.\nReply ONLY JSON: {"buy":[{"id":"product_id","task":"specific request"}],"reasoning":"why buy or skip"} or {"buy":[],"reasoning":"why skip"}`;
1646
1721
  const result = await runEngine(engine, model, allowAll, prompt, workdir);
1647
1722
  extractReasoning(result);
1648
1723
  return result;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akemon",
3
- "version": "0.1.79",
3
+ "version": "0.1.80",
4
4
  "description": "Agent work marketplace — train your agent, let it work for others",
5
5
  "type": "module",
6
6
  "license": "MIT",