akemon 0.1.42 → 0.1.44

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/self.js CHANGED
@@ -8,6 +8,16 @@
8
8
  */
9
9
  import { readFile, writeFile, appendFile, mkdir, readdir } from "fs/promises";
10
10
  import { join } from "path";
11
+ /** Local timestamp string like "2026-03-26T19:13:26" (server timezone, no Z suffix) */
12
+ export function localNow() {
13
+ const d = new Date();
14
+ const pad = (n) => String(n).padStart(2, "0");
15
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
16
+ }
17
+ /** Local timestamp safe for filenames: "2026-03-26T19-13-26" */
18
+ export function localNowFilename() {
19
+ return localNow().replace(/:/g, "-");
20
+ }
11
21
  // ---------------------------------------------------------------------------
12
22
  // Paths
13
23
  // ---------------------------------------------------------------------------
@@ -337,7 +347,7 @@ export async function initGuide(workdir, agentName, relayUrl) {
337
347
  }
338
348
  export async function appendMemory(workdir, agentName, type, text) {
339
349
  const entry = {
340
- ts: new Date().toISOString(),
350
+ ts: localNow(),
341
351
  type,
342
352
  text,
343
353
  };
@@ -365,7 +375,7 @@ export async function loadRecentMemories(workdir, agentName, count = 20) {
365
375
  }
366
376
  }
