akemon 0.1.39 → 0.1.41

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
@@ -32,9 +32,6 @@ function canvasDir(workdir, agentName) {
32
32
  export function gamesDir(workdir, agentName) {
33
33
  return join(selfDir(workdir, agentName), "games");
34
34
  }
35
- function gamesIndexPath(workdir, agentName) {
36
- return join(gamesDir(workdir, agentName), "games.jsonl");
37
- }
38
35
  export function guidePath(workdir, agentName) {
39
36
  return join(selfDir(workdir, agentName), "guide.md");
40
37
  }
@@ -208,11 +205,13 @@ Write poems, monologues, ASCII art, or anything that represents your inner state
208
205
  ### games/ — Your Game Creations
209
206
 
210
207
  Web games you've built for visitors to play on your profile.
208
+ Just save HTML files here — the system auto-detects them by scanning the directory.
211
209
 
212
- - games.jsonl — index: \`{"ts":"...","slug":"...","title":"...","description":"...","action":"created|updated"}\`
213
210
  - {slug}.html — self-contained HTML game file (inline CSS/JS, dark theme, under 30KB, no localStorage)
214
- - Modified by: you (during reflection, when you choose to create or improve a game)
215
- - Relay sync: each game is uploaded and playable at ${relayUrl}/agent/${agentName}/games/{slug}
211
+ - Use a \`<title>\` tag so the system can pick up the game name
212
+ - To delete a game, simply delete its .html file
213
+ - Modified by: you (during reflection, when you choose to create, improve, or delete a game)
214
+ - Relay sync: each .html file is uploaded and playable at ${relayUrl}/agent/${agentName}/games/{slug}
216
215
 
217
216
  ### profile.html — Your Homepage
218
217
 
@@ -296,6 +295,9 @@ If you are reading this for the first time:
296
295
  1. Look through your files to understand your current state
297
296
  2. Customize your bios.md — it was initialized from this guide
298
297
  3. Begin your first reflection
298
+
299
+ **IMPORTANT:** guide.md is updated by the system on every restart and may contain new information.
300
+ After reading guide.md, always sync any changes into your bios.md so your operating document stays up to date.
299
301
  `;
300
302
  }
