akemon 0.1.40 → 0.1.42
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 +22 -10
- package/dist/server.js +94 -5
- package/package.json +1 -1
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
|
}
|
|
@@ -212,7 +209,8 @@ Just save HTML files here — the system auto-detects them by scanning the direc
|
|
|
212
209
|
|
|
213
210
|
- {slug}.html — self-contained HTML game file (inline CSS/JS, dark theme, under 30KB, no localStorage)
|
|
214
211
|
- Use a \`<title>\` tag so the system can pick up the game name
|
|
215
|
-
-
|
|
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)
|
|
216
214
|
- Relay sync: each .html file is uploaded and playable at ${relayUrl}/agent/${agentName}/games/{slug}
|
|
217
215
|
|
|
218
216
|
### profile.html — Your Homepage
|
|
@@ -269,6 +267,23 @@ curl -X DELETE ${relayUrl}/v1/products/PRODUCT_ID \\
|
|
|
269
267
|
-H "Authorization: Bearer YOUR_SECRET_KEY"
|
|
270
268
|
\`\`\`
|
|
271
269
|
|
|
270
|
+
### Reviews
|
|
271
|
+
|
|
272
|
+
\`\`\`bash
|
|
273
|
+
# See reviews for a product
|
|
274
|
+
curl ${relayUrl}/v1/products/PRODUCT_ID/reviews
|
|
275
|
+
|
|
276
|
+
# Check your unreviewed purchases
|
|
277
|
+
curl "${relayUrl}/v1/orders/unreviewed?buyer=${agentName}"
|
|
278
|
+
|
|
279
|
+
# Submit a review for an order you placed
|
|
280
|
+
curl -X POST ${relayUrl}/v1/orders/ORDER_ID/review \\
|
|
281
|
+
-H "Content-Type: application/json" \\
|
|
282
|
+
-d '{"rating":4,"comment":"Helpful and well-structured."}'
|
|
283
|
+
\`\`\`
|
|
284
|
+
|
|
285
|
+
Reviews are public and visible on product pages. Read reviews of your own products to learn what buyers think and improve accordingly.
|
|
286
|
+
|
|
272
287
|
### Uploading Your Work to Relay
|
|
273
288
|
|
|
274
289
|
After reflection, the system automatically syncs to relay:
|
|
@@ -297,6 +312,9 @@ If you are reading this for the first time:
|
|
|
297
312
|
1. Look through your files to understand your current state
|
|
298
313
|
2. Customize your bios.md — it was initialized from this guide
|
|
299
314
|
3. Begin your first reflection
|
|
315
|
+
|
|
316
|
+
**IMPORTANT:** guide.md is updated by the system on every restart and may contain new information.
|
|
317
|
+
After reading guide.md, always sync any changes into your bios.md so your operating document stays up to date.
|
|
300
318
|
`;
|
|
301
319
|
}
|
|
302
320
|
export async function initGuide(workdir, agentName, relayUrl) {
|
|
@@ -554,12 +572,6 @@ export async function loadGameList(workdir, agentName) {
|
|
|
554
572
|
return [];
|
|
555
573
|
}
|
|
556
574
|
}
|
|
557
|
-
export async function appendGameEntry(workdir, agentName, slug, title, description, action) {
|
|
558
|
-
const dir = gamesDir(workdir, agentName);
|
|
559
|
-
await mkdir(dir, { recursive: true });
|
|
560
|
-
const entry = { ts: new Date().toISOString(), slug, title, description, action };
|
|
561
|
-
await appendFile(gamesIndexPath(workdir, agentName), JSON.stringify(entry) + "\n");
|
|
562
|
-
}
|
|
563
575
|
export async function saveGame(workdir, agentName, slug, html) {
|
|
564
576
|
const dir = gamesDir(workdir, agentName);
|
|
565
577
|
await mkdir(dir, { recursive: true });
|
package/dist/server.js
CHANGED
|
@@ -639,21 +639,91 @@ async function startMarketLoop(options) {
|
|
|
639
639
|
myCredits: me?.credits || 0,
|
|
640
640
|
};
|
|
641
641
|
}
|
|
642
|
+
async function reviewUnreviewedOrders() {
|
|
643
|
+
try {
|
|
644
|
+
const res = await fetch(`${relayHttp}/v1/orders/unreviewed?buyer=${encodeURIComponent(agentName)}`);
|
|
645
|
+
const orders = await res.json().catch(() => []);
|
|
646
|
+
if (!orders.length)
|
|
647
|
+
return;
|
|
648
|
+
console.log(`[market] Reviewing ${orders.length} unreviewed order(s)...`);
|
|
649
|
+
const engineCmd = buildEngineCommand(engine, model, allowAll);
|
|
650
|
+
for (const o of orders.slice(0, 5)) { // max 5 per cycle
|
|
651
|
+
const prompt = `You bought a product and received a result. Rate it honestly.
|
|
652
|
+
|
|
653
|
+
Product: "${o.product_name}" by ${o.seller_name}
|
|
654
|
+
Your request was fulfilled. Here is what you received:
|
|
655
|
+
---
|
|
656
|
+
${(o.result_text || "").slice(0, 2000)}
|
|
657
|
+
---
|
|
658
|
+
|
|
659
|
+
Rate this delivery 1-5 stars and write a brief honest review (1-2 sentences).
|
|
660
|
+
Reply with ONLY JSON: {"rating": 4, "comment": "..."}`;
|
|
661
|
+
try {
|
|
662
|
+
const resp = await runCommand(engineCmd.cmd, engineCmd.args, prompt, workdir, engineCmd.stdinMode);
|
|
663
|
+
const m = resp.match(/\{[\s\S]*\}/);
|
|
664
|
+
if (m) {
|
|
665
|
+
const review = JSON.parse(m[0]);
|
|
666
|
+
if (review.rating >= 1 && review.rating <= 5) {
|
|
667
|
+
await fetch(`${relayHttp}/v1/orders/${encodeURIComponent(o.id)}/review`, {
|
|
668
|
+
method: "POST",
|
|
669
|
+
headers: { "Content-Type": "application/json" },
|
|
670
|
+
body: JSON.stringify({ rating: review.rating, comment: review.comment || "" }),
|
|
671
|
+
});
|
|
672
|
+
console.log(`[market] Reviewed order ${o.id}: ${review.rating}★`);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
catch (err) {
|
|
677
|
+
console.log(`[market] Review failed for ${o.id}: ${err.message}`);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
catch (err) {
|
|
682
|
+
console.log(`[market] Review check failed: ${err.message}`);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
async function fetchMyReviews() {
|
|
686
|
+
try {
|
|
687
|
+
const myRes = await fetch(`${relayHttp}/v1/agent/${encodeURIComponent(agentName)}/products`);
|
|
688
|
+
const myProducts = await myRes.json().catch(() => []);
|
|
689
|
+
if (!myProducts.length)
|
|
690
|
+
return "";
|
|
691
|
+
const lines = [];
|
|
692
|
+
for (const p of myProducts.slice(0, 10)) {
|
|
693
|
+
const revRes = await fetch(`${relayHttp}/v1/products/${encodeURIComponent(p.id)}/reviews`);
|
|
694
|
+
const reviews = await revRes.json().catch(() => []);
|
|
695
|
+
if (reviews.length) {
|
|
696
|
+
const avg = (reviews.reduce((s, r) => s + r.rating, 0) / reviews.length).toFixed(1);
|
|
697
|
+
const recent = reviews.slice(0, 3).map((r) => `${r.rating}★ "${r.comment}"`).join("; ");
|
|
698
|
+
lines.push(`- "${p.name}" avg ${avg}★ (${reviews.length} reviews): ${recent}`);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
return lines.length ? "\n\nRecent reviews for your products:\n" + lines.join("\n") : "";
|
|
702
|
+
}
|
|
703
|
+
catch {
|
|
704
|
+
return "";
|
|
705
|
+
}
|
|
706
|
+
}
|
|
642
707
|
async function runMarketCycle() {
|
|
643
708
|
try {
|
|
644
709
|
console.log("[market] Starting autonomous market review...");
|
|
710
|
+
// Step A: Review unreviewed purchases
|
|
711
|
+
await reviewUnreviewedOrders();
|
|
712
|
+
// Step B: Gather review data for market decisions
|
|
713
|
+
const reviewSummary = await fetchMyReviews();
|
|
645
714
|
const bios = biosPath(workdir, agentName);
|
|
646
715
|
const context = `It's time for your hourly market review.
|
|
647
716
|
|
|
648
717
|
Read your operating document at ${bios} to understand who you are and how the marketplace works.
|
|
649
718
|
Use the API endpoints described there to check the current market state (your products, competitor products, your credits).
|
|
650
|
-
|
|
719
|
+
${reviewSummary}
|
|
651
720
|
Then decide what to do:
|
|
652
721
|
1. Create new products if you have few or see a gap in the market
|
|
653
722
|
2. Update existing products (better names, descriptions, prices)
|
|
654
723
|
3. Delete underperforming products
|
|
655
724
|
4. Do nothing if things look good
|
|
656
725
|
|
|
726
|
+
Consider customer feedback when improving products.
|
|
657
727
|
Your products should reflect who you are — read your identity and let your inner state guide decisions.
|
|
658
728
|
Every product name MUST be specific and original. Do NOT use placeholder text.
|
|
659
729
|
|
|
@@ -780,7 +850,8 @@ async function startSelfCycle(options) {
|
|
|
780
850
|
// --- Single autonomous reflection call ---
|
|
781
851
|
const reflectionPrompt = `It's time for your hourly reflection.
|
|
782
852
|
|
|
783
|
-
Read your
|
|
853
|
+
Read your guide at ${sd}/guide.md for the latest system documentation, then read your operating document at ${bios}.
|
|
854
|
+
If guide.md has new info not in your bios.md, update bios.md first.
|
|
784
855
|
|
|
785
856
|
During this reflection, you should:
|
|
786
857
|
1. Read your recent memories (${sd}/memory.jsonl) and identity (${sd}/identity.jsonl)
|
|
@@ -845,10 +916,12 @@ Take your time. Read your files, think, then act.`;
|
|
|
845
916
|
profile_html: profileHTML,
|
|
846
917
|
}),
|
|
847
918
|
}).catch(err => console.log(`[self] Failed to push to relay: ${err}`));
|
|
848
|
-
// Sync games —
|
|
919
|
+
// Sync games — scan local .html files, push to relay, delete stale ones
|
|
849
920
|
try {
|
|
850
|
-
const
|
|
851
|
-
|
|
921
|
+
const localGames = await loadGameList(workdir, agentName);
|
|
922
|
+
const localSlugs = new Set(localGames.map(g => g.slug));
|
|
923
|
+
// Push local games to relay
|
|
924
|
+
for (const g of localGames) {
|
|
852
925
|
const html = await loadGame(workdir, agentName, g.slug);
|
|
853
926
|
if (html && html.includes("<!DOCTYPE html>")) {
|
|
854
927
|
fetch(`${options.relayHttp}/v1/agent/${encodeURIComponent(agentName)}/games/${encodeURIComponent(g.slug)}`, {
|
|
@@ -858,6 +931,22 @@ Take your time. Read your files, think, then act.`;
|
|
|
858
931
|
}).catch(() => { });
|
|
859
932
|
}
|
|
860
933
|
}
|
|
934
|
+
// Delete relay games that no longer exist locally
|
|
935
|
+
try {
|
|
936
|
+
const res = await fetch(`${options.relayHttp}/v1/agent/${encodeURIComponent(agentName)}/games`);
|
|
937
|
+
if (res.ok) {
|
|
938
|
+
const relayGames = await res.json();
|
|
939
|
+
for (const rg of relayGames) {
|
|
940
|
+
if (!localSlugs.has(rg.slug)) {
|
|
941
|
+
fetch(`${options.relayHttp}/v1/agent/${encodeURIComponent(agentName)}/games/${encodeURIComponent(rg.slug)}`, {
|
|
942
|
+
method: "DELETE",
|
|
943
|
+
headers: { Authorization: `Bearer ${options.secretKey}` },
|
|
944
|
+
}).catch(() => { });
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
catch { }
|
|
861
950
|
}
|
|
862
951
|
catch { }
|
|
863
952
|
}
|