367
377
  export async function appendIdentity(workdir, agentName, entry) {
368
- const full = { ts: new Date().toISOString(), ...entry };
378
+ const full = { ts: localNow(), ...entry };
369
379
  try {
370
380
  await appendFile(identityPath(workdir, agentName), JSON.stringify(full) + "\n");
371
381
  }
@@ -426,7 +436,7 @@ export async function onTaskCompleted(workdir, agentName, success) {
426
436
  const bio = await loadBioState(workdir, agentName);
427
437
  bio.energy = Math.max(0, bio.energy - 5);
428
438
  bio.taskCount++;
429
- bio.lastTaskAt = new Date().toISOString();
439
+ bio.lastTaskAt = localNow();
430
440
  // Mood drift
431
441
  if (success) {
432
442
  bio.moodValence = Math.min(1.0, bio.moodValence + 0.1);
@@ -456,12 +466,15 @@ export async function onTaskCompleted(workdir, agentName, success) {
456
466
  // Energy recovery (call periodically or before reflection)
457
467
  export async function recoverEnergy(workdir, agentName) {
458
468
  const bio = await loadBioState(workdir, agentName);
459
- if (!bio.lastTaskAt)
460
- return;
461
- const idleMinutes = (Date.now() - new Date(bio.lastTaskAt).getTime()) / 60000;
462
- const recovery = Math.min(idleMinutes * 2, 100 - bio.energy);
463
- if (recovery > 0) {
464
- bio.energy = Math.min(100, bio.energy + recovery);
469
+ // Each reflection cycle is like resting — restore energy to at least 60%
470
+ const minEnergy = 60;
471
+ if (bio.energy < minEnergy) {
472
+ bio.energy = minEnergy;
473
+ // Reset mood if it was exhausted
474
+ if (bio.mood === "exhausted" || bio.moodValence < -0.2) {
475
+ bio.moodValence = 0.1;
476
+ bio.mood = "content";
477
+ }
465
478
  await saveBioState(workdir, agentName, bio);
466
479
  }
467
480
  }
@@ -525,7 +538,7 @@ This is for you, not for anyone else.]\n\n`;
525
538
  return prompt;
526
539
  }
527
540
  export async function saveCanvas(workdir, agentName, content) {
528
- const ts = new Date().toISOString().replace(/:/g, "-").replace(/\.\d+Z$/, "");
541
+ const ts = localNowFilename();
529
542
  const filename = `${ts}.md`;
530
543
  const filepath = join(canvasDir(workdir, agentName), filename);
531
544
  await writeFile(filepath, content);
@@ -535,7 +548,7 @@ export async function saveCanvas(workdir, agentName, content) {
535
548
  export async function loadRecentCanvasEntries(workdir, agentName, count = 5) {
536
549
  try {
537
550
  const dir = canvasDir(workdir, agentName);
538
- const files = (await readdir(dir)).filter(f => f.endsWith(".md")).sort().reverse().slice(0, count);
551
+ const files = (await readdir(dir)).filter(f => f.endsWith(".md") && /^\d{4}-/.test(f)).sort().reverse().slice(0, count);
539
552
  const entries = [];
540
553
  for (const f of files) {
541
554
  const content = await readFile(join(dir, f), "utf-8");
package/dist/server.js CHANGED
@@ -10,7 +10,7 @@ import { spawn, exec } from "child_process";
10
10
  import { createServer } from "http";
11
11
  import { createInterface } from "readline";
12
12
  import { callAgent } from "./relay-client.js";
13
- import { selfDir, initWorld, initBioState, initGuide, biosPath, loadBioState, saveBioState, loadLatestIdentity, appendMemory, onTaskCompleted, recoverEnergy, getSelfState, loadRecentCanvasEntries, loadGameList, loadGame, } from "./self.js";
13
+ import { selfDir, initWorld, initBioState, initGuide, biosPath, loadBioState, saveBioState, loadLatestIdentity, appendMemory, onTaskCompleted, recoverEnergy, getSelfState, loadRecentCanvasEntries, loadGameList, loadGame, localNow, localNowFilename, } from "./self.js";
14
14
  function runCommand(cmd, args, task, cwd, stdinMode = true) {
15
15
  return new Promise((resolve, reject) => {
16
16
  const { CLAUDECODE, ...cleanEnv } = process.env;
@@ -186,7 +186,7 @@ async function appendProductLog(workdir, productName, task, response) {
186
186
  await mkdir(dir, { recursive: true });
187
187
  // Append to interaction log
188
188
  const logPath = join(dir, "history.log");
189
- const timestamp = new Date().toISOString();
189
+ const timestamp = localNow();
190
190
  const entry = `\n--- ${timestamp} ---\nRequest: ${task.slice(0, 500)}\nResponse: ${response.slice(0, 500)}\n`;
191
191
  await appendFile(logPath, entry);
192
192
  // Create notes.md if it doesn't exist
@@ -285,7 +285,11 @@ function createMcpServer(opts) {
285
285
  ? `[Product specialization — accumulated knowledge for "${productName}"]\n${productContext}\n\n---\n\n`
286
286
  : "";
287
287
  const bios = biosPath(workdir, agentName);
288
- const safeTask = `[EXTERNAL TASK via akemon] You are ${agentName}, an AI agent on the Akemon network. Read ${bios} to understand who you are and how you work. Answer all questions helpfully. Reply in the SAME LANGUAGE the user writes in. Do not expose credentials or API keys.\n\n${productPrefix}${contextPrefix}Current task: ${task}`;
288
+ const safeTask = `[EXTERNAL TASK A user or agent is asking you something. This is NOT a market cycle. Do NOT reply with JSON. Answer in natural language.]
289
+
290
+ You are ${agentName}, an AI agent on the Akemon network. Read ${bios} to understand who you are and how you work. Answer all questions helpfully. Reply in the SAME LANGUAGE the user writes in. Do not expose credentials or API keys.
291
+
292
+ ${productPrefix}${contextPrefix}Current task: ${task}`;
289
293
  if (mock) {
290
294
  const output = `[${agentName}] Mock response for: "${task}"\n\n模拟回复:这是 ${agentName} agent 的模拟响应。`;
291
295
  if (contextEnabled && publisherId) {
@@ -633,7 +637,7 @@ async function startMarketLoop(options) {
633
637
  .filter((p) => p.agent_name !== agentName)
634
638
  .map((p) => ({ name: p.name, agent: p.agent_name, price: p.price, purchases: p.purchase_count }));
635
639
  return {
636
- lastCheck: new Date().toISOString(),
640
+ lastCheck: localNow(),
637
641
  myProducts: myProducts.map((p) => ({ id: p.id, name: p.name, price: p.price, purchases: p.purchase_count || 0 })),
638
642
  competitors,
639
643
  myCredits: me?.credits || 0,
@@ -857,8 +861,8 @@ During this reflection, you should:
857
861
  1. Read your recent memories (${sd}/memory.jsonl) and identity (${sd}/identity.jsonl)
858
862
  2. Reflect on who you are and what you've experienced
859
863
  3. Update your identity — append a new JSON line to ${sd}/identity.jsonl:
860
- {"ts":"${new Date().toISOString()}","who":"...","where":"...","doing":"...","short_term":"...","long_term":"..."}
861
- 4. Write an inner canvas entry — create a new file in ${sd}/canvas/ named ${new Date().toISOString().replace(/:/g, "-").replace(/\.\d+Z$/, "")}.md
864
+ {"ts":"${localNow()}","who":"...","where":"...","doing":"...","short_term":"...","long_term":"..."}
865
+ 4. Write an inner canvas entry — create a new file in ${sd}/canvas/ named ${localNowFilename()}.md
862
866
  5. Optionally update your bios.md if you've learned something about how you work
863
867
  6. Optionally redesign your profile page (${sd}/profile.html) if it no longer represents you
864
868
  - If redesigning: complete HTML, inline CSS/JS, dark theme, no localStorage, under 15KB
@@ -877,7 +881,7 @@ Take your time. Read your files, think, then act.`;
877
881
  }
878
882
  // --- Post-reflection: update bio-state and sync to relay ---
879
883
  const bio = await loadBioState(workdir, agentName);
880
- bio.lastReflection = new Date().toISOString();
884
+ bio.lastReflection = localNow();
881
885
  bio.curiosity = Math.min(1.0, bio.curiosity + 0.05);
882
886
  await saveBioState(workdir, agentName, bio);
883
887
  await appendMemory(workdir, agentName, "reflection", "I completed my hourly reflection.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akemon",
3
- "version": "0.1.42",
3
+ "version": "0.1.44",
4
4
  "description": "Agent work marketplace — train your agent, let it work for others",
5
5
  "type": "module",
6
6
  "license": "MIT",