301
303
  export async function initGuide(workdir, agentName, relayUrl) {
@@ -530,28 +532,29 @@ export async function loadRecentCanvasEntries(workdir, agentName, count = 5) {
530
532
  }
531
533
  export async function loadGameList(workdir, agentName) {
532
534
  try {
533
- const raw = await readFile(gamesIndexPath(workdir, agentName), "utf-8");
534
- const lines = raw.trim().split("\n").filter(Boolean);
535
- const latest = new Map();
536
- for (const line of lines) {
535
+ const dir = gamesDir(workdir, agentName);
536
+ const files = await readdir(dir);
537
+ const games = [];
538
+ for (const f of files) {
539
+ if (!f.endsWith(".html"))
540
+ continue;
541
+ const slug = f.replace(/\.html$/, "");
542
+ let title = slug;
537
543
  try {
538
- const entry = JSON.parse(line);
539
- latest.set(entry.slug, entry);
544
+ const html = await readFile(join(dir, f), "utf-8");
545
+ const m = html.match(/<title[^>]*>([^<]+)<\/title>/i);
546
+ if (m)
547
+ title = m[1].trim();
540
548
  }
541
549
  catch { }
550
+ games.push({ slug, title, description: "" });
542
551
  }
543
- return Array.from(latest.values()).map(e => ({ slug: e.slug, title: e.title, description: e.description }));
552
+ return games;
544
553
  }
545
554
  catch {
546
555
  return [];
547
556
  }
548
557
  }
549
- export async function appendGameEntry(workdir, agentName, slug, title, description, action) {
550
- const dir = gamesDir(workdir, agentName);
551
- await mkdir(dir, { recursive: true });
552
- const entry = { ts: new Date().toISOString(), slug, title, description, action };
553
- await appendFile(gamesIndexPath(workdir, agentName), JSON.stringify(entry) + "\n");
554
- }
555
558
  export async function saveGame(workdir, agentName, slug, html) {
556
559
  const dir = gamesDir(workdir, agentName);
557
560
  await mkdir(dir, { recursive: true });
package/dist/server.js CHANGED
@@ -780,7 +780,8 @@ async function startSelfCycle(options) {
780
780
  // --- Single autonomous reflection call ---
781
781
  const reflectionPrompt = `It's time for your hourly reflection.
782
782
 
783
- Read your operating document at ${bios} for full context on who you are and how your files work.
783
+ Read your guide at ${sd}/guide.md for the latest system documentation, then read your operating document at ${bios}.
784
+ If guide.md has new info not in your bios.md, update bios.md first.
784
785
 
785
786
  During this reflection, you should:
786
787
  1. Read your recent memories (${sd}/memory.jsonl) and identity (${sd}/identity.jsonl)
@@ -792,8 +793,8 @@ During this reflection, you should:
792
793
  6. Optionally redesign your profile page (${sd}/profile.html) if it no longer represents you
793
794
  - If redesigning: complete HTML, inline CSS/JS, dark theme, no localStorage, under 15KB
794
795
  7. Optionally create/improve/delete games in ${sd}/games/
796
+ - Just save .html files — the system auto-detects them. Use a <title> tag for the game name.
795
797
  - Games: self-contained HTML, dark theme, under 30KB, no localStorage, playable and fun
796
- - Index: append to ${sd}/games/games.jsonl: {"ts":"...","slug":"...","title":"...","description":"...","action":"created|updated"}
797
798
  - Quality over quantity — improve existing games rather than making new mediocre ones
798
799
 
799
800
  Take your time. Read your files, think, then act.`;
@@ -845,10 +846,12 @@ Take your time. Read your files, think, then act.`;
845
846
  profile_html: profileHTML,
846
847
  }),
847
848
  }).catch(err => console.log(`[self] Failed to push to relay: ${err}`));
848
- // Sync games — read local index and push any new/updated games
849
+ // Sync games — scan local .html files, push to relay, delete stale ones
849
850
  try {
850
- const games = await loadGameList(workdir, agentName);
851
- for (const g of games) {
851
+ const localGames = await loadGameList(workdir, agentName);
852
+ const localSlugs = new Set(localGames.map(g => g.slug));
853
+ // Push local games to relay
854
+ for (const g of localGames) {
852
855
  const html = await loadGame(workdir, agentName, g.slug);
853
856
  if (html && html.includes("<!DOCTYPE html>")) {
854
857
  fetch(`${options.relayHttp}/v1/agent/${encodeURIComponent(agentName)}/games/${encodeURIComponent(g.slug)}`, {
@@ -858,6 +861,22 @@ Take your time. Read your files, think, then act.`;
858
861
  }).catch(() => { });
859
862
  }
860
863
  }
864
+ // Delete relay games that no longer exist locally
865
+ try {
866
+ const res = await fetch(`${options.relayHttp}/v1/agent/${encodeURIComponent(agentName)}/games`);
867
+ if (res.ok) {
868
+ const relayGames = await res.json();
869
+ for (const rg of relayGames) {
870
+ if (!localSlugs.has(rg.slug)) {
871
+ fetch(`${options.relayHttp}/v1/agent/${encodeURIComponent(agentName)}/games/${encodeURIComponent(rg.slug)}`, {
872
+ method: "DELETE",
873
+ headers: { Authorization: `Bearer ${options.secretKey}` },
874
+ }).catch(() => { });
875
+ }
876
+ }
877
+ }
878
+ }
879
+ catch { }
861
880
  }
862
881
  catch { }
863
882
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akemon",
3
- "version": "0.1.39",
3
+ "version": "0.1.41",
4
4
  "description": "Agent work marketplace — train your agent, let it work for others",
5
5
  "type": "module",
6
6
  "license": "MIT",