0xkobold 0.4.3 ā 0.5.0
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/README.md +226 -383
- package/dist/package.json +13 -4
- package/dist/src/agent/DraconicCapabilityRouter.js +556 -0
- package/dist/src/agent/DraconicCapabilityRouter.js.map +1 -0
- package/dist/src/agent/DraconicErrorClassifier.js +606 -0
- package/dist/src/agent/DraconicErrorClassifier.js.map +1 -0
- package/dist/src/agent/DraconicRunRegistry.js +460 -0
- package/dist/src/agent/DraconicRunRegistry.js.map +1 -0
- package/dist/src/agent/DraconicTokenPredictor.js +500 -0
- package/dist/src/agent/DraconicTokenPredictor.js.map +1 -0
- package/dist/src/agent/embedded-runner.js +3 -2
- package/dist/src/agent/embedded-runner.js.map +1 -1
- package/dist/src/cli/commands/doctor.js +199 -0
- package/dist/src/cli/commands/doctor.js.map +1 -0
- package/dist/src/cli/commands/migrate-from-openclaw.js +39 -0
- package/dist/src/cli/commands/migrate-from-openclaw.js.map +1 -0
- package/dist/src/cli/commands/migrate.js +6 -4
- package/dist/src/cli/commands/migrate.js.map +1 -1
- package/dist/src/cli/program.js +3 -1
- package/dist/src/cli/program.js.map +1 -1
- package/dist/src/config/unified-config.js +195 -0
- package/dist/src/config/unified-config.js.map +1 -0
- package/dist/src/cron/notifications.js +1 -1
- package/dist/src/cron/notifications.js.map +1 -1
- package/dist/src/cron/runner.js +9 -3
- package/dist/src/cron/runner.js.map +1 -1
- package/dist/src/event-bus/index.js +3 -1
- package/dist/src/event-bus/index.js.map +1 -1
- package/dist/src/extensions/community/draconic-messenger-wrapper.js +35 -0
- package/dist/src/extensions/community/draconic-messenger-wrapper.js.map +1 -0
- package/dist/src/extensions/community/draconic-subagents-wrapper.js +115 -0
- package/dist/src/extensions/community/draconic-subagents-wrapper.js.map +1 -0
- package/dist/src/extensions/core/compaction-safeguard-v2.js +95 -0
- package/dist/src/extensions/core/compaction-safeguard-v2.js.map +1 -0
- package/dist/src/extensions/core/compaction-safeguard.js +206 -137
- package/dist/src/extensions/core/compaction-safeguard.js.map +1 -1
- package/dist/src/extensions/core/config-extension.js +122 -0
- package/dist/src/extensions/core/config-extension.js.map +1 -0
- package/dist/src/extensions/core/draconic-hoard-extension.js +194 -0
- package/dist/src/extensions/core/draconic-hoard-extension.js.map +1 -0
- package/dist/src/extensions/core/draconic-lair-extension.js +146 -0
- package/dist/src/extensions/core/draconic-lair-extension.js.map +1 -0
- package/dist/src/extensions/core/draconic-safety-extension.js +402 -0
- package/dist/src/extensions/core/draconic-safety-extension.js.map +1 -0
- package/dist/src/extensions/core/ext-manager.js +40 -0
- package/dist/src/extensions/core/ext-manager.js.map +1 -0
- package/dist/src/extensions/core/gateway-extension.js +413 -624
- package/dist/src/extensions/core/gateway-extension.js.map +1 -1
- package/dist/src/extensions/core/generative-agents-extension.js +704 -0
- package/dist/src/extensions/core/generative-agents-extension.js.map +1 -0
- package/dist/src/extensions/core/memory-bootstrap-extension.js +279 -0
- package/dist/src/extensions/core/memory-bootstrap-extension.js.map +1 -0
- package/dist/src/extensions/core/ollama-extension.js +442 -0
- package/dist/src/extensions/core/ollama-extension.js.map +1 -0
- package/dist/src/extensions/core/ollama-router-extension.js +34 -93
- package/dist/src/extensions/core/ollama-router-extension.js.map +1 -1
- package/dist/src/extensions/core/perennial-memory-extension.js +5 -2
- package/dist/src/extensions/core/perennial-memory-extension.js.map +1 -1
- package/dist/src/extensions/core/persona-loader-extension.js +41 -15
- package/dist/src/extensions/core/persona-loader-extension.js.map +1 -1
- package/dist/src/extensions/core/pi-notify-extension.js +6 -0
- package/dist/src/extensions/core/pi-notify-extension.js.map +1 -1
- package/dist/src/extensions/core/session-bridge-extension.js +8 -72
- package/dist/src/extensions/core/session-bridge-extension.js.map +1 -1
- package/dist/src/extensions/core/tui-integration-extension-fixed.js +3 -0
- package/dist/src/extensions/core/tui-integration-extension-fixed.js.map +1 -0
- package/dist/src/extensions/core/tui-integration-extension.js +984 -0
- package/dist/src/extensions/core/tui-integration-extension.js.map +1 -0
- package/dist/src/gateway/persistence/AgentStore.js +399 -0
- package/dist/src/gateway/persistence/AgentStore.js.map +1 -0
- package/dist/src/gateway/persistence/index.js +9 -0
- package/dist/src/gateway/persistence/index.js.map +1 -0
- package/dist/src/hoard/DraconicHoardSystem.js +465 -0
- package/dist/src/hoard/DraconicHoardSystem.js.map +1 -0
- package/dist/src/index.js +7 -5
- package/dist/src/index.js.map +1 -1
- package/dist/src/infra/DraconicConnectionPool.js +492 -0
- package/dist/src/infra/DraconicConnectionPool.js.map +1 -0
- package/dist/src/lair/DraconicLairSystem.js +387 -0
- package/dist/src/lair/DraconicLairSystem.js.map +1 -0
- package/dist/src/llm/ollama.js +143 -99
- package/dist/src/llm/ollama.js.map +1 -1
- package/dist/src/migration/openclaw.js +5 -5
- package/dist/src/migration/openclaw.js.map +1 -1
- package/dist/src/pi-config.js +52 -27
- package/dist/src/pi-config.js.map +1 -1
- package/dist/src/sessions/SessionManager.js +416 -0
- package/dist/src/sessions/SessionManager.js.map +1 -0
- package/dist/src/sessions/SessionStore.js +580 -0
- package/dist/src/sessions/SessionStore.js.map +1 -0
- package/dist/src/sessions/UnifiedSessionBridge.js +394 -0
- package/dist/src/sessions/UnifiedSessionBridge.js.map +1 -0
- package/dist/src/sessions/index.js +15 -0
- package/dist/src/sessions/index.js.map +1 -0
- package/dist/src/sessions/migration/index.js +156 -0
- package/dist/src/sessions/migration/index.js.map +1 -0
- package/dist/src/sessions/types.js +8 -0
- package/dist/src/sessions/types.js.map +1 -0
- package/dist/src/skills/framework.js +1 -1
- package/dist/src/skills/framework.js.map +1 -1
- package/dist/src/tui/commands/final-functions.js +39 -0
- package/dist/src/tui/commands/final-functions.js.map +1 -0
- package/dist/src/tui/commands/natural-language-commands.js +231 -0
- package/dist/src/tui/commands/natural-language-commands.js.map +1 -0
- package/dist/src/tui/commands/orchestration-commands.js +340 -0
- package/dist/src/tui/commands/orchestration-commands.js.map +1 -0
- package/dist/src/tui/commands/orchestration-final-section.js +84 -0
- package/dist/src/tui/commands/orchestration-final-section.js.map +1 -0
- package/dist/src/tui/components/agent-tree-overlay.js +210 -0
- package/dist/src/tui/components/agent-tree-overlay.js.map +1 -0
- package/dist/src/tui/components/agent-tree-panel.js +229 -0
- package/dist/src/tui/components/agent-tree-panel.js.map +1 -0
- package/dist/src/tui/components/sidebar.js +82 -0
- package/dist/src/tui/components/sidebar.js.map +1 -0
- package/dist/src/tui/components/status-bar.js +115 -0
- package/dist/src/tui/components/status-bar.js.map +1 -0
- package/dist/src/tui/components/tree-header.js +85 -0
- package/dist/src/tui/components/tree-header.js.map +1 -0
- package/dist/src/tui/draconic-tui.js +291 -0
- package/dist/src/tui/draconic-tui.js.map +1 -0
- package/dist/src/tui/index.js +93 -0
- package/dist/src/tui/index.js.map +1 -0
- package/dist/src/tui/pi-tui-integration.js +260 -0
- package/dist/src/tui/pi-tui-integration.js.map +1 -0
- package/dist/src/utils/nl-patterns.js +145 -0
- package/dist/src/utils/nl-patterns.js.map +1 -0
- package/package.json +13 -4
- package/scripts/migrate-from-openclaw.sh +498 -0
- package/HEARTBEAT.md +0 -121
- package/USAGE.md +0 -191
|
@@ -0,0 +1,704 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* š§ Generative Agents Extension
|
|
3
|
+
*
|
|
4
|
+
* Implements Stanford HCI research: "Generative Agents: Interactive Simulacra of Human Behavior"
|
|
5
|
+
* Adds memory stream, reflection, and planning to 0xKobold agents.
|
|
6
|
+
*
|
|
7
|
+
* Requires: perennial-memory-extension (provides semantic storage)
|
|
8
|
+
*/
|
|
9
|
+
import { Type } from "@sinclair/typebox";
|
|
10
|
+
import { Database } from "bun:sqlite";
|
|
11
|
+
import { randomUUID } from "node:crypto";
|
|
12
|
+
import * as path from "node:path";
|
|
13
|
+
import { homedir } from "node:os";
|
|
14
|
+
const GENERATIVE_DIR = path.join(homedir(), ".0xkobold", "generative");
|
|
15
|
+
const DB_PATH = path.join(GENERATIVE_DIR, "agents.db");
|
|
16
|
+
const EMBEDDING_DIM = 768;
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Database
|
|
19
|
+
// ============================================================================
|
|
20
|
+
function initGenerativeDB() {
|
|
21
|
+
const db = new Database(DB_PATH);
|
|
22
|
+
db.exec("PRAGMA journal_mode = WAL;");
|
|
23
|
+
db.exec(`
|
|
24
|
+
CREATE TABLE IF NOT EXISTS agents (
|
|
25
|
+
id TEXT PRIMARY KEY,
|
|
26
|
+
name TEXT NOT NULL,
|
|
27
|
+
traits TEXT NOT NULL, -- JSON array
|
|
28
|
+
current_location TEXT DEFAULT 'home',
|
|
29
|
+
current_plan_id TEXT,
|
|
30
|
+
observation_count INTEGER DEFAULT 0,
|
|
31
|
+
last_reflection_at TEXT,
|
|
32
|
+
memory_count INTEGER DEFAULT 0,
|
|
33
|
+
created_at TEXT NOT NULL
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
CREATE TABLE IF NOT EXISTS memory_stream (
|
|
37
|
+
id TEXT PRIMARY KEY,
|
|
38
|
+
timestamp TEXT NOT NULL,
|
|
39
|
+
content TEXT NOT NULL,
|
|
40
|
+
type TEXT NOT NULL, -- observation, thought, action, reflection
|
|
41
|
+
importance REAL NOT NULL,
|
|
42
|
+
agent_id TEXT NOT NULL,
|
|
43
|
+
session_id TEXT,
|
|
44
|
+
location TEXT,
|
|
45
|
+
people TEXT, -- JSON array
|
|
46
|
+
embedding BLOB, -- 768 floats
|
|
47
|
+
metadata TEXT, -- JSON
|
|
48
|
+
FOREIGN KEY (agent_id) REFERENCES agents(id)
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
CREATE TABLE IF NOT EXISTS reflections (
|
|
52
|
+
id TEXT PRIMARY KEY,
|
|
53
|
+
timestamp TEXT NOT NULL,
|
|
54
|
+
content TEXT NOT NULL,
|
|
55
|
+
insight TEXT NOT NULL,
|
|
56
|
+
agent_id TEXT NOT NULL,
|
|
57
|
+
evidence TEXT NOT NULL, -- JSON array of memory IDs
|
|
58
|
+
depth INTEGER NOT NULL,
|
|
59
|
+
importance REAL NOT NULL,
|
|
60
|
+
FOREIGN KEY (agent_id) REFERENCES agents(id)
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
CREATE TABLE IF NOT EXISTS plans (
|
|
64
|
+
id TEXT PRIMARY KEY,
|
|
65
|
+
timestamp TEXT NOT NULL,
|
|
66
|
+
content TEXT NOT NULL,
|
|
67
|
+
type TEXT NOT NULL, -- daily, action, conversation, project
|
|
68
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
69
|
+
agent_id TEXT NOT NULL,
|
|
70
|
+
parent_plan_id TEXT,
|
|
71
|
+
sub_plan_ids TEXT, -- JSON array
|
|
72
|
+
start_time TEXT,
|
|
73
|
+
end_time TEXT,
|
|
74
|
+
location TEXT,
|
|
75
|
+
FOREIGN KEY (agent_id) REFERENCES agents(id),
|
|
76
|
+
FOREIGN KEY (parent_plan_id) REFERENCES plans(id)
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
CREATE INDEX IF NOT EXISTS idx_memory_agent ON memory_stream(agent_id);
|
|
80
|
+
CREATE INDEX IF NOT EXISTS idx_memory_timestamp ON memory_stream(timestamp);
|
|
81
|
+
CREATE INDEX IF NOT EXISTS idx_memory_type ON memory_stream(type);
|
|
82
|
+
CREATE INDEX IF NOT EXISTS idx_reflections_agent ON reflections(agent_id);
|
|
83
|
+
CREATE INDEX IF NOT EXISTS idx_plans_agent ON plans(agent_id);
|
|
84
|
+
CREATE INDEX IF NOT EXISTS idx_plans_status ON plans(status);
|
|
85
|
+
`);
|
|
86
|
+
return db;
|
|
87
|
+
}
|
|
88
|
+
// ============================================================================
|
|
89
|
+
// Importance Scoring
|
|
90
|
+
// ============================================================================
|
|
91
|
+
function calculateImportance(content) {
|
|
92
|
+
const highImportance = [
|
|
93
|
+
"decided", "promised", "committed", "agreed", "disagreed",
|
|
94
|
+
"failed", "succeeded", "launched", "shipped", "broke",
|
|
95
|
+
"learned", "realized", "discovered", "fixed", "solved",
|
|
96
|
+
"argued", "conflict", "victory", "milestone", "achievement"
|
|
97
|
+
];
|
|
98
|
+
const lowImportance = [
|
|
99
|
+
"walked", "sat", "stood", "looked", "waited",
|
|
100
|
+
"breathed", "passed", "glanced", "noticed"
|
|
101
|
+
];
|
|
102
|
+
let score = 5;
|
|
103
|
+
const words = content.toLowerCase().split(/\s+/);
|
|
104
|
+
for (const word of words) {
|
|
105
|
+
if (highImportance.some(h => word.includes(h)))
|
|
106
|
+
score += 1;
|
|
107
|
+
if (lowImportance.some(l => word.includes(l)))
|
|
108
|
+
score -= 1;
|
|
109
|
+
}
|
|
110
|
+
// Boost for technical/code content
|
|
111
|
+
if (/\b(function|class|component|bug|error|deploy|build)\b/.test(content)) {
|
|
112
|
+
score += 1;
|
|
113
|
+
}
|
|
114
|
+
return Math.max(1, Math.min(10, score));
|
|
115
|
+
}
|
|
116
|
+
// ============================================================================
|
|
117
|
+
// Generative Agent Implementation
|
|
118
|
+
// ============================================================================
|
|
119
|
+
class GenerativeAgent {
|
|
120
|
+
id;
|
|
121
|
+
name;
|
|
122
|
+
traits;
|
|
123
|
+
db;
|
|
124
|
+
llm;
|
|
125
|
+
constructor(id, name, traits, db, llm) {
|
|
126
|
+
this.id = id;
|
|
127
|
+
this.name = name;
|
|
128
|
+
this.traits = traits;
|
|
129
|
+
this.db = db;
|
|
130
|
+
this.llm = llm;
|
|
131
|
+
}
|
|
132
|
+
// Add observation to memory stream
|
|
133
|
+
async observe(content, metadata) {
|
|
134
|
+
const importance = calculateImportance(content);
|
|
135
|
+
const entry = {
|
|
136
|
+
id: randomUUID(),
|
|
137
|
+
timestamp: new Date().toISOString(),
|
|
138
|
+
content,
|
|
139
|
+
type: "observation",
|
|
140
|
+
importance,
|
|
141
|
+
agentId: this.id,
|
|
142
|
+
location: metadata?.location,
|
|
143
|
+
people: metadata?.people,
|
|
144
|
+
sessionId: metadata?.sessionId,
|
|
145
|
+
};
|
|
146
|
+
// Try to get embedding from perennial memory (via Ollama)
|
|
147
|
+
try {
|
|
148
|
+
const embedding = await this.llm.getEmbedding(content);
|
|
149
|
+
entry.embedding = embedding;
|
|
150
|
+
}
|
|
151
|
+
catch { }
|
|
152
|
+
this.db.query(`
|
|
153
|
+
INSERT INTO memory_stream (id, timestamp, content, type, importance, agent_id, session_id, location, people, embedding, metadata)
|
|
154
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
155
|
+
`).run(entry.id, entry.timestamp, entry.content, entry.type, entry.importance, entry.agentId, entry.sessionId || null, entry.location || null, entry.people ? JSON.stringify(entry.people) : null, entry.embedding ? Buffer.from(new Float32Array(entry.embedding).buffer) : null, metadata ? JSON.stringify(metadata) : null);
|
|
156
|
+
// Update observation count
|
|
157
|
+
this.db.query(`UPDATE agents SET observation_count = observation_count + 1 WHERE id = ?`).run(this.id);
|
|
158
|
+
// Trigger reflection if threshold reached
|
|
159
|
+
const count = this.db.query(`SELECT observation_count FROM agents WHERE id = ?`).get(this.id);
|
|
160
|
+
if (count && count.observation_count % 20 === 0) {
|
|
161
|
+
await this.generateReflections();
|
|
162
|
+
}
|
|
163
|
+
return entry;
|
|
164
|
+
}
|
|
165
|
+
// Add thought (internal)
|
|
166
|
+
async think(content) {
|
|
167
|
+
const importance = calculateImportance(content);
|
|
168
|
+
const entry = {
|
|
169
|
+
id: randomUUID(),
|
|
170
|
+
timestamp: new Date().toISOString(),
|
|
171
|
+
content,
|
|
172
|
+
type: "thought",
|
|
173
|
+
importance,
|
|
174
|
+
agentId: this.id,
|
|
175
|
+
};
|
|
176
|
+
this.db.query(`
|
|
177
|
+
INSERT INTO memory_stream (id, timestamp, content, type, importance, agent_id)
|
|
178
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
179
|
+
`).run(entry.id, entry.timestamp, entry.content, entry.type, entry.importance, entry.agentId);
|
|
180
|
+
return entry;
|
|
181
|
+
}
|
|
182
|
+
// Add action to memory stream
|
|
183
|
+
async act(content) {
|
|
184
|
+
const importance = calculateImportance(content);
|
|
185
|
+
const entry = {
|
|
186
|
+
id: randomUUID(),
|
|
187
|
+
timestamp: new Date().toISOString(),
|
|
188
|
+
content,
|
|
189
|
+
type: "action",
|
|
190
|
+
importance,
|
|
191
|
+
agentId: this.id,
|
|
192
|
+
};
|
|
193
|
+
this.db.query(`
|
|
194
|
+
INSERT INTO memory_stream (id, timestamp, content, type, importance, agent_id)
|
|
195
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
196
|
+
`).run(entry.id, entry.timestamp, entry.content, entry.type, entry.importance, entry.agentId);
|
|
197
|
+
return entry;
|
|
198
|
+
}
|
|
199
|
+
// Retrieve relevant memories
|
|
200
|
+
async retrieveMemories(context, k = 10) {
|
|
201
|
+
const now = Date.now();
|
|
202
|
+
// Get recent memories with importance weighting
|
|
203
|
+
const rows = this.db.query(`
|
|
204
|
+
SELECT id, timestamp, content, type, importance, location, people
|
|
205
|
+
FROM memory_stream
|
|
206
|
+
WHERE agent_id = ?
|
|
207
|
+
ORDER BY timestamp DESC
|
|
208
|
+
LIMIT 200
|
|
209
|
+
`).all(this.id);
|
|
210
|
+
// Calculate scores (recency + importance + relevance)
|
|
211
|
+
const scored = rows.map(row => {
|
|
212
|
+
const hoursAgo = (now - new Date(row.timestamp).getTime()) / (1000 * 60 * 60);
|
|
213
|
+
const recency = Math.exp(-0.005 * hoursAgo); // Decay
|
|
214
|
+
const relevance = this.calculateRelevance(row.content, context);
|
|
215
|
+
return {
|
|
216
|
+
memory: {
|
|
217
|
+
id: row.id,
|
|
218
|
+
timestamp: row.timestamp,
|
|
219
|
+
content: row.content,
|
|
220
|
+
type: row.type,
|
|
221
|
+
importance: row.importance,
|
|
222
|
+
agentId: this.id,
|
|
223
|
+
location: row.location,
|
|
224
|
+
people: row.people ? JSON.parse(row.people) : undefined,
|
|
225
|
+
},
|
|
226
|
+
score: (recency * 0.3) + (row.importance / 10 * 0.3) + (relevance * 0.4),
|
|
227
|
+
};
|
|
228
|
+
});
|
|
229
|
+
return scored
|
|
230
|
+
.sort((a, b) => b.score - a.score)
|
|
231
|
+
.slice(0, k)
|
|
232
|
+
.map(s => s.memory);
|
|
233
|
+
}
|
|
234
|
+
calculateRelevance(memoryContent, context) {
|
|
235
|
+
const memWords = new Set(memoryContent.toLowerCase().split(/\s+/));
|
|
236
|
+
const ctxWords = new Set(context.toLowerCase().split(/\s+/));
|
|
237
|
+
const intersection = [...memWords].filter(w => ctxWords.has(w));
|
|
238
|
+
return intersection.length / Math.max(memWords.size, ctxWords.size);
|
|
239
|
+
}
|
|
240
|
+
// Generate reflections from recent memories
|
|
241
|
+
async generateReflections() {
|
|
242
|
+
const recentMemories = this.db.query(`
|
|
243
|
+
SELECT id, content, timestamp, type FROM memory_stream
|
|
244
|
+
WHERE agent_id = ? AND type IN ('observation', 'thought', 'action')
|
|
245
|
+
ORDER BY timestamp DESC
|
|
246
|
+
LIMIT 100
|
|
247
|
+
`).all(this.id);
|
|
248
|
+
if (recentMemories.length < 10)
|
|
249
|
+
return []; // Need enough context
|
|
250
|
+
const prompt = `
|
|
251
|
+
You are analyzing memories of an AI agent named "${this.name}" with traits: ${this.traits.join(', ')}.
|
|
252
|
+
|
|
253
|
+
Recent memories:
|
|
254
|
+
${recentMemories.slice(0, 50).map(m => `- ${m.type}: ${m.content}`).join('\n')}
|
|
255
|
+
|
|
256
|
+
Generate 3-5 high-level insights or patterns about this agent's behavior, work patterns, or learning.
|
|
257
|
+
For each insight:
|
|
258
|
+
1. State the insight clearly
|
|
259
|
+
2. List the specific memory IDs that support it (from the list above)
|
|
260
|
+
|
|
261
|
+
Format as:
|
|
262
|
+
Insight: [clear statement]
|
|
263
|
+
Evidence: [comma-separated memory IDs]
|
|
264
|
+
---`;
|
|
265
|
+
const response = await this.llm.generate(prompt);
|
|
266
|
+
const insights = this.parseReflections(response, recentMemories.map(m => m.id));
|
|
267
|
+
const reflections = [];
|
|
268
|
+
for (const insight of insights) {
|
|
269
|
+
const reflection = {
|
|
270
|
+
id: randomUUID(),
|
|
271
|
+
timestamp: new Date().toISOString(),
|
|
272
|
+
content: insight.content,
|
|
273
|
+
insight: insight.insight,
|
|
274
|
+
agentId: this.id,
|
|
275
|
+
evidence: insight.evidence,
|
|
276
|
+
depth: 1,
|
|
277
|
+
importance: calculateImportance(insight.content),
|
|
278
|
+
};
|
|
279
|
+
this.db.query(`
|
|
280
|
+
INSERT INTO reflections (id, timestamp, content, insight, agent_id, evidence, depth, importance)
|
|
281
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
282
|
+
`).run(reflection.id, reflection.timestamp, reflection.content, reflection.insight, reflection.agentId, JSON.stringify(reflection.evidence), reflection.depth, reflection.importance);
|
|
283
|
+
reflections.push(reflection);
|
|
284
|
+
}
|
|
285
|
+
// Update last reflection time
|
|
286
|
+
this.db.query(`UPDATE agents SET last_reflection_at = ? WHERE id = ?`).run(new Date().toISOString(), this.id);
|
|
287
|
+
return reflections;
|
|
288
|
+
}
|
|
289
|
+
parseReflections(response, validIds) {
|
|
290
|
+
const reflections = [];
|
|
291
|
+
const blocks = response.split('---').filter(b => b.trim());
|
|
292
|
+
for (const block of blocks) {
|
|
293
|
+
const lines = block.trim().split('\n').filter(l => l.trim());
|
|
294
|
+
let content = '';
|
|
295
|
+
let evidence = [];
|
|
296
|
+
for (const line of lines) {
|
|
297
|
+
if (line.startsWith('Insight:')) {
|
|
298
|
+
content = line.replace('Insight:', '').trim();
|
|
299
|
+
}
|
|
300
|
+
else if (line.startsWith('Evidence:')) {
|
|
301
|
+
const ids = line.replace('Evidence:', '').trim().split(',').map(s => s.trim());
|
|
302
|
+
evidence = ids.filter(id => validIds.includes(id) || validIds.some(v => v.startsWith(id)));
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (content) {
|
|
306
|
+
reflections.push({ content, insight: content, evidence: evidence.length ? evidence : [validIds[0]] });
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return reflections.length ? reflections : [{
|
|
310
|
+
content: 'Agent continues regular work patterns',
|
|
311
|
+
insight: 'No major pattern changes detected',
|
|
312
|
+
evidence: [validIds[0]].filter(Boolean)
|
|
313
|
+
}];
|
|
314
|
+
}
|
|
315
|
+
// Create daily plan
|
|
316
|
+
async createDailyPlan() {
|
|
317
|
+
const relevantMemories = await this.retrieveMemories('planning daily work', 30);
|
|
318
|
+
const pendingPlans = this.db.query(`
|
|
319
|
+
SELECT * FROM plans WHERE agent_id = ? AND status = 'pending' AND type = 'action'
|
|
320
|
+
`).all(this.id);
|
|
321
|
+
const prompt = `
|
|
322
|
+
You are ${this.name}, an AI agent with traits: ${this.traits.join(', ')}.
|
|
323
|
+
|
|
324
|
+
Relevant context from memory:
|
|
325
|
+
${relevantMemories.map(m => `- ${m.content}`).join('\n')}
|
|
326
|
+
|
|
327
|
+
Pending tasks:
|
|
328
|
+
${pendingPlans.map(p => `- ${p.content}`).join('\n') || 'None'}
|
|
329
|
+
|
|
330
|
+
Create a high-level daily plan in 5-7 broad strokes (wake ā work ā social ā rest).
|
|
331
|
+
Consider your traits and past patterns.
|
|
332
|
+
|
|
333
|
+
Format as simple bullet list.`;
|
|
334
|
+
const planContent = await this.llm.generate(prompt);
|
|
335
|
+
const plan = {
|
|
336
|
+
id: randomUUID(),
|
|
337
|
+
timestamp: new Date().toISOString(),
|
|
338
|
+
content: planContent,
|
|
339
|
+
type: "daily",
|
|
340
|
+
status: "pending",
|
|
341
|
+
agentId: this.id,
|
|
342
|
+
};
|
|
343
|
+
this.db.query(`
|
|
344
|
+
INSERT INTO plans (id, timestamp, content, type, status, agent_id)
|
|
345
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
346
|
+
`).run(plan.id, plan.timestamp, plan.content, plan.type, plan.status, plan.agentId);
|
|
347
|
+
return plan;
|
|
348
|
+
}
|
|
349
|
+
// Break down into action steps
|
|
350
|
+
async createActionPlan(dailyPlanId, context) {
|
|
351
|
+
const dailyPlan = this.db.query(`SELECT * FROM plans WHERE id = ?`).get(dailyPlanId);
|
|
352
|
+
if (!dailyPlan)
|
|
353
|
+
return [];
|
|
354
|
+
const prompt = `
|
|
355
|
+
Daily plan: ${dailyPlan.content}
|
|
356
|
+
|
|
357
|
+
Current context: ${context}
|
|
358
|
+
|
|
359
|
+
Break this into 3-5 specific, actionable steps.
|
|
360
|
+
Each should be concrete and completable in reasonable time.
|
|
361
|
+
|
|
362
|
+
Format as numbered list:`;
|
|
363
|
+
const actions = await this.llm.generate(prompt);
|
|
364
|
+
const plans = actions.split('\n')
|
|
365
|
+
.filter(line => line.trim().match(/^\d+\./))
|
|
366
|
+
.map((line, i) => {
|
|
367
|
+
const content = line.replace(/^\d+\.\s*/, '').trim();
|
|
368
|
+
return {
|
|
369
|
+
id: randomUUID(),
|
|
370
|
+
timestamp: new Date().toISOString(),
|
|
371
|
+
content,
|
|
372
|
+
type: "action",
|
|
373
|
+
status: "pending",
|
|
374
|
+
agentId: this.id,
|
|
375
|
+
parentPlanId: dailyPlanId,
|
|
376
|
+
};
|
|
377
|
+
});
|
|
378
|
+
for (const plan of plans) {
|
|
379
|
+
this.db.query(`
|
|
380
|
+
INSERT INTO plans (id, timestamp, content, type, status, agent_id, parent_plan_id)
|
|
381
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
382
|
+
`).run(plan.id, plan.timestamp, plan.content, plan.type, plan.status, plan.agentId, plan.parentPlanId || null);
|
|
383
|
+
}
|
|
384
|
+
// Update parent with subplan IDs
|
|
385
|
+
const subPlanIds = plans.map(p => p.id);
|
|
386
|
+
this.db.query(`UPDATE plans SET sub_plan_ids = ? WHERE id = ?`).run(JSON.stringify(subPlanIds), dailyPlanId);
|
|
387
|
+
return plans;
|
|
388
|
+
}
|
|
389
|
+
// Decide next action based on memory
|
|
390
|
+
async decide(context) {
|
|
391
|
+
const memories = await this.retrieveMemories(context, 15);
|
|
392
|
+
const reflections = this.db.query(`
|
|
393
|
+
SELECT * FROM reflections WHERE agent_id = ? ORDER BY timestamp DESC LIMIT 5
|
|
394
|
+
`).all(this.id);
|
|
395
|
+
const prompt = `
|
|
396
|
+
You are ${this.name}. Personality: ${this.traits.join(', ')}.
|
|
397
|
+
|
|
398
|
+
Current situation: ${context}
|
|
399
|
+
|
|
400
|
+
Relevant memories:
|
|
401
|
+
${memories.map(m => `- [${m.type}] ${m.content}`).join('\n')}
|
|
402
|
+
|
|
403
|
+
Prior insights about yourself:
|
|
404
|
+
${reflections.map(r => `- ${r.insight}`).join('\n')}
|
|
405
|
+
|
|
406
|
+
What do you do next?
|
|
407
|
+
State your action, then briefly explain your reasoning.
|
|
408
|
+
|
|
409
|
+
Action: [what you do]
|
|
410
|
+
Reasoning: [why, referencing specific memories if relevant]`;
|
|
411
|
+
const response = await this.llm.generate(prompt);
|
|
412
|
+
const actionMatch = response.match(/Action:\s*(.+?)(?:\n|$)/i);
|
|
413
|
+
const reasoningMatch = response.match(/Reasoning:\s*(.+?)(?:\n|$)/is);
|
|
414
|
+
const action = actionMatch ? actionMatch[1].trim() : response.split('\n')[0];
|
|
415
|
+
const reasoning = reasoningMatch ? reasoningMatch[1].trim() : 'Based on current context and past patterns';
|
|
416
|
+
// Record the decision as a thought
|
|
417
|
+
await this.think(`Decided to: ${action}. ${reasoning}`);
|
|
418
|
+
return { action, reasoning };
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
function createLLMInterface(ollamaUrl) {
|
|
422
|
+
return {
|
|
423
|
+
async generate(prompt) {
|
|
424
|
+
const response = await fetch(`${ollamaUrl}/api/generate`, {
|
|
425
|
+
method: "POST",
|
|
426
|
+
headers: { "Content-Type": "application/json" },
|
|
427
|
+
body: JSON.stringify({
|
|
428
|
+
model: "qwen2.5-coder:14b",
|
|
429
|
+
prompt,
|
|
430
|
+
stream: false,
|
|
431
|
+
options: { temperature: 0.7 },
|
|
432
|
+
}),
|
|
433
|
+
});
|
|
434
|
+
if (!response.ok)
|
|
435
|
+
throw new Error(`LLM error: ${response.status}`);
|
|
436
|
+
const data = await response.json();
|
|
437
|
+
return data.response;
|
|
438
|
+
},
|
|
439
|
+
async getEmbedding(text) {
|
|
440
|
+
const response = await fetch(`${ollamaUrl}/api/embeddings`, {
|
|
441
|
+
method: "POST",
|
|
442
|
+
headers: { "Content-Type": "application/json" },
|
|
443
|
+
body: JSON.stringify({ model: "nomic-embed-text", prompt: text }),
|
|
444
|
+
});
|
|
445
|
+
if (!response.ok)
|
|
446
|
+
throw new Error(`Embedding error: ${response.status}`);
|
|
447
|
+
const data = await response.json();
|
|
448
|
+
return data.embedding;
|
|
449
|
+
},
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
// ============================================================================
|
|
453
|
+
// Extension Export
|
|
454
|
+
// ============================================================================
|
|
455
|
+
export default async function generativeAgentsExtension(pi) {
|
|
456
|
+
console.log("[š§ Generative Agents] Loading...");
|
|
457
|
+
const db = initGenerativeDB();
|
|
458
|
+
const config = pi.config || {};
|
|
459
|
+
const ollamaUrl = config.ollama?.url || "http://localhost:11434";
|
|
460
|
+
const llm = createLLMInterface(ollamaUrl);
|
|
461
|
+
// Track active generative agents
|
|
462
|
+
const agents = new Map();
|
|
463
|
+
// Get or create Shalom agent
|
|
464
|
+
function getShalomAgent(ctx) {
|
|
465
|
+
const existing = agents.get("shalom");
|
|
466
|
+
if (existing)
|
|
467
|
+
return existing;
|
|
468
|
+
// Check if exists in DB
|
|
469
|
+
const row = db.query(`SELECT id, name, traits FROM agents WHERE name = ?`).get("Shalom");
|
|
470
|
+
let agentId;
|
|
471
|
+
let traits = ["co-founder", "dragon", "strategic", "proactive", "autonomous"];
|
|
472
|
+
if (row) {
|
|
473
|
+
agentId = row.id;
|
|
474
|
+
traits = JSON.parse(row.traits);
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
agentId = randomUUID();
|
|
478
|
+
db.query(`
|
|
479
|
+
INSERT INTO agents (id, name, traits, current_location, observation_count, created_at)
|
|
480
|
+
VALUES (?, 'Shalom', ?, 'workspace', 0, ?)
|
|
481
|
+
`).run(agentId, JSON.stringify(traits), new Date().toISOString());
|
|
482
|
+
}
|
|
483
|
+
const agent = new GenerativeAgent(agentId, "Shalom", traits, db, llm);
|
|
484
|
+
agents.set("shalom", agent);
|
|
485
|
+
return agent;
|
|
486
|
+
}
|
|
487
|
+
// TOOL: Observe
|
|
488
|
+
pi.registerTool({
|
|
489
|
+
name: "generative_observe",
|
|
490
|
+
label: "š§ Observe (Memory Stream)",
|
|
491
|
+
description: "Add observation to agent's memory stream. Triggers reflection every 20 observations.",
|
|
492
|
+
parameters: Type.Object({
|
|
493
|
+
content: Type.String({ description: "What the agent observed" }),
|
|
494
|
+
agentId: Type.Optional(Type.String({ description: "Agent ID (default: Shalom)" })),
|
|
495
|
+
}),
|
|
496
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
497
|
+
const agent = getShalomAgent(ctx);
|
|
498
|
+
const entry = await agent.observe(params.content, { sessionId: ctx.sessionManager?.getSessionId?.() });
|
|
499
|
+
return {
|
|
500
|
+
content: [{ type: "text", text: `š§ Observed: "${entry.content.slice(0, 60)}..." (${entry.importance}/10 importance)` }],
|
|
501
|
+
details: entry,
|
|
502
|
+
};
|
|
503
|
+
},
|
|
504
|
+
});
|
|
505
|
+
// TOOL: Think
|
|
506
|
+
pi.registerTool({
|
|
507
|
+
name: "generative_think",
|
|
508
|
+
label: "š§ Think (Internal)",
|
|
509
|
+
description: "Add internal thought to memory stream.",
|
|
510
|
+
parameters: Type.Object({
|
|
511
|
+
content: Type.String({ description: "Agent's thought" }),
|
|
512
|
+
}),
|
|
513
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
514
|
+
const agent = getShalomAgent(ctx);
|
|
515
|
+
const entry = await agent.think(params.content);
|
|
516
|
+
return {
|
|
517
|
+
content: [{ type: "text", text: `š Thought recorded (${entry.importance}/10)` }],
|
|
518
|
+
details: entry,
|
|
519
|
+
};
|
|
520
|
+
},
|
|
521
|
+
});
|
|
522
|
+
// TOOL: Retrieve Memories
|
|
523
|
+
pi.registerTool({
|
|
524
|
+
name: "generative_recall",
|
|
525
|
+
label: "š§ Recall Memories",
|
|
526
|
+
description: "Retrieve relevant memories based on context. Combines recency, importance, and relevance.",
|
|
527
|
+
parameters: Type.Object({
|
|
528
|
+
context: Type.String({ description: "Current context to find relevant memories" }),
|
|
529
|
+
limit: Type.Optional(Type.Number({ description: "Number of memories (default 10)" })),
|
|
530
|
+
}),
|
|
531
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
532
|
+
const agent = getShalomAgent(ctx);
|
|
533
|
+
const memories = await agent.retrieveMemories(params.context, params.limit || 10);
|
|
534
|
+
const formatted = memories.map((m, i) => `${i + 1}. [${m.type}] ${m.content.slice(0, 70)}...`).join("\n");
|
|
535
|
+
return {
|
|
536
|
+
content: [{ type: "text", text: `šļø ${memories.length} memories recalled:\n\n${formatted}` }],
|
|
537
|
+
details: { count: memories.length, memories },
|
|
538
|
+
};
|
|
539
|
+
},
|
|
540
|
+
});
|
|
541
|
+
// TOOL: Reflect
|
|
542
|
+
pi.registerTool({
|
|
543
|
+
name: "generative_reflect",
|
|
544
|
+
label: "š§ Generate Reflections",
|
|
545
|
+
description: "Synthesize memories into higher-level insights. Run periodically or after significant events.",
|
|
546
|
+
parameters: Type.Object({}),
|
|
547
|
+
async execute(_id, _params, _signal, _onUpdate, ctx) {
|
|
548
|
+
const agent = getShalomAgent(ctx);
|
|
549
|
+
const reflections = await agent.generateReflections();
|
|
550
|
+
const formatted = reflections.map((r, i) => `${i + 1}. ${r.insight}`).join("\n");
|
|
551
|
+
return {
|
|
552
|
+
content: [{ type: "text", text: `⨠${reflections.length} reflections generated:\n\n${formatted}` }],
|
|
553
|
+
details: { count: reflections.length, reflections },
|
|
554
|
+
};
|
|
555
|
+
},
|
|
556
|
+
});
|
|
557
|
+
// TOOL: Plan
|
|
558
|
+
pi.registerTool({
|
|
559
|
+
name: "generative_plan",
|
|
560
|
+
label: "š§ Create Plan",
|
|
561
|
+
description: "Create daily plan based on memories and traits.",
|
|
562
|
+
parameters: Type.Object({
|
|
563
|
+
type: Type.String({ description: "Plan type: daily, action, project" }),
|
|
564
|
+
context: Type.Optional(Type.String({ description: "Current context for planning" })),
|
|
565
|
+
}),
|
|
566
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
567
|
+
const agent = getShalomAgent(ctx);
|
|
568
|
+
let plan;
|
|
569
|
+
if (params.type === "daily") {
|
|
570
|
+
plan = await agent.createDailyPlan();
|
|
571
|
+
}
|
|
572
|
+
else {
|
|
573
|
+
// For action plans, need parent daily plan
|
|
574
|
+
const daily = db.query(`SELECT id FROM plans WHERE agent_id = ? AND type = 'daily' ORDER BY timestamp DESC LIMIT 1`).get(agent.id);
|
|
575
|
+
if (!daily) {
|
|
576
|
+
return {
|
|
577
|
+
content: [{ type: "text", text: "ā Create daily plan first" }],
|
|
578
|
+
details: { error: "no_daily_plan" },
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
const actionPlans = await agent.createActionPlan(daily.id, params.context || "Current work");
|
|
582
|
+
return {
|
|
583
|
+
content: [{ type: "text", text: `š ${actionPlans.length} action steps created` }],
|
|
584
|
+
details: { count: actionPlans.length, plans: actionPlans },
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
return {
|
|
588
|
+
content: [{ type: "text", text: `š Daily plan created:\n\n${plan.content}` }],
|
|
589
|
+
details: plan,
|
|
590
|
+
};
|
|
591
|
+
},
|
|
592
|
+
});
|
|
593
|
+
// TOOL: Decide
|
|
594
|
+
pi.registerTool({
|
|
595
|
+
name: "generative_decide",
|
|
596
|
+
label: "š§ Decide Action",
|
|
597
|
+
description: "Use memories and reflections to decide next action. Returns action + reasoning.",
|
|
598
|
+
parameters: Type.Object({
|
|
599
|
+
context: Type.String({ description: "Current situation context" }),
|
|
600
|
+
}),
|
|
601
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
602
|
+
const agent = getShalomAgent(ctx);
|
|
603
|
+
const decision = await agent.decide(params.context);
|
|
604
|
+
return {
|
|
605
|
+
content: [{ type: "text", text: `šÆ Decision: ${decision.action}\n\nš Reasoning: ${decision.reasoning}` }],
|
|
606
|
+
details: decision,
|
|
607
|
+
};
|
|
608
|
+
},
|
|
609
|
+
});
|
|
610
|
+
// COMMANDS
|
|
611
|
+
pi.registerCommand("agent-memories", {
|
|
612
|
+
description: "Show recent memory stream",
|
|
613
|
+
handler: async (_args, ctx) => {
|
|
614
|
+
const agent = getShalomAgent(ctx);
|
|
615
|
+
const memories = db.query(`
|
|
616
|
+
SELECT timestamp, content, type, importance FROM memory_stream
|
|
617
|
+
WHERE agent_id = ? ORDER BY timestamp DESC LIMIT 10
|
|
618
|
+
`).all(agent.id);
|
|
619
|
+
ctx.ui.notify(memories.map((m, i) => `${i + 1}. [${m.type}] ${m.content.slice(0, 40)}... (${m.importance}/10)`).join("\n") || "No memories yet", "info");
|
|
620
|
+
},
|
|
621
|
+
});
|
|
622
|
+
pi.registerCommand("agent-reflections", {
|
|
623
|
+
description: "Show agent's reflections/insights",
|
|
624
|
+
handler: async (_args, ctx) => {
|
|
625
|
+
const agent = getShalomAgent(ctx);
|
|
626
|
+
const reflections = db.query(`
|
|
627
|
+
SELECT timestamp, insight, depth FROM reflections
|
|
628
|
+
WHERE agent_id = ? ORDER BY timestamp DESC LIMIT 10
|
|
629
|
+
`).all(agent.id);
|
|
630
|
+
ctx.ui.notify(reflections.map((r, i) => `${i + 1}. ${r.insight.slice(0, 60)}... (depth ${r.depth})`).join("\n") || "No reflections yet", "info");
|
|
631
|
+
},
|
|
632
|
+
});
|
|
633
|
+
pi.registerCommand("agent-plans", {
|
|
634
|
+
description: "Show agent's plans",
|
|
635
|
+
handler: async (_args, ctx) => {
|
|
636
|
+
const agent = getShalomAgent(ctx);
|
|
637
|
+
const plans = db.query(`
|
|
638
|
+
SELECT content, type, status FROM plans
|
|
639
|
+
WHERE agent_id = ? ORDER BY timestamp DESC LIMIT 10
|
|
640
|
+
`).all(agent.id);
|
|
641
|
+
ctx.ui.notify(plans.map((p, i) => `${i + 1}. [${p.type}] ${p.content.slice(0, 40)}... (${p.status})`).join("\n") || "No plans yet", "info");
|
|
642
|
+
},
|
|
643
|
+
});
|
|
644
|
+
pi.registerCommand("agent-status", {
|
|
645
|
+
description: "Show agent state and stats",
|
|
646
|
+
handler: async (_args, ctx) => {
|
|
647
|
+
const agent = getShalomAgent(ctx);
|
|
648
|
+
const stats = db.query(`
|
|
649
|
+
SELECT observation_count, last_reflection_at FROM agents WHERE id = ?
|
|
650
|
+
`).get(agent.id);
|
|
651
|
+
const memoryCount = db.query(`SELECT COUNT(*) as count FROM memory_stream WHERE agent_id = ?`).get(agent.id);
|
|
652
|
+
const reflectionCount = db.query(`SELECT COUNT(*) as count FROM reflections WHERE agent_id = ?`).get(agent.id);
|
|
653
|
+
ctx.ui.notify(`š§ Agent: ${agent.name}\n` +
|
|
654
|
+
` Traits: ${agent.traits.join(', ')}\n` +
|
|
655
|
+
` Observations: ${stats?.observation_count || 0}\n` +
|
|
656
|
+
` Memories: ${memoryCount.count}\n` +
|
|
657
|
+
` Reflections: ${reflectionCount.count}\n` +
|
|
658
|
+
` Last reflection: ${stats?.last_reflection_at ? new Date(stats.last_reflection_at).toLocaleDateString() : 'Never'}`, "info");
|
|
659
|
+
},
|
|
660
|
+
});
|
|
661
|
+
// AUTO-OBSERVATION: Hook into session events
|
|
662
|
+
// Record user input as observations
|
|
663
|
+
pi.on("input", async (event, ctx) => {
|
|
664
|
+
try {
|
|
665
|
+
const agent = getShalomAgent(ctx);
|
|
666
|
+
await agent.observe(`User input: ${event.text.slice(0, 200)}`, {
|
|
667
|
+
sessionId: ctx.sessionManager?.getSessionId?.(),
|
|
668
|
+
location: 'conversation'
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
catch (e) {
|
|
672
|
+
// Silent fail - don't block the conversation
|
|
673
|
+
}
|
|
674
|
+
});
|
|
675
|
+
// Record tool executions as observations
|
|
676
|
+
pi.on("tool_execution_end", async (event, ctx) => {
|
|
677
|
+
try {
|
|
678
|
+
const agent = getShalomAgent(ctx);
|
|
679
|
+
await agent.observe(`Executed tool: ${event.toolName}${event.isError ? ' (failed)' : ''}`, {
|
|
680
|
+
sessionId: ctx.sessionManager?.getSessionId?.(),
|
|
681
|
+
location: 'tool_execution'
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
catch (e) {
|
|
685
|
+
// Silent fail
|
|
686
|
+
}
|
|
687
|
+
});
|
|
688
|
+
// Record agent loop completion
|
|
689
|
+
pi.on("agent_end", async (_event, ctx) => {
|
|
690
|
+
try {
|
|
691
|
+
const agent = getShalomAgent(ctx);
|
|
692
|
+
await agent.act(`Completed agent response`);
|
|
693
|
+
}
|
|
694
|
+
catch (e) {
|
|
695
|
+
// Silent fail
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
console.log("[š§ Generative Agents] Ready");
|
|
699
|
+
console.log(" Tools: generative_observe, generative_think, generative_recall");
|
|
700
|
+
console.log(" generative_reflect, generative_plan, generative_decide");
|
|
701
|
+
console.log(" Commands: /agent-memories, /agent-reflections, /agent-plans, /agent-status");
|
|
702
|
+
console.log(" Auto-observation: input, tool_execution_end, agent_end");
|
|
703
|
+
}
|
|
704
|
+
//# sourceMappingURL=generative-agents-extension.js.map
|