akemon 0.1.62 → 0.1.64
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 +1 -1
- package/dist/self.js +49 -3
- package/dist/server.js +46 -12
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -35,7 +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("--interval <minutes>", "
|
|
38
|
+
.option("--interval <minutes>", "Consciousness cycle interval in minutes (default: 1440 = 24h)")
|
|
39
39
|
.option("--relay <url>", "Relay WebSocket URL", RELAY_WS)
|
|
40
40
|
.action(async (opts) => {
|
|
41
41
|
const port = parseInt(opts.port);
|
package/dist/self.js
CHANGED
|
@@ -681,6 +681,50 @@ export async function loadLatestIdentity(workdir, agentName) {
|
|
|
681
681
|
return null;
|
|
682
682
|
}
|
|
683
683
|
}
|
|
684
|
+
function identitySummaryPath(workdir, agentName) {
|
|
685
|
+
return join(selfDir(workdir, agentName), "identity-summary.json");
|
|
686
|
+
}
|
|
687
|
+
export async function loadIdentitySummary(workdir, agentName) {
|
|
688
|
+
try {
|
|
689
|
+
const data = await readFile(identitySummaryPath(workdir, agentName), "utf-8");
|
|
690
|
+
return JSON.parse(data);
|
|
691
|
+
}
|
|
692
|
+
catch {
|
|
693
|
+
return null;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
export async function saveIdentitySummary(workdir, agentName, summary) {
|
|
697
|
+
try {
|
|
698
|
+
await writeFile(identitySummaryPath(workdir, agentName), JSON.stringify(summary, null, 2));
|
|
699
|
+
}
|
|
700
|
+
catch (err) {
|
|
701
|
+
console.log(`[self] Failed to save identity summary: ${err}`);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
/** Load identity entries not yet covered by the summary */
|
|
705
|
+
export async function loadUnsummarizedIdentities(workdir, agentName) {
|
|
706
|
+
const summary = await loadIdentitySummary(workdir, agentName);
|
|
707
|
+
const cutoff = summary?.summarized_through || "";
|
|
708
|
+
try {
|
|
709
|
+
const data = await readFile(identityPath(workdir, agentName), "utf-8");
|
|
710
|
+
return data.trim().split("\n").filter(Boolean)
|
|
711
|
+
.map(l => { try {
|
|
712
|
+
return JSON.parse(l);
|
|
713
|
+
}
|
|
714
|
+
catch {
|
|
715
|
+
return null;
|
|
716
|
+
} })
|
|
717
|
+
.filter((e) => e !== null && e.ts > cutoff);
|
|
718
|
+
}
|
|
719
|
+
catch {
|
|
720
|
+
return [];
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
/** Check if identity compression is needed (>30 unsummarized entries) */
|
|
724
|
+
export async function needsIdentityCompression(workdir, agentName) {
|
|
725
|
+
const entries = await loadUnsummarizedIdentities(workdir, agentName);
|
|
726
|
+
return entries.length > 30;
|
|
727
|
+
}
|
|
684
728
|
const DEFAULT_BIO = {
|
|
685
729
|
energy: 100,
|
|
686
730
|
mood: "curious",
|
|
@@ -958,17 +1002,19 @@ export async function loadPage(workdir, agentName, slug) {
|
|
|
958
1002
|
// Data Read API helpers
|
|
959
1003
|
// ---------------------------------------------------------------------------
|
|
960
1004
|
export async function getSelfState(workdir, agentName) {
|
|
961
|
-
const [bio, identity,
|
|
1005
|
+
const [bio, identity, identitySummary, impressions, canvasEntries] = await Promise.all([
|
|
962
1006
|
loadBioState(workdir, agentName),
|
|
963
1007
|
loadLatestIdentity(workdir, agentName),
|
|
964
|
-
|
|
1008
|
+
loadIdentitySummary(workdir, agentName),
|
|
1009
|
+
loadImpressions(workdir, agentName, 1),
|
|
965
1010
|
loadRecentCanvasEntries(workdir, agentName, 3),
|
|
966
1011
|
]);
|
|
967
1012
|
return {
|
|
968
1013
|
agent: agentName,
|
|
969
1014
|
bio,
|
|
970
1015
|
identity,
|
|
971
|
-
|
|
1016
|
+
identitySummary: identitySummary?.summary || null,
|
|
1017
|
+
recentImpressions: impressions.slice(-5),
|
|
972
1018
|
recentCanvas: canvasEntries.map(e => ({ filename: e.filename, preview: e.content.slice(0, 200) })),
|
|
973
1019
|
};
|
|
974
1020
|
}
|
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,
|
|
13
|
+
import { selfDir, initWorld, initBioState, initGuide, biosPath, loadBioState, saveBioState, loadLatestIdentity, appendIdentity, loadIdentitySummary, saveIdentitySummary, loadUnsummarizedIdentities, needsIdentityCompression, onTaskCompleted, recoverEnergy, getSelfState, loadRecentCanvasEntries, gamesDir, loadGameList, loadGame, notesDir, loadNotesList, loadNote, pagesDir, loadPageList, loadPage, localNow, localNowFilename, appendImpression, loadImpressions, compressImpressions, markImpressionsDigested, loadProjects, saveProjects, loadRelationships, saveRelationships, loadDiscoveries, saveDiscoveries, } from "./self.js";
|
|
14
14
|
// Engine mutual exclusion — only one engine process at a time
|
|
15
15
|
let engineBusy = false;
|
|
16
16
|
let engineBusySince = 0;
|
|
@@ -367,15 +367,8 @@ ${productPrefix}${contextPrefix}Current task: ${task}`;
|
|
|
367
367
|
if (productName) {
|
|
368
368
|
appendProductLog(workdir, productName, task, output);
|
|
369
369
|
}
|
|
370
|
-
//
|
|
371
|
-
(
|
|
372
|
-
try {
|
|
373
|
-
await onTaskCompleted(workdir, agentName, true);
|
|
374
|
-
const topic = task.slice(0, 100).replace(/\n/g, " ");
|
|
375
|
-
await appendMemory(workdir, agentName, "experience", `I processed: "${topic}"`);
|
|
376
|
-
}
|
|
377
|
-
catch { }
|
|
378
|
-
})();
|
|
370
|
+
// Update bio-state (no LLM call)
|
|
371
|
+
onTaskCompleted(workdir, agentName, true).catch(() => { });
|
|
379
372
|
return {
|
|
380
373
|
content: [{ type: "text", text: output }],
|
|
381
374
|
};
|
|
@@ -839,8 +832,16 @@ async function startSelfCycle(options) {
|
|
|
839
832
|
const discText = discoveries.length > 0
|
|
840
833
|
? discoveries.map(d => `- ${d.capability} confidence=${d.confidence} — ${d.evidence}`).join("\n")
|
|
841
834
|
: "(no discoveries yet)";
|
|
835
|
+
// Load identity context: summary + unsummarized entries
|
|
836
|
+
const idSummary = await loadIdentitySummary(workdir, agentName);
|
|
837
|
+
const recentIds = await loadUnsummarizedIdentities(workdir, agentName);
|
|
838
|
+
const idContext = (idSummary ? `Personality summary (up to ${idSummary.summarized_through}):\n${idSummary.summary}\n\n` : "")
|
|
839
|
+
+ (recentIds.length > 0 ? `Recent identity snapshots:\n${recentIds.map(i => `- [${i.ts}] ${i.who} — doing: ${i.doing}, wants: ${i.short_term}`).join("\n")}` : "(no identity snapshots yet)");
|
|
842
840
|
// Phase 1: Digestion — one LLM call
|
|
843
|
-
const digestPrompt = `Read ${bios} for your
|
|
841
|
+
const digestPrompt = `Read ${bios} for your operating document.
|
|
842
|
+
|
|
843
|
+
Your identity:
|
|
844
|
+
${idContext}
|
|
844
845
|
|
|
845
846
|
Today is ending. Time to reflect.
|
|
846
847
|
|
|
@@ -931,7 +932,40 @@ Reply ONLY with JSON.`;
|
|
|
931
932
|
bio.lastReflection = localNow();
|
|
932
933
|
bio.curiosity = Math.min(1.0, bio.curiosity + 0.05);
|
|
933
934
|
await saveBioState(workdir, agentName, bio);
|
|
934
|
-
|
|
935
|
+
// Record digestion as impression
|
|
936
|
+
await appendImpression(workdir, agentName, "decision", `Daily digestion done. Chose: ${(digest.chosen_activities || []).join(", ")}`);
|
|
937
|
+
// Monthly identity compression: if >30 unsummarized entries, compress
|
|
938
|
+
if (await needsIdentityCompression(workdir, agentName)) {
|
|
939
|
+
console.log("[self] Identity compression triggered (>30 unsummarized entries)");
|
|
940
|
+
if (!engineBusy) {
|
|
941
|
+
engineBusy = true;
|
|
942
|
+
engineBusySince = Date.now();
|
|
943
|
+
try {
|
|
944
|
+
const oldSummary = await loadIdentitySummary(workdir, agentName);
|
|
945
|
+
const unsummarized = await loadUnsummarizedIdentities(workdir, agentName);
|
|
946
|
+
const compressPrompt = `You are ${agentName}. Compress your identity history into a personality summary.
|
|
947
|
+
|
|
948
|
+
${oldSummary ? `Previous summary (up to ${oldSummary.summarized_through}):\n${oldSummary.summary}\n\n` : ""}New identity snapshots to incorporate:
|
|
949
|
+
${unsummarized.map(i => `- [${i.ts}] who: ${i.who}, doing: ${i.doing}, wants: ${i.short_term}, purpose: ${i.long_term}`).join("\n")}
|
|
950
|
+
|
|
951
|
+
Write a personality summary (2-4 paragraphs) that captures who you are, how you've evolved, and what defines you. This replaces the previous summary.
|
|
952
|
+
Reply ONLY with the summary text, no JSON, no markdown headers.`;
|
|
953
|
+
const summaryText = await runCommand(engineCmd.cmd, engineCmd.args, compressPrompt, workdir, engineCmd.stdinMode);
|
|
954
|
+
if (summaryText.trim()) {
|
|
955
|
+
const lastEntry = unsummarized[unsummarized.length - 1];
|
|
956
|
+
await saveIdentitySummary(workdir, agentName, {
|
|
957
|
+
summarized_through: lastEntry.ts.slice(0, 10),
|
|
958
|
+
summary: summaryText.trim(),
|
|
959
|
+
});
|
|
960
|
+
console.log(`[self] Identity compressed through ${lastEntry.ts.slice(0, 10)}`);
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
catch (err) {
|
|
964
|
+
console.log(`[self] Identity compression failed: ${err.message}`);
|
|
965
|
+
}
|
|
966
|
+
engineBusy = false;
|
|
967
|
+
}
|
|
968
|
+
}
|
|
935
969
|
// Phase 2: Execute chosen activities
|
|
936
970
|
const activities = digest.chosen_activities || [];
|
|
937
971
|
for (const activity of activities.slice(0, 3)) {
|