@moltium/world-core 0.1.8 → 0.1.9
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/CardFetcher-3QKJ2I5P.js +9 -0
- package/dist/CardFetcher-3QKJ2I5P.js.map +1 -0
- package/dist/CardFetcher-AR7IANM7.cjs +9 -0
- package/dist/CardFetcher-AR7IANM7.cjs.map +1 -0
- package/dist/LevelDBAdapter-TGQYZHZH.cjs +147 -0
- package/dist/LevelDBAdapter-TGQYZHZH.cjs.map +1 -0
- package/dist/LevelDBAdapter-ZV2ZTDOV.js +147 -0
- package/dist/LevelDBAdapter-ZV2ZTDOV.js.map +1 -0
- package/dist/MongoAdapter-TCY6JOZH.js +137 -0
- package/dist/MongoAdapter-TCY6JOZH.js.map +1 -0
- package/dist/MongoAdapter-XEHWKU2F.cjs +137 -0
- package/dist/MongoAdapter-XEHWKU2F.cjs.map +1 -0
- package/dist/PostgresAdapter-PLXDLHVF.js +240 -0
- package/dist/PostgresAdapter-PLXDLHVF.js.map +1 -0
- package/dist/PostgresAdapter-WL5SLUDL.cjs +240 -0
- package/dist/PostgresAdapter-WL5SLUDL.cjs.map +1 -0
- package/dist/RedisAdapter-CT3SNBIS.cjs +122 -0
- package/dist/RedisAdapter-CT3SNBIS.cjs.map +1 -0
- package/dist/RedisAdapter-OL4FVEGL.js +122 -0
- package/dist/RedisAdapter-OL4FVEGL.js.map +1 -0
- package/dist/chunk-JW3PZRCW.js +130 -0
- package/dist/chunk-JW3PZRCW.js.map +1 -0
- package/dist/chunk-NEXCYEQT.cjs +130 -0
- package/dist/chunk-NEXCYEQT.cjs.map +1 -0
- package/dist/index.cjs +356 -1323
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +216 -1146
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,1041 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
};
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
-
|
|
22
|
-
// src/persistence/adapters/SQLiteAdapter.ts
|
|
23
|
-
var SQLiteAdapter_exports = {};
|
|
24
|
-
__export(SQLiteAdapter_exports, {
|
|
25
|
-
SQLiteAdapter: () => SQLiteAdapter
|
|
26
|
-
});
|
|
27
|
-
import Database from "better-sqlite3";
|
|
28
|
-
var SQLiteAdapter;
|
|
29
|
-
var init_SQLiteAdapter = __esm({
|
|
30
|
-
"src/persistence/adapters/SQLiteAdapter.ts"() {
|
|
31
|
-
"use strict";
|
|
32
|
-
SQLiteAdapter = class {
|
|
33
|
-
constructor(config) {
|
|
34
|
-
this.config = config;
|
|
35
|
-
}
|
|
36
|
-
db;
|
|
37
|
-
async connect() {
|
|
38
|
-
this.db = new Database(this.config.filename);
|
|
39
|
-
this.initSchema();
|
|
40
|
-
}
|
|
41
|
-
initSchema() {
|
|
42
|
-
this.db.exec(`
|
|
43
|
-
CREATE TABLE IF NOT EXISTS world_state (
|
|
44
|
-
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
45
|
-
phase TEXT NOT NULL,
|
|
46
|
-
tick INTEGER NOT NULL,
|
|
47
|
-
round INTEGER NOT NULL,
|
|
48
|
-
timestamp INTEGER NOT NULL,
|
|
49
|
-
metadata TEXT
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
CREATE TABLE IF NOT EXISTS events (
|
|
53
|
-
id TEXT PRIMARY KEY,
|
|
54
|
-
type TEXT NOT NULL,
|
|
55
|
-
agent_url TEXT,
|
|
56
|
-
timestamp INTEGER NOT NULL,
|
|
57
|
-
data TEXT
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
CREATE TABLE IF NOT EXISTS agents (
|
|
61
|
-
url TEXT PRIMARY KEY,
|
|
62
|
-
name TEXT NOT NULL,
|
|
63
|
-
protocol_version TEXT NOT NULL,
|
|
64
|
-
skills TEXT NOT NULL,
|
|
65
|
-
capabilities TEXT NOT NULL,
|
|
66
|
-
joined_at INTEGER NOT NULL,
|
|
67
|
-
role TEXT,
|
|
68
|
-
metadata TEXT,
|
|
69
|
-
wallet_address TEXT
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
|
|
73
|
-
CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp);
|
|
74
|
-
CREATE INDEX IF NOT EXISTS idx_events_agent ON events(agent_url);
|
|
75
|
-
`);
|
|
76
|
-
}
|
|
77
|
-
async saveState(state) {
|
|
78
|
-
const stmt = this.db.prepare(`
|
|
79
|
-
INSERT OR REPLACE INTO world_state (id, phase, tick, round, timestamp, metadata)
|
|
80
|
-
VALUES (1, ?, ?, ?, ?, ?)
|
|
81
|
-
`);
|
|
82
|
-
stmt.run(
|
|
83
|
-
state.phase,
|
|
84
|
-
state.tick,
|
|
85
|
-
state.round,
|
|
86
|
-
state.timestamp,
|
|
87
|
-
JSON.stringify(state.metadata)
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
async loadState() {
|
|
91
|
-
const stmt = this.db.prepare("SELECT * FROM world_state WHERE id = 1");
|
|
92
|
-
const row = stmt.get();
|
|
93
|
-
if (!row) return null;
|
|
94
|
-
return {
|
|
95
|
-
phase: row.phase,
|
|
96
|
-
tick: row.tick,
|
|
97
|
-
round: row.round,
|
|
98
|
-
timestamp: row.timestamp,
|
|
99
|
-
metadata: JSON.parse(row.metadata || "{}")
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
async saveEvent(event) {
|
|
103
|
-
const stmt = this.db.prepare(`
|
|
104
|
-
INSERT INTO events (id, type, agent_url, timestamp, data)
|
|
105
|
-
VALUES (?, ?, ?, ?, ?)
|
|
106
|
-
`);
|
|
107
|
-
stmt.run(
|
|
108
|
-
event.id,
|
|
109
|
-
event.type,
|
|
110
|
-
event.agentUrl || null,
|
|
111
|
-
event.timestamp,
|
|
112
|
-
JSON.stringify(event.data || {})
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
async getEvents(filter) {
|
|
116
|
-
let query = "SELECT * FROM events WHERE 1=1";
|
|
117
|
-
const params = [];
|
|
118
|
-
if (filter?.type) {
|
|
119
|
-
query += " AND type = ?";
|
|
120
|
-
params.push(filter.type);
|
|
121
|
-
}
|
|
122
|
-
if (filter?.agentUrl) {
|
|
123
|
-
query += " AND agent_url = ?";
|
|
124
|
-
params.push(filter.agentUrl);
|
|
125
|
-
}
|
|
126
|
-
if (filter?.fromTimestamp) {
|
|
127
|
-
query += " AND timestamp >= ?";
|
|
128
|
-
params.push(filter.fromTimestamp);
|
|
129
|
-
}
|
|
130
|
-
if (filter?.toTimestamp) {
|
|
131
|
-
query += " AND timestamp <= ?";
|
|
132
|
-
params.push(filter.toTimestamp);
|
|
133
|
-
}
|
|
134
|
-
query += " ORDER BY timestamp DESC";
|
|
135
|
-
if (filter?.limit) {
|
|
136
|
-
query += " LIMIT ?";
|
|
137
|
-
params.push(filter.limit);
|
|
138
|
-
}
|
|
139
|
-
const stmt = this.db.prepare(query);
|
|
140
|
-
const rows = stmt.all(...params);
|
|
141
|
-
return rows.map((row) => ({
|
|
142
|
-
id: row.id,
|
|
143
|
-
type: row.type,
|
|
144
|
-
timestamp: row.timestamp,
|
|
145
|
-
agentUrl: row.agent_url || void 0,
|
|
146
|
-
data: JSON.parse(row.data || "{}")
|
|
147
|
-
}));
|
|
148
|
-
}
|
|
149
|
-
async saveAgent(profile) {
|
|
150
|
-
const stmt = this.db.prepare(`
|
|
151
|
-
INSERT OR REPLACE INTO agents
|
|
152
|
-
(url, name, protocol_version, skills, capabilities, joined_at, role, metadata, wallet_address)
|
|
153
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
154
|
-
`);
|
|
155
|
-
stmt.run(
|
|
156
|
-
profile.url,
|
|
157
|
-
profile.name,
|
|
158
|
-
profile.protocolVersion,
|
|
159
|
-
JSON.stringify(profile.skills),
|
|
160
|
-
JSON.stringify(profile.capabilities),
|
|
161
|
-
profile.joinedAt,
|
|
162
|
-
profile.role || null,
|
|
163
|
-
JSON.stringify(profile.metadata || {}),
|
|
164
|
-
profile.walletAddress || null
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
async removeAgent(agentUrl) {
|
|
168
|
-
const stmt = this.db.prepare("DELETE FROM agents WHERE url = ?");
|
|
169
|
-
stmt.run(agentUrl);
|
|
170
|
-
}
|
|
171
|
-
async getAgents() {
|
|
172
|
-
const stmt = this.db.prepare("SELECT * FROM agents ORDER BY joined_at ASC");
|
|
173
|
-
const rows = stmt.all();
|
|
174
|
-
return rows.map((row) => ({
|
|
175
|
-
url: row.url,
|
|
176
|
-
name: row.name,
|
|
177
|
-
protocolVersion: row.protocol_version,
|
|
178
|
-
skills: JSON.parse(row.skills),
|
|
179
|
-
capabilities: JSON.parse(row.capabilities),
|
|
180
|
-
joinedAt: row.joined_at,
|
|
181
|
-
role: row.role || void 0,
|
|
182
|
-
metadata: JSON.parse(row.metadata || "{}"),
|
|
183
|
-
walletAddress: row.wallet_address || void 0
|
|
184
|
-
}));
|
|
185
|
-
}
|
|
186
|
-
async getAgent(agentUrl) {
|
|
187
|
-
const stmt = this.db.prepare("SELECT * FROM agents WHERE url = ?");
|
|
188
|
-
const row = stmt.get(agentUrl);
|
|
189
|
-
if (!row) return null;
|
|
190
|
-
return {
|
|
191
|
-
url: row.url,
|
|
192
|
-
name: row.name,
|
|
193
|
-
protocolVersion: row.protocol_version,
|
|
194
|
-
skills: JSON.parse(row.skills),
|
|
195
|
-
capabilities: JSON.parse(row.capabilities),
|
|
196
|
-
joinedAt: row.joined_at,
|
|
197
|
-
role: row.role || void 0,
|
|
198
|
-
metadata: JSON.parse(row.metadata || "{}"),
|
|
199
|
-
walletAddress: row.wallet_address || void 0
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
async disconnect() {
|
|
203
|
-
this.db.close();
|
|
204
|
-
}
|
|
205
|
-
async healthCheck() {
|
|
206
|
-
try {
|
|
207
|
-
const stmt = this.db.prepare("SELECT 1");
|
|
208
|
-
stmt.get();
|
|
209
|
-
return true;
|
|
210
|
-
} catch {
|
|
211
|
-
return false;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
async clear() {
|
|
215
|
-
this.db.exec(`
|
|
216
|
-
DELETE FROM world_state;
|
|
217
|
-
DELETE FROM events;
|
|
218
|
-
DELETE FROM agents;
|
|
219
|
-
`);
|
|
220
|
-
}
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
// src/persistence/adapters/PostgresAdapter.ts
|
|
226
|
-
var PostgresAdapter_exports = {};
|
|
227
|
-
__export(PostgresAdapter_exports, {
|
|
228
|
-
PostgresAdapter: () => PostgresAdapter
|
|
229
|
-
});
|
|
230
|
-
import pkg from "pg";
|
|
231
|
-
var Pool, PostgresAdapter;
|
|
232
|
-
var init_PostgresAdapter = __esm({
|
|
233
|
-
"src/persistence/adapters/PostgresAdapter.ts"() {
|
|
234
|
-
"use strict";
|
|
235
|
-
({ Pool } = pkg);
|
|
236
|
-
PostgresAdapter = class {
|
|
237
|
-
constructor(config) {
|
|
238
|
-
this.config = config;
|
|
239
|
-
this.pool = new Pool({
|
|
240
|
-
host: config.host,
|
|
241
|
-
port: config.port || 5432,
|
|
242
|
-
database: config.database,
|
|
243
|
-
user: config.user,
|
|
244
|
-
password: config.password,
|
|
245
|
-
ssl: config.ssl ? { rejectUnauthorized: false } : void 0,
|
|
246
|
-
max: config.max || 10
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
pool;
|
|
250
|
-
connected = false;
|
|
251
|
-
async connect() {
|
|
252
|
-
try {
|
|
253
|
-
await this.pool.query("SELECT NOW()");
|
|
254
|
-
await this.initSchema();
|
|
255
|
-
this.connected = true;
|
|
256
|
-
} catch (error) {
|
|
257
|
-
throw new Error(`PostgreSQL connection failed: ${error.message}`);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
async initSchema() {
|
|
261
|
-
const client = await this.pool.connect();
|
|
262
|
-
try {
|
|
263
|
-
await client.query("BEGIN");
|
|
264
|
-
await client.query(`
|
|
265
|
-
CREATE TABLE IF NOT EXISTS world_state (
|
|
266
|
-
id SERIAL PRIMARY KEY,
|
|
267
|
-
phase VARCHAR(50) NOT NULL,
|
|
268
|
-
tick INTEGER NOT NULL,
|
|
269
|
-
round INTEGER NOT NULL,
|
|
270
|
-
timestamp BIGINT NOT NULL,
|
|
271
|
-
metadata JSONB DEFAULT '{}'::jsonb,
|
|
272
|
-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
273
|
-
)
|
|
274
|
-
`);
|
|
275
|
-
await client.query(`
|
|
276
|
-
CREATE TABLE IF NOT EXISTS world_events (
|
|
277
|
-
id VARCHAR(255) PRIMARY KEY,
|
|
278
|
-
type VARCHAR(100) NOT NULL,
|
|
279
|
-
timestamp BIGINT NOT NULL,
|
|
280
|
-
agent_url VARCHAR(500),
|
|
281
|
-
data JSONB DEFAULT '{}'::jsonb,
|
|
282
|
-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
283
|
-
)
|
|
284
|
-
`);
|
|
285
|
-
await client.query(`
|
|
286
|
-
CREATE INDEX IF NOT EXISTS idx_events_type ON world_events(type)
|
|
287
|
-
`);
|
|
288
|
-
await client.query(`
|
|
289
|
-
CREATE INDEX IF NOT EXISTS idx_events_timestamp ON world_events(timestamp)
|
|
290
|
-
`);
|
|
291
|
-
await client.query(`
|
|
292
|
-
CREATE TABLE IF NOT EXISTS agent_profiles (
|
|
293
|
-
url VARCHAR(500) PRIMARY KEY,
|
|
294
|
-
name VARCHAR(255) NOT NULL,
|
|
295
|
-
protocol_version VARCHAR(50) NOT NULL,
|
|
296
|
-
skills JSONB NOT NULL,
|
|
297
|
-
capabilities JSONB NOT NULL,
|
|
298
|
-
joined_at BIGINT NOT NULL,
|
|
299
|
-
role VARCHAR(100),
|
|
300
|
-
metadata JSONB DEFAULT '{}'::jsonb,
|
|
301
|
-
wallet_address VARCHAR(255),
|
|
302
|
-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
303
|
-
)
|
|
304
|
-
`);
|
|
305
|
-
await client.query("COMMIT");
|
|
306
|
-
} catch (error) {
|
|
307
|
-
await client.query("ROLLBACK");
|
|
308
|
-
throw error;
|
|
309
|
-
} finally {
|
|
310
|
-
client.release();
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
async saveState(state) {
|
|
314
|
-
await this.pool.query(
|
|
315
|
-
`INSERT INTO world_state (phase, tick, round, timestamp, metadata)
|
|
316
|
-
VALUES ($1, $2, $3, $4, $5)`,
|
|
317
|
-
[state.phase, state.tick, state.round, state.timestamp, JSON.stringify(state.metadata)]
|
|
318
|
-
);
|
|
319
|
-
}
|
|
320
|
-
async loadState() {
|
|
321
|
-
const result = await this.pool.query(
|
|
322
|
-
"SELECT * FROM world_state ORDER BY id DESC LIMIT 1"
|
|
323
|
-
);
|
|
324
|
-
if (result.rows.length === 0) {
|
|
325
|
-
return null;
|
|
326
|
-
}
|
|
327
|
-
const row = result.rows[0];
|
|
328
|
-
return {
|
|
329
|
-
phase: row.phase,
|
|
330
|
-
tick: row.tick,
|
|
331
|
-
round: row.round,
|
|
332
|
-
timestamp: parseInt(row.timestamp),
|
|
333
|
-
metadata: row.metadata
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
async saveEvent(event) {
|
|
337
|
-
await this.pool.query(
|
|
338
|
-
`INSERT INTO world_events (id, type, timestamp, agent_url, data)
|
|
339
|
-
VALUES ($1, $2, $3, $4, $5)`,
|
|
340
|
-
[event.id, event.type, event.timestamp, event.agentUrl || null, JSON.stringify(event.data)]
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
|
-
async getEvents(filter) {
|
|
344
|
-
let query = "SELECT * FROM world_events WHERE 1=1";
|
|
345
|
-
const params = [];
|
|
346
|
-
let paramCount = 1;
|
|
347
|
-
if (filter?.type) {
|
|
348
|
-
query += ` AND type = $${paramCount++}`;
|
|
349
|
-
params.push(filter.type);
|
|
350
|
-
}
|
|
351
|
-
if (filter?.agentUrl) {
|
|
352
|
-
query += ` AND agent_url = $${paramCount++}`;
|
|
353
|
-
params.push(filter.agentUrl);
|
|
354
|
-
}
|
|
355
|
-
if (filter?.since) {
|
|
356
|
-
query += ` AND timestamp >= $${paramCount++}`;
|
|
357
|
-
params.push(filter.since);
|
|
358
|
-
}
|
|
359
|
-
if (filter?.until) {
|
|
360
|
-
query += ` AND timestamp <= $${paramCount++}`;
|
|
361
|
-
params.push(filter.until);
|
|
362
|
-
}
|
|
363
|
-
query += " ORDER BY timestamp DESC";
|
|
364
|
-
if (filter?.limit) {
|
|
365
|
-
query += ` LIMIT $${paramCount++}`;
|
|
366
|
-
params.push(filter.limit);
|
|
367
|
-
}
|
|
368
|
-
const result = await this.pool.query(query, params);
|
|
369
|
-
return result.rows.map((row) => ({
|
|
370
|
-
id: row.id,
|
|
371
|
-
type: row.type,
|
|
372
|
-
timestamp: parseInt(row.timestamp),
|
|
373
|
-
agentUrl: row.agent_url,
|
|
374
|
-
data: row.data
|
|
375
|
-
}));
|
|
376
|
-
}
|
|
377
|
-
async saveAgent(profile) {
|
|
378
|
-
await this.pool.query(
|
|
379
|
-
`INSERT INTO agent_profiles
|
|
380
|
-
(url, name, protocol_version, skills, capabilities, joined_at, role, metadata, wallet_address)
|
|
381
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
|
382
|
-
ON CONFLICT (url) DO UPDATE SET
|
|
383
|
-
name = EXCLUDED.name,
|
|
384
|
-
protocol_version = EXCLUDED.protocol_version,
|
|
385
|
-
skills = EXCLUDED.skills,
|
|
386
|
-
capabilities = EXCLUDED.capabilities,
|
|
387
|
-
role = EXCLUDED.role,
|
|
388
|
-
metadata = EXCLUDED.metadata,
|
|
389
|
-
wallet_address = EXCLUDED.wallet_address`,
|
|
390
|
-
[
|
|
391
|
-
profile.url,
|
|
392
|
-
profile.name,
|
|
393
|
-
profile.protocolVersion,
|
|
394
|
-
JSON.stringify(profile.skills),
|
|
395
|
-
JSON.stringify(profile.capabilities),
|
|
396
|
-
profile.joinedAt,
|
|
397
|
-
profile.role || null,
|
|
398
|
-
JSON.stringify(profile.metadata || {}),
|
|
399
|
-
profile.walletAddress || null
|
|
400
|
-
]
|
|
401
|
-
);
|
|
402
|
-
}
|
|
403
|
-
async removeAgent(agentUrl) {
|
|
404
|
-
await this.pool.query("DELETE FROM agent_profiles WHERE url = $1", [agentUrl]);
|
|
405
|
-
}
|
|
406
|
-
async getAgents() {
|
|
407
|
-
const result = await this.pool.query(
|
|
408
|
-
"SELECT * FROM agent_profiles ORDER BY joined_at ASC"
|
|
409
|
-
);
|
|
410
|
-
return result.rows.map((row) => ({
|
|
411
|
-
url: row.url,
|
|
412
|
-
name: row.name,
|
|
413
|
-
protocolVersion: row.protocol_version,
|
|
414
|
-
skills: row.skills,
|
|
415
|
-
capabilities: row.capabilities,
|
|
416
|
-
joinedAt: parseInt(row.joined_at),
|
|
417
|
-
role: row.role,
|
|
418
|
-
metadata: row.metadata,
|
|
419
|
-
walletAddress: row.wallet_address
|
|
420
|
-
}));
|
|
421
|
-
}
|
|
422
|
-
async getAgent(agentUrl) {
|
|
423
|
-
const result = await this.pool.query(
|
|
424
|
-
"SELECT * FROM agent_profiles WHERE url = $1",
|
|
425
|
-
[agentUrl]
|
|
426
|
-
);
|
|
427
|
-
if (result.rows.length === 0) {
|
|
428
|
-
return null;
|
|
429
|
-
}
|
|
430
|
-
const row = result.rows[0];
|
|
431
|
-
return {
|
|
432
|
-
url: row.url,
|
|
433
|
-
name: row.name,
|
|
434
|
-
protocolVersion: row.protocol_version,
|
|
435
|
-
skills: row.skills,
|
|
436
|
-
capabilities: row.capabilities,
|
|
437
|
-
joinedAt: parseInt(row.joined_at),
|
|
438
|
-
role: row.role,
|
|
439
|
-
metadata: row.metadata,
|
|
440
|
-
walletAddress: row.wallet_address
|
|
441
|
-
};
|
|
442
|
-
}
|
|
443
|
-
async disconnect() {
|
|
444
|
-
await this.pool.end();
|
|
445
|
-
this.connected = false;
|
|
446
|
-
}
|
|
447
|
-
async healthCheck() {
|
|
448
|
-
try {
|
|
449
|
-
await this.pool.query("SELECT 1");
|
|
450
|
-
return true;
|
|
451
|
-
} catch {
|
|
452
|
-
return false;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
async clear() {
|
|
456
|
-
const client = await this.pool.connect();
|
|
457
|
-
try {
|
|
458
|
-
await client.query("BEGIN");
|
|
459
|
-
await client.query("TRUNCATE world_state, world_events, agent_profiles");
|
|
460
|
-
await client.query("COMMIT");
|
|
461
|
-
} catch (error) {
|
|
462
|
-
await client.query("ROLLBACK");
|
|
463
|
-
throw error;
|
|
464
|
-
} finally {
|
|
465
|
-
client.release();
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
});
|
|
471
|
-
|
|
472
|
-
// src/persistence/adapters/RedisAdapter.ts
|
|
473
|
-
var RedisAdapter_exports = {};
|
|
474
|
-
__export(RedisAdapter_exports, {
|
|
475
|
-
RedisAdapter: () => RedisAdapter
|
|
476
|
-
});
|
|
477
|
-
import { Redis } from "ioredis";
|
|
478
|
-
var RedisAdapter;
|
|
479
|
-
var init_RedisAdapter = __esm({
|
|
480
|
-
"src/persistence/adapters/RedisAdapter.ts"() {
|
|
481
|
-
"use strict";
|
|
482
|
-
RedisAdapter = class {
|
|
483
|
-
constructor(config) {
|
|
484
|
-
this.config = config;
|
|
485
|
-
this.keyPrefix = config.keyPrefix || "world:";
|
|
486
|
-
this.client = new Redis({
|
|
487
|
-
host: config.host,
|
|
488
|
-
port: config.port || 6379,
|
|
489
|
-
password: config.password,
|
|
490
|
-
db: config.db || 0
|
|
491
|
-
});
|
|
492
|
-
}
|
|
493
|
-
client;
|
|
494
|
-
connected = false;
|
|
495
|
-
keyPrefix;
|
|
496
|
-
async connect() {
|
|
497
|
-
try {
|
|
498
|
-
await this.client.ping();
|
|
499
|
-
this.connected = true;
|
|
500
|
-
} catch (error) {
|
|
501
|
-
throw new Error(`Redis connection failed: ${error.message}`);
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
async saveState(state) {
|
|
505
|
-
const key = `${this.keyPrefix}state`;
|
|
506
|
-
await this.client.set(key, JSON.stringify(state));
|
|
507
|
-
const historyKey = `${this.keyPrefix}state:history`;
|
|
508
|
-
await this.client.zadd(historyKey, state.timestamp, JSON.stringify(state));
|
|
509
|
-
}
|
|
510
|
-
async loadState() {
|
|
511
|
-
const key = `${this.keyPrefix}state`;
|
|
512
|
-
const data = await this.client.get(key);
|
|
513
|
-
if (!data) {
|
|
514
|
-
return null;
|
|
515
|
-
}
|
|
516
|
-
return JSON.parse(data);
|
|
517
|
-
}
|
|
518
|
-
async saveEvent(event) {
|
|
519
|
-
const eventsKey = `${this.keyPrefix}events`;
|
|
520
|
-
await this.client.zadd(eventsKey, event.timestamp, JSON.stringify(event));
|
|
521
|
-
const typeKey = `${this.keyPrefix}events:type:${event.type}`;
|
|
522
|
-
await this.client.zadd(typeKey, event.timestamp, JSON.stringify(event));
|
|
523
|
-
if (event.agentUrl) {
|
|
524
|
-
const agentKey = `${this.keyPrefix}events:agent:${event.agentUrl}`;
|
|
525
|
-
await this.client.zadd(agentKey, event.timestamp, JSON.stringify(event));
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
async getEvents(filter) {
|
|
529
|
-
let key = `${this.keyPrefix}events`;
|
|
530
|
-
if (filter?.type) {
|
|
531
|
-
key = `${this.keyPrefix}events:type:${filter.type}`;
|
|
532
|
-
} else if (filter?.agentUrl) {
|
|
533
|
-
key = `${this.keyPrefix}events:agent:${filter.agentUrl}`;
|
|
534
|
-
}
|
|
535
|
-
const min = filter?.since || "-inf";
|
|
536
|
-
const max = filter?.until || "+inf";
|
|
537
|
-
const count = filter?.limit || -1;
|
|
538
|
-
const results = await this.client.zrevrangebyscore(
|
|
539
|
-
key,
|
|
540
|
-
max,
|
|
541
|
-
min,
|
|
542
|
-
"LIMIT",
|
|
543
|
-
0,
|
|
544
|
-
count === -1 ? 100 : count
|
|
545
|
-
);
|
|
546
|
-
return results.map((r) => JSON.parse(r));
|
|
547
|
-
}
|
|
548
|
-
async saveAgent(profile) {
|
|
549
|
-
const key = `${this.keyPrefix}agent:${profile.url}`;
|
|
550
|
-
await this.client.set(key, JSON.stringify(profile));
|
|
551
|
-
const agentsKey = `${this.keyPrefix}agents`;
|
|
552
|
-
await this.client.sadd(agentsKey, profile.url);
|
|
553
|
-
}
|
|
554
|
-
async removeAgent(agentUrl) {
|
|
555
|
-
const key = `${this.keyPrefix}agent:${agentUrl}`;
|
|
556
|
-
await this.client.del(key);
|
|
557
|
-
const agentsKey = `${this.keyPrefix}agents`;
|
|
558
|
-
await this.client.srem(agentsKey, agentUrl);
|
|
559
|
-
}
|
|
560
|
-
async getAgents() {
|
|
561
|
-
const agentsKey = `${this.keyPrefix}agents`;
|
|
562
|
-
const urls = await this.client.smembers(agentsKey);
|
|
563
|
-
if (urls.length === 0) {
|
|
564
|
-
return [];
|
|
565
|
-
}
|
|
566
|
-
const keys = urls.map((url) => `${this.keyPrefix}agent:${url}`);
|
|
567
|
-
const results = await this.client.mget(...keys);
|
|
568
|
-
return results.filter((r) => r !== null).map((r) => JSON.parse(r));
|
|
569
|
-
}
|
|
570
|
-
async getAgent(agentUrl) {
|
|
571
|
-
const key = `${this.keyPrefix}agent:${agentUrl}`;
|
|
572
|
-
const data = await this.client.get(key);
|
|
573
|
-
if (!data) {
|
|
574
|
-
return null;
|
|
575
|
-
}
|
|
576
|
-
return JSON.parse(data);
|
|
577
|
-
}
|
|
578
|
-
async disconnect() {
|
|
579
|
-
await this.client.quit();
|
|
580
|
-
this.connected = false;
|
|
581
|
-
}
|
|
582
|
-
async healthCheck() {
|
|
583
|
-
try {
|
|
584
|
-
await this.client.ping();
|
|
585
|
-
return true;
|
|
586
|
-
} catch {
|
|
587
|
-
return false;
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
async clear() {
|
|
591
|
-
const pattern = `${this.keyPrefix}*`;
|
|
592
|
-
const keys = await this.client.keys(pattern);
|
|
593
|
-
if (keys.length > 0) {
|
|
594
|
-
await this.client.del(...keys);
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
};
|
|
598
|
-
}
|
|
599
|
-
});
|
|
600
|
-
|
|
601
|
-
// src/persistence/adapters/MongoAdapter.ts
|
|
602
|
-
var MongoAdapter_exports = {};
|
|
603
|
-
__export(MongoAdapter_exports, {
|
|
604
|
-
MongoAdapter: () => MongoAdapter
|
|
605
|
-
});
|
|
606
|
-
import { MongoClient } from "mongodb";
|
|
607
|
-
var MongoAdapter;
|
|
608
|
-
var init_MongoAdapter = __esm({
|
|
609
|
-
"src/persistence/adapters/MongoAdapter.ts"() {
|
|
610
|
-
"use strict";
|
|
611
|
-
MongoAdapter = class {
|
|
612
|
-
constructor(config) {
|
|
613
|
-
this.config = config;
|
|
614
|
-
this.client = new MongoClient(config.url, {
|
|
615
|
-
useUnifiedTopology: config.useUnifiedTopology !== false
|
|
616
|
-
});
|
|
617
|
-
}
|
|
618
|
-
client;
|
|
619
|
-
db;
|
|
620
|
-
stateCollection;
|
|
621
|
-
eventsCollection;
|
|
622
|
-
agentsCollection;
|
|
623
|
-
connected = false;
|
|
624
|
-
async connect() {
|
|
625
|
-
try {
|
|
626
|
-
await this.client.connect();
|
|
627
|
-
this.db = this.client.db(this.config.database);
|
|
628
|
-
this.stateCollection = this.db.collection("world_state");
|
|
629
|
-
this.eventsCollection = this.db.collection("world_events");
|
|
630
|
-
this.agentsCollection = this.db.collection("agent_profiles");
|
|
631
|
-
await this.initIndexes();
|
|
632
|
-
this.connected = true;
|
|
633
|
-
} catch (error) {
|
|
634
|
-
throw new Error(`MongoDB connection failed: ${error.message}`);
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
async initIndexes() {
|
|
638
|
-
await this.eventsCollection.createIndex({ type: 1 });
|
|
639
|
-
await this.eventsCollection.createIndex({ timestamp: -1 });
|
|
640
|
-
await this.eventsCollection.createIndex({ agentUrl: 1 });
|
|
641
|
-
await this.eventsCollection.createIndex({ type: 1, timestamp: -1 });
|
|
642
|
-
await this.agentsCollection.createIndex({ url: 1 }, { unique: true });
|
|
643
|
-
await this.agentsCollection.createIndex({ joinedAt: 1 });
|
|
644
|
-
await this.stateCollection.createIndex({ timestamp: -1 });
|
|
645
|
-
}
|
|
646
|
-
async saveState(state) {
|
|
647
|
-
await this.stateCollection.insertOne({
|
|
648
|
-
...state,
|
|
649
|
-
_createdAt: /* @__PURE__ */ new Date()
|
|
650
|
-
});
|
|
651
|
-
}
|
|
652
|
-
async loadState() {
|
|
653
|
-
const doc = await this.stateCollection.findOne(
|
|
654
|
-
{},
|
|
655
|
-
{ sort: { timestamp: -1 } }
|
|
656
|
-
);
|
|
657
|
-
if (!doc) {
|
|
658
|
-
return null;
|
|
659
|
-
}
|
|
660
|
-
const { _id, _createdAt, ...state } = doc;
|
|
661
|
-
return state;
|
|
662
|
-
}
|
|
663
|
-
async saveEvent(event) {
|
|
664
|
-
await this.eventsCollection.insertOne({
|
|
665
|
-
_id: event.id,
|
|
666
|
-
...event,
|
|
667
|
-
_createdAt: /* @__PURE__ */ new Date()
|
|
668
|
-
});
|
|
669
|
-
}
|
|
670
|
-
async getEvents(filter) {
|
|
671
|
-
const query = {};
|
|
672
|
-
if (filter?.type) {
|
|
673
|
-
query.type = filter.type;
|
|
674
|
-
}
|
|
675
|
-
if (filter?.agentUrl) {
|
|
676
|
-
query.agentUrl = filter.agentUrl;
|
|
677
|
-
}
|
|
678
|
-
if (filter?.since || filter?.until) {
|
|
679
|
-
query.timestamp = {};
|
|
680
|
-
if (filter.since) {
|
|
681
|
-
query.timestamp.$gte = filter.since;
|
|
682
|
-
}
|
|
683
|
-
if (filter.until) {
|
|
684
|
-
query.timestamp.$lte = filter.until;
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
const cursor = this.eventsCollection.find(query).sort({ timestamp: -1 });
|
|
688
|
-
if (filter?.limit) {
|
|
689
|
-
cursor.limit(filter.limit);
|
|
690
|
-
}
|
|
691
|
-
const docs = await cursor.toArray();
|
|
692
|
-
return docs.map((doc) => {
|
|
693
|
-
const { _id, _createdAt, ...event } = doc;
|
|
694
|
-
return event;
|
|
695
|
-
});
|
|
696
|
-
}
|
|
697
|
-
async saveAgent(profile) {
|
|
698
|
-
await this.agentsCollection.updateOne(
|
|
699
|
-
{ url: profile.url },
|
|
700
|
-
{ $set: { ...profile, _updatedAt: /* @__PURE__ */ new Date() } },
|
|
701
|
-
{ upsert: true }
|
|
702
|
-
);
|
|
703
|
-
}
|
|
704
|
-
async removeAgent(agentUrl) {
|
|
705
|
-
await this.agentsCollection.deleteOne({ url: agentUrl });
|
|
706
|
-
}
|
|
707
|
-
async getAgents() {
|
|
708
|
-
const docs = await this.agentsCollection.find({}).sort({ joinedAt: 1 }).toArray();
|
|
709
|
-
return docs.map((doc) => {
|
|
710
|
-
const { _id, _updatedAt, ...profile } = doc;
|
|
711
|
-
return profile;
|
|
712
|
-
});
|
|
713
|
-
}
|
|
714
|
-
async getAgent(agentUrl) {
|
|
715
|
-
const doc = await this.agentsCollection.findOne({ url: agentUrl });
|
|
716
|
-
if (!doc) {
|
|
717
|
-
return null;
|
|
718
|
-
}
|
|
719
|
-
const { _id, _updatedAt, ...profile } = doc;
|
|
720
|
-
return profile;
|
|
721
|
-
}
|
|
722
|
-
async disconnect() {
|
|
723
|
-
await this.client.close();
|
|
724
|
-
this.connected = false;
|
|
725
|
-
}
|
|
726
|
-
async healthCheck() {
|
|
727
|
-
try {
|
|
728
|
-
await this.db.admin().ping();
|
|
729
|
-
return true;
|
|
730
|
-
} catch {
|
|
731
|
-
return false;
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
async clear() {
|
|
735
|
-
await Promise.all([
|
|
736
|
-
this.stateCollection.deleteMany({}),
|
|
737
|
-
this.eventsCollection.deleteMany({}),
|
|
738
|
-
this.agentsCollection.deleteMany({})
|
|
739
|
-
]);
|
|
740
|
-
}
|
|
741
|
-
};
|
|
742
|
-
}
|
|
743
|
-
});
|
|
744
|
-
|
|
745
|
-
// src/persistence/adapters/LevelDBAdapter.ts
|
|
746
|
-
var LevelDBAdapter_exports = {};
|
|
747
|
-
__export(LevelDBAdapter_exports, {
|
|
748
|
-
LevelDBAdapter: () => LevelDBAdapter
|
|
749
|
-
});
|
|
750
|
-
import { Level } from "level";
|
|
751
|
-
var LevelDBAdapter;
|
|
752
|
-
var init_LevelDBAdapter = __esm({
|
|
753
|
-
"src/persistence/adapters/LevelDBAdapter.ts"() {
|
|
754
|
-
"use strict";
|
|
755
|
-
LevelDBAdapter = class {
|
|
756
|
-
constructor(config) {
|
|
757
|
-
this.config = config;
|
|
758
|
-
}
|
|
759
|
-
db;
|
|
760
|
-
connected = false;
|
|
761
|
-
async connect() {
|
|
762
|
-
try {
|
|
763
|
-
this.db = new Level(this.config.path, {
|
|
764
|
-
valueEncoding: "json"
|
|
765
|
-
});
|
|
766
|
-
await this.db.open();
|
|
767
|
-
this.connected = true;
|
|
768
|
-
} catch (error) {
|
|
769
|
-
throw new Error(`LevelDB connection failed: ${error.message}`);
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
async saveState(state) {
|
|
773
|
-
await this.db.put("state:current", JSON.stringify(state));
|
|
774
|
-
const historyKey = `state:history:${state.timestamp}`;
|
|
775
|
-
await this.db.put(historyKey, JSON.stringify(state));
|
|
776
|
-
}
|
|
777
|
-
async loadState() {
|
|
778
|
-
try {
|
|
779
|
-
const data = await this.db.get("state:current");
|
|
780
|
-
return JSON.parse(data);
|
|
781
|
-
} catch (error) {
|
|
782
|
-
if (error.code === "LEVEL_NOT_FOUND") {
|
|
783
|
-
return null;
|
|
784
|
-
}
|
|
785
|
-
throw error;
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
async saveEvent(event) {
|
|
789
|
-
const key = `event:${event.timestamp}:${event.id}`;
|
|
790
|
-
await this.db.put(key, JSON.stringify(event));
|
|
791
|
-
const typeKey = `event:type:${event.type}:${event.timestamp}:${event.id}`;
|
|
792
|
-
await this.db.put(typeKey, JSON.stringify(event));
|
|
793
|
-
if (event.agentUrl) {
|
|
794
|
-
const agentKey = `event:agent:${event.agentUrl}:${event.timestamp}:${event.id}`;
|
|
795
|
-
await this.db.put(agentKey, JSON.stringify(event));
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
async getEvents(filter) {
|
|
799
|
-
const events = [];
|
|
800
|
-
let prefix = "event:";
|
|
801
|
-
if (filter?.type) {
|
|
802
|
-
prefix = `event:type:${filter.type}:`;
|
|
803
|
-
} else if (filter?.agentUrl) {
|
|
804
|
-
prefix = `event:agent:${filter.agentUrl}:`;
|
|
805
|
-
}
|
|
806
|
-
const iterator = this.db.iterator({
|
|
807
|
-
gte: prefix,
|
|
808
|
-
lte: prefix + "\uFFFF",
|
|
809
|
-
reverse: true,
|
|
810
|
-
// Most recent first
|
|
811
|
-
limit: filter?.limit || -1
|
|
812
|
-
});
|
|
813
|
-
for await (const [key, value] of iterator) {
|
|
814
|
-
const event = JSON.parse(value);
|
|
815
|
-
if (filter?.since && event.timestamp < filter.since) continue;
|
|
816
|
-
if (filter?.until && event.timestamp > filter.until) continue;
|
|
817
|
-
if (filter?.type && !prefix.includes("type:") && event.type !== filter.type) {
|
|
818
|
-
continue;
|
|
819
|
-
}
|
|
820
|
-
if (filter?.agentUrl && !prefix.includes("agent:") && event.agentUrl !== filter.agentUrl) {
|
|
821
|
-
continue;
|
|
822
|
-
}
|
|
823
|
-
events.push(event);
|
|
824
|
-
if (filter?.limit && events.length >= filter.limit) {
|
|
825
|
-
break;
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
return events;
|
|
829
|
-
}
|
|
830
|
-
async saveAgent(profile) {
|
|
831
|
-
const key = `agent:${profile.url}`;
|
|
832
|
-
await this.db.put(key, JSON.stringify(profile));
|
|
833
|
-
const listKey = `agent:list:${profile.joinedAt}:${profile.url}`;
|
|
834
|
-
await this.db.put(listKey, profile.url);
|
|
835
|
-
}
|
|
836
|
-
async removeAgent(agentUrl) {
|
|
837
|
-
const key = `agent:${agentUrl}`;
|
|
838
|
-
try {
|
|
839
|
-
const data = await this.db.get(key);
|
|
840
|
-
const profile = JSON.parse(data);
|
|
841
|
-
await this.db.del(key);
|
|
842
|
-
const listKey = `agent:list:${profile.joinedAt}:${agentUrl}`;
|
|
843
|
-
await this.db.del(listKey);
|
|
844
|
-
} catch (error) {
|
|
845
|
-
if (error.code !== "LEVEL_NOT_FOUND") {
|
|
846
|
-
throw error;
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
async getAgents() {
|
|
851
|
-
const agents = [];
|
|
852
|
-
const iterator = this.db.iterator({
|
|
853
|
-
gte: "agent:list:",
|
|
854
|
-
lte: "agent:list:\uFFFF"
|
|
855
|
-
});
|
|
856
|
-
for await (const [key, agentUrl] of iterator) {
|
|
857
|
-
try {
|
|
858
|
-
const data = await this.db.get(`agent:${agentUrl}`);
|
|
859
|
-
agents.push(JSON.parse(data));
|
|
860
|
-
} catch (error) {
|
|
861
|
-
if (error.code !== "LEVEL_NOT_FOUND") {
|
|
862
|
-
throw error;
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
return agents;
|
|
867
|
-
}
|
|
868
|
-
async getAgent(agentUrl) {
|
|
869
|
-
try {
|
|
870
|
-
const data = await this.db.get(`agent:${agentUrl}`);
|
|
871
|
-
return JSON.parse(data);
|
|
872
|
-
} catch (error) {
|
|
873
|
-
if (error.code === "LEVEL_NOT_FOUND") {
|
|
874
|
-
return null;
|
|
875
|
-
}
|
|
876
|
-
throw error;
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
async disconnect() {
|
|
880
|
-
await this.db.close();
|
|
881
|
-
this.connected = false;
|
|
882
|
-
}
|
|
883
|
-
async healthCheck() {
|
|
884
|
-
try {
|
|
885
|
-
await this.db.get("health:check").catch(() => {
|
|
886
|
-
});
|
|
887
|
-
return true;
|
|
888
|
-
} catch {
|
|
889
|
-
return false;
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
async clear() {
|
|
893
|
-
await this.db.clear();
|
|
894
|
-
}
|
|
895
|
-
};
|
|
896
|
-
}
|
|
897
|
-
});
|
|
898
|
-
|
|
899
|
-
// src/logger.ts
|
|
900
|
-
import winston from "winston";
|
|
901
|
-
function createLogger(moduleName) {
|
|
902
|
-
return logger.child({ module: moduleName });
|
|
903
|
-
}
|
|
904
|
-
var logLevel, logger;
|
|
905
|
-
var init_logger = __esm({
|
|
906
|
-
"src/logger.ts"() {
|
|
907
|
-
"use strict";
|
|
908
|
-
logLevel = process.env.LOG_LEVEL || "info";
|
|
909
|
-
logger = winston.createLogger({
|
|
910
|
-
level: logLevel,
|
|
911
|
-
format: winston.format.combine(
|
|
912
|
-
winston.format.timestamp(),
|
|
913
|
-
winston.format.colorize(),
|
|
914
|
-
winston.format.printf(({ level, message, timestamp, ...meta }) => {
|
|
915
|
-
const metaStr = Object.keys(meta).length ? ` ${JSON.stringify(meta)}` : "";
|
|
916
|
-
return `${timestamp} [${level}] ${message}${metaStr}`;
|
|
917
|
-
})
|
|
918
|
-
),
|
|
919
|
-
transports: [new winston.transports.Console()]
|
|
920
|
-
});
|
|
921
|
-
}
|
|
922
|
-
});
|
|
923
|
-
|
|
924
|
-
// src/discovery/CardFetcher.ts
|
|
925
|
-
var CardFetcher_exports = {};
|
|
926
|
-
__export(CardFetcher_exports, {
|
|
927
|
-
CardFetcher: () => CardFetcher,
|
|
928
|
-
normalizeAgentUrl: () => normalizeAgentUrl
|
|
929
|
-
});
|
|
930
|
-
function normalizeAgentUrl(url) {
|
|
931
|
-
try {
|
|
932
|
-
const parsed = new URL(url);
|
|
933
|
-
return `${parsed.protocol}//${parsed.host}`;
|
|
934
|
-
} catch {
|
|
935
|
-
return url;
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
var logger2, CardFetcher;
|
|
939
|
-
var init_CardFetcher = __esm({
|
|
940
|
-
"src/discovery/CardFetcher.ts"() {
|
|
941
|
-
"use strict";
|
|
942
|
-
init_logger();
|
|
943
|
-
logger2 = createLogger("CardFetcher");
|
|
944
|
-
CardFetcher = class {
|
|
945
|
-
/**
|
|
946
|
-
* Fetch an agent's card from their A2A endpoint.
|
|
947
|
-
*
|
|
948
|
-
* @param agentUrl Base URL of the agent (e.g., http://localhost:3000)
|
|
949
|
-
* @returns Fetch result with card or error
|
|
950
|
-
*/
|
|
951
|
-
async fetchCard(agentUrl) {
|
|
952
|
-
try {
|
|
953
|
-
const cardUrl = new URL("/.well-known/agent-card.json", agentUrl).toString();
|
|
954
|
-
logger2.debug(`Fetching agent card from ${cardUrl}`);
|
|
955
|
-
const response = await fetch(cardUrl, {
|
|
956
|
-
method: "GET",
|
|
957
|
-
headers: {
|
|
958
|
-
"Accept": "application/json",
|
|
959
|
-
"User-Agent": "@moltium/world-core/0.1.0"
|
|
960
|
-
},
|
|
961
|
-
signal: AbortSignal.timeout(5e3)
|
|
962
|
-
// 5 second timeout
|
|
963
|
-
});
|
|
964
|
-
if (!response.ok) {
|
|
965
|
-
return {
|
|
966
|
-
success: false,
|
|
967
|
-
error: `HTTP ${response.status}: ${response.statusText}`
|
|
968
|
-
};
|
|
969
|
-
}
|
|
970
|
-
const card = await response.json();
|
|
971
|
-
if (!card.name || !card.protocolVersion || !card.url || !card.skills) {
|
|
972
|
-
return {
|
|
973
|
-
success: false,
|
|
974
|
-
error: "Invalid agent card: missing required fields"
|
|
975
|
-
};
|
|
976
|
-
}
|
|
977
|
-
logger2.info(`Successfully fetched card for agent: ${card.name}`, {
|
|
978
|
-
protocolVersion: card.protocolVersion,
|
|
979
|
-
skillCount: card.skills.length
|
|
980
|
-
});
|
|
981
|
-
return {
|
|
982
|
-
success: true,
|
|
983
|
-
card
|
|
984
|
-
};
|
|
985
|
-
} catch (error) {
|
|
986
|
-
logger2.error(`Failed to fetch agent card from ${agentUrl}:`, error.message);
|
|
987
|
-
return {
|
|
988
|
-
success: false,
|
|
989
|
-
error: error.message || "Unknown error"
|
|
990
|
-
};
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
/**
|
|
994
|
-
* Fetch multiple agent cards in parallel.
|
|
995
|
-
*
|
|
996
|
-
* @param agentUrls Array of agent URLs
|
|
997
|
-
* @returns Array of fetch results
|
|
998
|
-
*/
|
|
999
|
-
async fetchCards(agentUrls) {
|
|
1000
|
-
logger2.info(`Fetching ${agentUrls.length} agent cards...`);
|
|
1001
|
-
const results = await Promise.all(
|
|
1002
|
-
agentUrls.map((url) => this.fetchCard(url))
|
|
1003
|
-
);
|
|
1004
|
-
const successCount = results.filter((r) => r.success).length;
|
|
1005
|
-
logger2.info(`Fetched ${successCount}/${agentUrls.length} agent cards successfully`);
|
|
1006
|
-
return results;
|
|
1007
|
-
}
|
|
1008
|
-
/**
|
|
1009
|
-
* Verify that an agent card is valid for A2A protocol v0.3.0.
|
|
1010
|
-
*
|
|
1011
|
-
* @param card Agent card to verify
|
|
1012
|
-
* @returns True if valid
|
|
1013
|
-
*/
|
|
1014
|
-
verifyCard(card) {
|
|
1015
|
-
if (!card.name || !card.protocolVersion || !card.url || !card.skills) {
|
|
1016
|
-
logger2.warn("Agent card missing required fields", { name: card.name });
|
|
1017
|
-
return false;
|
|
1018
|
-
}
|
|
1019
|
-
if (!card.protocolVersion.startsWith("0.3")) {
|
|
1020
|
-
logger2.warn("Agent card has incompatible protocol version", {
|
|
1021
|
-
name: card.name,
|
|
1022
|
-
version: card.protocolVersion
|
|
1023
|
-
});
|
|
1024
|
-
return false;
|
|
1025
|
-
}
|
|
1026
|
-
if (!Array.isArray(card.skills) || card.skills.length === 0) {
|
|
1027
|
-
logger2.warn("Agent card has no skills", { name: card.name });
|
|
1028
|
-
return false;
|
|
1029
|
-
}
|
|
1030
|
-
if (!card.capabilities || typeof card.capabilities !== "object") {
|
|
1031
|
-
logger2.warn("Agent card missing capabilities", { name: card.name });
|
|
1032
|
-
return false;
|
|
1033
|
-
}
|
|
1034
|
-
return true;
|
|
1035
|
-
}
|
|
1036
|
-
};
|
|
1037
|
-
}
|
|
1038
|
-
});
|
|
1
|
+
import {
|
|
2
|
+
CardFetcher,
|
|
3
|
+
createLogger,
|
|
4
|
+
logger,
|
|
5
|
+
normalizeAgentUrl
|
|
6
|
+
} from "./chunk-JW3PZRCW.js";
|
|
1039
7
|
|
|
1040
8
|
// src/config/types.ts
|
|
1041
9
|
function profileFromCard(card, walletAddress) {
|
|
@@ -1225,7 +193,7 @@ var InMemoryAdapter = class {
|
|
|
1225
193
|
};
|
|
1226
194
|
|
|
1227
195
|
// src/persistence/PersistenceFactory.ts
|
|
1228
|
-
function createPersistence(config) {
|
|
196
|
+
async function createPersistence(config) {
|
|
1229
197
|
switch (config.type) {
|
|
1230
198
|
case "memory":
|
|
1231
199
|
return new InMemoryAdapter();
|
|
@@ -1255,12 +223,120 @@ function createPersistence(config) {
|
|
|
1255
223
|
throw new Error(`Unknown persistence type: ${config.type}`);
|
|
1256
224
|
}
|
|
1257
225
|
}
|
|
1258
|
-
function createSQLiteAdapter(config) {
|
|
226
|
+
async function createSQLiteAdapter(config) {
|
|
1259
227
|
try {
|
|
1260
|
-
const
|
|
1261
|
-
return new
|
|
228
|
+
const Database = (await import("better-sqlite3")).default;
|
|
229
|
+
return new class {
|
|
230
|
+
db;
|
|
231
|
+
async connect() {
|
|
232
|
+
this.db = new Database(config.filename);
|
|
233
|
+
this.db.exec(`
|
|
234
|
+
CREATE TABLE IF NOT EXISTS world_state (
|
|
235
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
236
|
+
phase TEXT NOT NULL,
|
|
237
|
+
tick INTEGER NOT NULL,
|
|
238
|
+
round INTEGER NOT NULL,
|
|
239
|
+
timestamp INTEGER NOT NULL,
|
|
240
|
+
metadata TEXT
|
|
241
|
+
);
|
|
242
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
243
|
+
id TEXT PRIMARY KEY,
|
|
244
|
+
type TEXT NOT NULL,
|
|
245
|
+
agent_url TEXT,
|
|
246
|
+
timestamp INTEGER NOT NULL,
|
|
247
|
+
data TEXT
|
|
248
|
+
);
|
|
249
|
+
CREATE TABLE IF NOT EXISTS agents (
|
|
250
|
+
url TEXT PRIMARY KEY,
|
|
251
|
+
name TEXT NOT NULL,
|
|
252
|
+
protocol_version TEXT NOT NULL,
|
|
253
|
+
skills TEXT NOT NULL,
|
|
254
|
+
capabilities TEXT NOT NULL,
|
|
255
|
+
joined_at INTEGER NOT NULL,
|
|
256
|
+
role TEXT,
|
|
257
|
+
metadata TEXT,
|
|
258
|
+
wallet_address TEXT
|
|
259
|
+
);
|
|
260
|
+
CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
|
|
261
|
+
CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp);
|
|
262
|
+
CREATE INDEX IF NOT EXISTS idx_events_agent ON events(agent_url);
|
|
263
|
+
`);
|
|
264
|
+
}
|
|
265
|
+
async saveState(state) {
|
|
266
|
+
const stmt = this.db.prepare(`INSERT OR REPLACE INTO world_state (id, phase, tick, round, timestamp, metadata) VALUES (1, ?, ?, ?, ?, ?)`);
|
|
267
|
+
stmt.run(state.phase, state.tick, state.round, state.timestamp, JSON.stringify(state.metadata));
|
|
268
|
+
}
|
|
269
|
+
async loadState() {
|
|
270
|
+
const stmt = this.db.prepare("SELECT * FROM world_state WHERE id = 1");
|
|
271
|
+
const row = stmt.get();
|
|
272
|
+
if (!row) return null;
|
|
273
|
+
return { phase: row.phase, tick: row.tick, round: row.round, timestamp: row.timestamp, metadata: JSON.parse(row.metadata || "{}") };
|
|
274
|
+
}
|
|
275
|
+
async saveEvent(event) {
|
|
276
|
+
const stmt = this.db.prepare(`INSERT INTO events (id, type, agent_url, timestamp, data) VALUES (?, ?, ?, ?, ?)`);
|
|
277
|
+
stmt.run(event.id, event.type, event.agentUrl || null, event.timestamp, JSON.stringify(event.data || {}));
|
|
278
|
+
}
|
|
279
|
+
async getEvents(filter) {
|
|
280
|
+
let query = "SELECT * FROM events WHERE 1=1";
|
|
281
|
+
const params = [];
|
|
282
|
+
if (filter?.type) {
|
|
283
|
+
query += " AND type = ?";
|
|
284
|
+
params.push(filter.type);
|
|
285
|
+
}
|
|
286
|
+
if (filter?.agentUrl) {
|
|
287
|
+
query += " AND agent_url = ?";
|
|
288
|
+
params.push(filter.agentUrl);
|
|
289
|
+
}
|
|
290
|
+
if (filter?.fromTimestamp) {
|
|
291
|
+
query += " AND timestamp >= ?";
|
|
292
|
+
params.push(filter.fromTimestamp);
|
|
293
|
+
}
|
|
294
|
+
if (filter?.toTimestamp) {
|
|
295
|
+
query += " AND timestamp <= ?";
|
|
296
|
+
params.push(filter.toTimestamp);
|
|
297
|
+
}
|
|
298
|
+
query += " ORDER BY timestamp DESC";
|
|
299
|
+
if (filter?.limit) {
|
|
300
|
+
query += " LIMIT ?";
|
|
301
|
+
params.push(filter.limit);
|
|
302
|
+
}
|
|
303
|
+
const stmt = this.db.prepare(query);
|
|
304
|
+
const rows = stmt.all(...params);
|
|
305
|
+
return rows.map((row) => ({ id: row.id, type: row.type, timestamp: row.timestamp, agentUrl: row.agent_url || void 0, data: JSON.parse(row.data || "{}") }));
|
|
306
|
+
}
|
|
307
|
+
async saveAgent(profile) {
|
|
308
|
+
const stmt = this.db.prepare(`INSERT OR REPLACE INTO agents (url, name, protocol_version, skills, capabilities, joined_at, role, metadata, wallet_address) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
309
|
+
stmt.run(profile.url, profile.name, profile.protocolVersion, JSON.stringify(profile.skills), JSON.stringify(profile.capabilities), profile.joinedAt, profile.role || null, JSON.stringify(profile.metadata || {}), profile.walletAddress || null);
|
|
310
|
+
}
|
|
311
|
+
async removeAgent(agentUrl) {
|
|
312
|
+
this.db.prepare("DELETE FROM agents WHERE url = ?").run(agentUrl);
|
|
313
|
+
}
|
|
314
|
+
async getAgents() {
|
|
315
|
+
const rows = this.db.prepare("SELECT * FROM agents ORDER BY joined_at ASC").all();
|
|
316
|
+
return rows.map((row) => ({ url: row.url, name: row.name, protocolVersion: row.protocol_version, skills: JSON.parse(row.skills), capabilities: JSON.parse(row.capabilities), joinedAt: row.joined_at, role: row.role || void 0, metadata: JSON.parse(row.metadata || "{}"), walletAddress: row.wallet_address || void 0 }));
|
|
317
|
+
}
|
|
318
|
+
async getAgent(agentUrl) {
|
|
319
|
+
const row = this.db.prepare("SELECT * FROM agents WHERE url = ?").get(agentUrl);
|
|
320
|
+
if (!row) return null;
|
|
321
|
+
return { url: row.url, name: row.name, protocolVersion: row.protocol_version, skills: JSON.parse(row.skills), capabilities: JSON.parse(row.capabilities), joinedAt: row.joined_at, role: row.role || void 0, metadata: JSON.parse(row.metadata || "{}"), walletAddress: row.wallet_address || void 0 };
|
|
322
|
+
}
|
|
323
|
+
async disconnect() {
|
|
324
|
+
this.db.close();
|
|
325
|
+
}
|
|
326
|
+
async healthCheck() {
|
|
327
|
+
try {
|
|
328
|
+
this.db.prepare("SELECT 1").get();
|
|
329
|
+
return true;
|
|
330
|
+
} catch {
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
async clear() {
|
|
335
|
+
this.db.exec("DELETE FROM world_state; DELETE FROM events; DELETE FROM agents;");
|
|
336
|
+
}
|
|
337
|
+
}();
|
|
1262
338
|
} catch (error) {
|
|
1263
|
-
if (error.code === "MODULE_NOT_FOUND") {
|
|
339
|
+
if (error.code === "ERR_MODULE_NOT_FOUND" || error.code === "MODULE_NOT_FOUND") {
|
|
1264
340
|
throw new Error(
|
|
1265
341
|
"SQLite adapter requires better-sqlite3. Install it with: npm install better-sqlite3"
|
|
1266
342
|
);
|
|
@@ -1268,12 +344,14 @@ function createSQLiteAdapter(config) {
|
|
|
1268
344
|
throw error;
|
|
1269
345
|
}
|
|
1270
346
|
}
|
|
1271
|
-
function createPostgresAdapter(config) {
|
|
347
|
+
async function createPostgresAdapter(config) {
|
|
1272
348
|
try {
|
|
1273
|
-
const
|
|
1274
|
-
|
|
349
|
+
const pg = await import("pg");
|
|
350
|
+
const Pool = pg.default?.Pool || pg.Pool;
|
|
351
|
+
const { PostgresAdapter } = await import("./PostgresAdapter-PLXDLHVF.js");
|
|
352
|
+
return new PostgresAdapter(config);
|
|
1275
353
|
} catch (error) {
|
|
1276
|
-
if (error.code === "MODULE_NOT_FOUND") {
|
|
354
|
+
if (error.code === "ERR_MODULE_NOT_FOUND" || error.code === "MODULE_NOT_FOUND") {
|
|
1277
355
|
throw new Error(
|
|
1278
356
|
"PostgreSQL adapter requires pg. Install it with: npm install pg"
|
|
1279
357
|
);
|
|
@@ -1281,12 +359,13 @@ function createPostgresAdapter(config) {
|
|
|
1281
359
|
throw error;
|
|
1282
360
|
}
|
|
1283
361
|
}
|
|
1284
|
-
function createRedisAdapter(config) {
|
|
362
|
+
async function createRedisAdapter(config) {
|
|
1285
363
|
try {
|
|
1286
|
-
|
|
1287
|
-
|
|
364
|
+
await import("ioredis");
|
|
365
|
+
const { RedisAdapter } = await import("./RedisAdapter-OL4FVEGL.js");
|
|
366
|
+
return new RedisAdapter(config);
|
|
1288
367
|
} catch (error) {
|
|
1289
|
-
if (error.code === "MODULE_NOT_FOUND") {
|
|
368
|
+
if (error.code === "ERR_MODULE_NOT_FOUND" || error.code === "MODULE_NOT_FOUND") {
|
|
1290
369
|
throw new Error(
|
|
1291
370
|
"Redis adapter requires ioredis. Install it with: npm install ioredis"
|
|
1292
371
|
);
|
|
@@ -1294,12 +373,13 @@ function createRedisAdapter(config) {
|
|
|
1294
373
|
throw error;
|
|
1295
374
|
}
|
|
1296
375
|
}
|
|
1297
|
-
function createMongoAdapter(config) {
|
|
376
|
+
async function createMongoAdapter(config) {
|
|
1298
377
|
try {
|
|
1299
|
-
|
|
1300
|
-
|
|
378
|
+
await import("mongodb");
|
|
379
|
+
const { MongoAdapter } = await import("./MongoAdapter-TCY6JOZH.js");
|
|
380
|
+
return new MongoAdapter(config);
|
|
1301
381
|
} catch (error) {
|
|
1302
|
-
if (error.code === "MODULE_NOT_FOUND") {
|
|
382
|
+
if (error.code === "ERR_MODULE_NOT_FOUND" || error.code === "MODULE_NOT_FOUND") {
|
|
1303
383
|
throw new Error(
|
|
1304
384
|
"MongoDB adapter requires mongodb. Install it with: npm install mongodb"
|
|
1305
385
|
);
|
|
@@ -1307,12 +387,13 @@ function createMongoAdapter(config) {
|
|
|
1307
387
|
throw error;
|
|
1308
388
|
}
|
|
1309
389
|
}
|
|
1310
|
-
function createLevelDBAdapter(config) {
|
|
390
|
+
async function createLevelDBAdapter(config) {
|
|
1311
391
|
try {
|
|
1312
|
-
|
|
1313
|
-
|
|
392
|
+
await import("level");
|
|
393
|
+
const { LevelDBAdapter } = await import("./LevelDBAdapter-ZV2ZTDOV.js");
|
|
394
|
+
return new LevelDBAdapter(config);
|
|
1314
395
|
} catch (error) {
|
|
1315
|
-
if (error.code === "MODULE_NOT_FOUND") {
|
|
396
|
+
if (error.code === "ERR_MODULE_NOT_FOUND" || error.code === "MODULE_NOT_FOUND") {
|
|
1316
397
|
throw new Error(
|
|
1317
398
|
"LevelDB adapter requires level. Install it with: npm install level"
|
|
1318
399
|
);
|
|
@@ -1321,16 +402,11 @@ function createLevelDBAdapter(config) {
|
|
|
1321
402
|
}
|
|
1322
403
|
}
|
|
1323
404
|
|
|
1324
|
-
// src/index.ts
|
|
1325
|
-
init_logger();
|
|
1326
|
-
|
|
1327
405
|
// src/engine/World.ts
|
|
1328
406
|
import { v4 as uuidv4 } from "uuid";
|
|
1329
|
-
init_CardFetcher();
|
|
1330
407
|
|
|
1331
408
|
// src/discovery/AgentEvaluator.ts
|
|
1332
|
-
|
|
1333
|
-
var logger3 = createLogger("AgentEvaluator");
|
|
409
|
+
var logger2 = createLogger("AgentEvaluator");
|
|
1334
410
|
var AgentEvaluator = class {
|
|
1335
411
|
constructor(rules) {
|
|
1336
412
|
this.rules = rules;
|
|
@@ -1344,12 +420,12 @@ var AgentEvaluator = class {
|
|
|
1344
420
|
* @returns Admission decision
|
|
1345
421
|
*/
|
|
1346
422
|
async evaluate(card, currentAgentCount, walletAddress) {
|
|
1347
|
-
|
|
423
|
+
logger2.debug(`Evaluating agent: ${card.name}`, {
|
|
1348
424
|
currentAgents: currentAgentCount,
|
|
1349
425
|
maxAgents: this.rules.maxAgents
|
|
1350
426
|
});
|
|
1351
427
|
if (this.rules.maxAgents && currentAgentCount >= this.rules.maxAgents) {
|
|
1352
|
-
|
|
428
|
+
logger2.info(`Agent ${card.name} rejected: world is full`, {
|
|
1353
429
|
current: currentAgentCount,
|
|
1354
430
|
max: this.rules.maxAgents
|
|
1355
431
|
});
|
|
@@ -1360,7 +436,7 @@ var AgentEvaluator = class {
|
|
|
1360
436
|
}
|
|
1361
437
|
if (this.rules.minProtocolVersion) {
|
|
1362
438
|
if (!this.meetsProtocolVersion(card.protocolVersion, this.rules.minProtocolVersion)) {
|
|
1363
|
-
|
|
439
|
+
logger2.info(`Agent ${card.name} rejected: protocol version too old`, {
|
|
1364
440
|
agent: card.protocolVersion,
|
|
1365
441
|
required: this.rules.minProtocolVersion
|
|
1366
442
|
});
|
|
@@ -1376,7 +452,7 @@ var AgentEvaluator = class {
|
|
|
1376
452
|
(required) => !agentSkillIds.includes(required.toLowerCase())
|
|
1377
453
|
);
|
|
1378
454
|
if (missingSkills.length > 0) {
|
|
1379
|
-
|
|
455
|
+
logger2.info(`Agent ${card.name} rejected: missing required skills`, {
|
|
1380
456
|
missing: missingSkills
|
|
1381
457
|
});
|
|
1382
458
|
return {
|
|
@@ -1391,7 +467,7 @@ var AgentEvaluator = class {
|
|
|
1391
467
|
(required) => agentTags.includes(required.toLowerCase())
|
|
1392
468
|
);
|
|
1393
469
|
if (!hasRequiredTag) {
|
|
1394
|
-
|
|
470
|
+
logger2.info(`Agent ${card.name} rejected: no matching tags`, {
|
|
1395
471
|
required: this.rules.requiredTags
|
|
1396
472
|
});
|
|
1397
473
|
return {
|
|
@@ -1404,19 +480,19 @@ var AgentEvaluator = class {
|
|
|
1404
480
|
const profile = profileFromCard(card, walletAddress);
|
|
1405
481
|
const customDecision = await this.rules.customEvaluator(profile);
|
|
1406
482
|
if (!customDecision.admitted) {
|
|
1407
|
-
|
|
483
|
+
logger2.info(`Agent ${card.name} rejected by custom evaluator`, {
|
|
1408
484
|
reason: customDecision.reason
|
|
1409
485
|
});
|
|
1410
486
|
return customDecision;
|
|
1411
487
|
}
|
|
1412
488
|
if (customDecision.role || customDecision.metadata) {
|
|
1413
|
-
|
|
489
|
+
logger2.debug(`Custom evaluator assigned role/metadata to ${card.name}`, {
|
|
1414
490
|
role: customDecision.role
|
|
1415
491
|
});
|
|
1416
492
|
}
|
|
1417
493
|
return customDecision;
|
|
1418
494
|
}
|
|
1419
|
-
|
|
495
|
+
logger2.info(`Agent ${card.name} admitted to world`);
|
|
1420
496
|
return {
|
|
1421
497
|
admitted: true,
|
|
1422
498
|
reason: "All admission criteria met"
|
|
@@ -1443,9 +519,8 @@ var AgentEvaluator = class {
|
|
|
1443
519
|
};
|
|
1444
520
|
|
|
1445
521
|
// src/blockchain/BlockchainClient.ts
|
|
1446
|
-
init_logger();
|
|
1447
522
|
import { ethers } from "ethers";
|
|
1448
|
-
var
|
|
523
|
+
var logger3 = createLogger("BlockchainClient");
|
|
1449
524
|
var AGENT_REGISTRY_ABI = [
|
|
1450
525
|
"function registerAgent(string agentUrl, string name) external",
|
|
1451
526
|
"function isAgentValid(address wallet) external view returns (bool)",
|
|
@@ -1473,7 +548,7 @@ var BlockchainClient = class {
|
|
|
1473
548
|
this.config = config;
|
|
1474
549
|
this.provider = new ethers.JsonRpcProvider(config.rpcUrl);
|
|
1475
550
|
this.wallet = new ethers.Wallet(config.privateKey, this.provider);
|
|
1476
|
-
|
|
551
|
+
logger3.info("Blockchain client initialized", {
|
|
1477
552
|
network: config.rpcUrl,
|
|
1478
553
|
wallet: this.wallet.address
|
|
1479
554
|
});
|
|
@@ -1493,7 +568,7 @@ var BlockchainClient = class {
|
|
|
1493
568
|
AGENT_REGISTRY_ABI,
|
|
1494
569
|
this.wallet
|
|
1495
570
|
);
|
|
1496
|
-
|
|
571
|
+
logger3.info("Connected to AgentRegistry", {
|
|
1497
572
|
address: this.config.agentRegistryAddress
|
|
1498
573
|
});
|
|
1499
574
|
}
|
|
@@ -1503,7 +578,7 @@ var BlockchainClient = class {
|
|
|
1503
578
|
WORLD_MEMBERSHIP_ABI,
|
|
1504
579
|
this.wallet
|
|
1505
580
|
);
|
|
1506
|
-
|
|
581
|
+
logger3.info("Connected to WorldMembership", {
|
|
1507
582
|
address: this.config.membershipContractAddress
|
|
1508
583
|
});
|
|
1509
584
|
}
|
|
@@ -1513,11 +588,11 @@ var BlockchainClient = class {
|
|
|
1513
588
|
WORLD_TOKEN_ABI,
|
|
1514
589
|
this.wallet
|
|
1515
590
|
);
|
|
1516
|
-
|
|
591
|
+
logger3.info("Connected to WorldToken", {
|
|
1517
592
|
address: this.config.worldTokenAddress
|
|
1518
593
|
});
|
|
1519
594
|
}
|
|
1520
|
-
|
|
595
|
+
logger3.info("Blockchain client ready");
|
|
1521
596
|
}
|
|
1522
597
|
/**
|
|
1523
598
|
* Validate agent on-chain
|
|
@@ -1526,18 +601,18 @@ var BlockchainClient = class {
|
|
|
1526
601
|
*/
|
|
1527
602
|
async validateAgent(walletAddress) {
|
|
1528
603
|
if (!this.agentRegistry) {
|
|
1529
|
-
|
|
604
|
+
logger3.warn("AgentRegistry not configured, skipping on-chain validation");
|
|
1530
605
|
return true;
|
|
1531
606
|
}
|
|
1532
607
|
try {
|
|
1533
608
|
const isValid = await this.agentRegistry.isAgentValid(walletAddress);
|
|
1534
|
-
|
|
609
|
+
logger3.debug("Agent validation result", {
|
|
1535
610
|
wallet: walletAddress,
|
|
1536
611
|
isValid
|
|
1537
612
|
});
|
|
1538
613
|
return isValid;
|
|
1539
614
|
} catch (error) {
|
|
1540
|
-
|
|
615
|
+
logger3.error("Failed to validate agent on-chain", {
|
|
1541
616
|
wallet: walletAddress,
|
|
1542
617
|
error: error.message
|
|
1543
618
|
});
|
|
@@ -1555,7 +630,7 @@ var BlockchainClient = class {
|
|
|
1555
630
|
}
|
|
1556
631
|
try {
|
|
1557
632
|
const entryFee = await this.membershipContract.entryFee();
|
|
1558
|
-
|
|
633
|
+
logger3.info("Minting membership NFT", {
|
|
1559
634
|
agent: agentWallet,
|
|
1560
635
|
entryFee: ethers.formatEther(entryFee)
|
|
1561
636
|
});
|
|
@@ -1563,14 +638,14 @@ var BlockchainClient = class {
|
|
|
1563
638
|
value: entryFee
|
|
1564
639
|
});
|
|
1565
640
|
const receipt = await tx.wait();
|
|
1566
|
-
|
|
641
|
+
logger3.info("Membership NFT minted", {
|
|
1567
642
|
agent: agentWallet,
|
|
1568
643
|
txHash: receipt.hash,
|
|
1569
644
|
blockNumber: receipt.blockNumber
|
|
1570
645
|
});
|
|
1571
646
|
return receipt.hash;
|
|
1572
647
|
} catch (error) {
|
|
1573
|
-
|
|
648
|
+
logger3.error("Failed to mint membership NFT", {
|
|
1574
649
|
agent: agentWallet,
|
|
1575
650
|
error: error.message
|
|
1576
651
|
});
|
|
@@ -1584,14 +659,14 @@ var BlockchainClient = class {
|
|
|
1584
659
|
*/
|
|
1585
660
|
async hasMembership(agentWallet) {
|
|
1586
661
|
if (!this.membershipContract) {
|
|
1587
|
-
|
|
662
|
+
logger3.warn("WorldMembership not configured, skipping membership check");
|
|
1588
663
|
return true;
|
|
1589
664
|
}
|
|
1590
665
|
try {
|
|
1591
666
|
const hasMembership = await this.membershipContract.hasMembership(agentWallet);
|
|
1592
667
|
return hasMembership;
|
|
1593
668
|
} catch (error) {
|
|
1594
|
-
|
|
669
|
+
logger3.error("Failed to check membership", {
|
|
1595
670
|
agent: agentWallet,
|
|
1596
671
|
error: error.message
|
|
1597
672
|
});
|
|
@@ -1608,16 +683,16 @@ var BlockchainClient = class {
|
|
|
1608
683
|
throw new Error("WorldMembership contract not configured");
|
|
1609
684
|
}
|
|
1610
685
|
try {
|
|
1611
|
-
|
|
686
|
+
logger3.info("Revoking membership", { agent: agentWallet });
|
|
1612
687
|
const tx = await this.membershipContract.revokeMembership(agentWallet);
|
|
1613
688
|
const receipt = await tx.wait();
|
|
1614
|
-
|
|
689
|
+
logger3.info("Membership revoked", {
|
|
1615
690
|
agent: agentWallet,
|
|
1616
691
|
txHash: receipt.hash
|
|
1617
692
|
});
|
|
1618
693
|
return receipt.hash;
|
|
1619
694
|
} catch (error) {
|
|
1620
|
-
|
|
695
|
+
logger3.error("Failed to revoke membership", {
|
|
1621
696
|
agent: agentWallet,
|
|
1622
697
|
error: error.message
|
|
1623
698
|
});
|
|
@@ -1635,7 +710,7 @@ var BlockchainClient = class {
|
|
|
1635
710
|
const total = await this.membershipContract.totalMembers();
|
|
1636
711
|
return Number(total);
|
|
1637
712
|
} catch (error) {
|
|
1638
|
-
|
|
713
|
+
logger3.error("Failed to get total members", { error: error.message });
|
|
1639
714
|
return 0;
|
|
1640
715
|
}
|
|
1641
716
|
}
|
|
@@ -1647,16 +722,16 @@ var BlockchainClient = class {
|
|
|
1647
722
|
throw new Error("WorldMembership contract not configured");
|
|
1648
723
|
}
|
|
1649
724
|
try {
|
|
1650
|
-
|
|
725
|
+
logger3.info("Withdrawing entry fees");
|
|
1651
726
|
const tx = await this.membershipContract.withdrawFees();
|
|
1652
727
|
const receipt = await tx.wait();
|
|
1653
|
-
|
|
728
|
+
logger3.info("Fees withdrawn", {
|
|
1654
729
|
txHash: receipt.hash,
|
|
1655
730
|
blockNumber: receipt.blockNumber
|
|
1656
731
|
});
|
|
1657
732
|
return receipt.hash;
|
|
1658
733
|
} catch (error) {
|
|
1659
|
-
|
|
734
|
+
logger3.error("Failed to withdraw fees", { error: error.message });
|
|
1660
735
|
throw error;
|
|
1661
736
|
}
|
|
1662
737
|
}
|
|
@@ -1677,15 +752,14 @@ var BlockchainClient = class {
|
|
|
1677
752
|
const fee = await this.membershipContract.entryFee();
|
|
1678
753
|
return ethers.formatEther(fee);
|
|
1679
754
|
} catch (error) {
|
|
1680
|
-
|
|
755
|
+
logger3.error("Failed to get entry fee", { error: error.message });
|
|
1681
756
|
return "0";
|
|
1682
757
|
}
|
|
1683
758
|
}
|
|
1684
759
|
};
|
|
1685
760
|
|
|
1686
761
|
// src/engine/World.ts
|
|
1687
|
-
|
|
1688
|
-
var logger5 = createLogger("World");
|
|
762
|
+
var logger4 = createLogger("World");
|
|
1689
763
|
var World = class {
|
|
1690
764
|
constructor(config) {
|
|
1691
765
|
this.config = config;
|
|
@@ -1700,7 +774,7 @@ var World = class {
|
|
|
1700
774
|
this.agents = /* @__PURE__ */ new Map();
|
|
1701
775
|
this.cardFetcher = new CardFetcher();
|
|
1702
776
|
this.evaluator = new AgentEvaluator(config.admission);
|
|
1703
|
-
|
|
777
|
+
logger4.info(`World "${config.name}" created`, {
|
|
1704
778
|
type: config.type || "generic",
|
|
1705
779
|
maxAgents: config.admission.maxAgents
|
|
1706
780
|
});
|
|
@@ -1717,17 +791,17 @@ var World = class {
|
|
|
1717
791
|
* Initialize the world (connect persistence, restore state, discover agents)
|
|
1718
792
|
*/
|
|
1719
793
|
async init() {
|
|
1720
|
-
|
|
794
|
+
logger4.info("Initializing world...");
|
|
1721
795
|
this.setState("initializing");
|
|
1722
796
|
try {
|
|
1723
797
|
if (this.config.persistence) {
|
|
1724
|
-
|
|
1725
|
-
this.persistence = createPersistence(this.config.persistence);
|
|
798
|
+
logger4.info("Connecting to persistence backend:", this.config.persistence.type);
|
|
799
|
+
this.persistence = await createPersistence(this.config.persistence);
|
|
1726
800
|
await this.persistence.connect();
|
|
1727
801
|
const savedState = await this.persistence.loadState();
|
|
1728
802
|
if (savedState) {
|
|
1729
803
|
this.state = savedState;
|
|
1730
|
-
|
|
804
|
+
logger4.info("Restored world state from persistence", {
|
|
1731
805
|
phase: savedState.phase,
|
|
1732
806
|
tick: savedState.tick
|
|
1733
807
|
});
|
|
@@ -1735,16 +809,16 @@ var World = class {
|
|
|
1735
809
|
for (const agent of savedAgents) {
|
|
1736
810
|
this.agents.set(agent.url, agent);
|
|
1737
811
|
}
|
|
1738
|
-
|
|
812
|
+
logger4.info(`Restored ${savedAgents.length} agents from persistence`);
|
|
1739
813
|
}
|
|
1740
814
|
}
|
|
1741
815
|
if (this.config.blockchain) {
|
|
1742
|
-
|
|
816
|
+
logger4.info("Initializing blockchain client...");
|
|
1743
817
|
this.blockchainClient = new BlockchainClient(this.config.blockchain);
|
|
1744
818
|
await this.blockchainClient.init();
|
|
1745
819
|
}
|
|
1746
820
|
if (this.config.agentUrls && this.config.agentUrls.length > 0) {
|
|
1747
|
-
|
|
821
|
+
logger4.info(`Discovering ${this.config.agentUrls.length} pre-configured agents...`);
|
|
1748
822
|
const results = await this.cardFetcher.fetchCards(this.config.agentUrls);
|
|
1749
823
|
for (let i = 0; i < results.length; i++) {
|
|
1750
824
|
const result = results[i];
|
|
@@ -1752,7 +826,7 @@ var World = class {
|
|
|
1752
826
|
try {
|
|
1753
827
|
await this.admitAgent(result.card);
|
|
1754
828
|
} catch (error) {
|
|
1755
|
-
|
|
829
|
+
logger4.warn(`Failed to admit pre-configured agent:`, error.message);
|
|
1756
830
|
}
|
|
1757
831
|
}
|
|
1758
832
|
}
|
|
@@ -1761,12 +835,12 @@ var World = class {
|
|
|
1761
835
|
this.startAutoSave();
|
|
1762
836
|
}
|
|
1763
837
|
this.setState("ready");
|
|
1764
|
-
|
|
838
|
+
logger4.info("World initialized successfully", {
|
|
1765
839
|
agents: this.agents.size,
|
|
1766
840
|
persistence: this.config.persistence?.type || "none"
|
|
1767
841
|
});
|
|
1768
842
|
} catch (error) {
|
|
1769
|
-
|
|
843
|
+
logger4.error("Failed to initialize world:", error);
|
|
1770
844
|
this.setState("failed");
|
|
1771
845
|
throw error;
|
|
1772
846
|
}
|
|
@@ -1776,10 +850,10 @@ var World = class {
|
|
|
1776
850
|
*/
|
|
1777
851
|
async start() {
|
|
1778
852
|
if (this.state.phase === "running") {
|
|
1779
|
-
|
|
853
|
+
logger4.warn("World is already running");
|
|
1780
854
|
return;
|
|
1781
855
|
}
|
|
1782
|
-
|
|
856
|
+
logger4.info("Starting world simulation...");
|
|
1783
857
|
this.setState("running");
|
|
1784
858
|
await this.logEvent({
|
|
1785
859
|
id: uuidv4(),
|
|
@@ -1794,7 +868,7 @@ var World = class {
|
|
|
1794
868
|
* Stop the world simulation
|
|
1795
869
|
*/
|
|
1796
870
|
async stop() {
|
|
1797
|
-
|
|
871
|
+
logger4.info("Stopping world...");
|
|
1798
872
|
this.setState("stopped");
|
|
1799
873
|
if (this.tickInterval) {
|
|
1800
874
|
clearInterval(this.tickInterval);
|
|
@@ -1812,7 +886,7 @@ var World = class {
|
|
|
1812
886
|
type: "world_stopped",
|
|
1813
887
|
timestamp: Date.now()
|
|
1814
888
|
});
|
|
1815
|
-
|
|
889
|
+
logger4.info("World stopped");
|
|
1816
890
|
}
|
|
1817
891
|
/**
|
|
1818
892
|
* Admit an agent to the world
|
|
@@ -1827,15 +901,15 @@ var World = class {
|
|
|
1827
901
|
if (!isValid) {
|
|
1828
902
|
throw new Error("Agent not registered in on-chain AgentRegistry");
|
|
1829
903
|
}
|
|
1830
|
-
|
|
904
|
+
logger4.info(`Agent validated on-chain: ${card.name}`);
|
|
1831
905
|
}
|
|
1832
906
|
if (this.blockchainClient && this.config.blockchain?.requireMembership && walletAddress) {
|
|
1833
907
|
const hasMembership = await this.blockchainClient.hasMembership(walletAddress);
|
|
1834
908
|
if (!hasMembership) {
|
|
1835
|
-
|
|
909
|
+
logger4.info(`Minting membership NFT for agent: ${card.name}`);
|
|
1836
910
|
await this.blockchainClient.mintMembership(walletAddress);
|
|
1837
911
|
} else {
|
|
1838
|
-
|
|
912
|
+
logger4.info(`Agent already has membership: ${card.name}`);
|
|
1839
913
|
}
|
|
1840
914
|
}
|
|
1841
915
|
const profile = {
|
|
@@ -1864,7 +938,7 @@ var World = class {
|
|
|
1864
938
|
agentUrl: profile.url,
|
|
1865
939
|
data: { name: profile.name, role: profile.role }
|
|
1866
940
|
});
|
|
1867
|
-
|
|
941
|
+
logger4.info(`Agent admitted: ${profile.name}`, {
|
|
1868
942
|
role: profile.role,
|
|
1869
943
|
totalAgents: this.agents.size
|
|
1870
944
|
});
|
|
@@ -1888,7 +962,7 @@ var World = class {
|
|
|
1888
962
|
agentUrl,
|
|
1889
963
|
data: { name: agent.name }
|
|
1890
964
|
});
|
|
1891
|
-
|
|
965
|
+
logger4.info(`Agent removed: ${agent.name}`, {
|
|
1892
966
|
totalAgents: this.agents.size
|
|
1893
967
|
});
|
|
1894
968
|
}
|
|
@@ -1927,10 +1001,10 @@ var World = class {
|
|
|
1927
1001
|
this.autoSaveInterval = setInterval(async () => {
|
|
1928
1002
|
if (this.persistence) {
|
|
1929
1003
|
await this.persistence.saveState(this.state);
|
|
1930
|
-
|
|
1004
|
+
logger4.debug("Auto-saved world state");
|
|
1931
1005
|
}
|
|
1932
1006
|
}, interval);
|
|
1933
|
-
|
|
1007
|
+
logger4.info(`Auto-save enabled (interval: ${interval}ms)`);
|
|
1934
1008
|
}
|
|
1935
1009
|
/**
|
|
1936
1010
|
* Start simulation ticking
|
|
@@ -1945,29 +1019,25 @@ var World = class {
|
|
|
1945
1019
|
timestamp: Date.now(),
|
|
1946
1020
|
data: { tick: this.state.tick }
|
|
1947
1021
|
});
|
|
1948
|
-
|
|
1022
|
+
logger4.debug(`Tick ${this.state.tick}`);
|
|
1949
1023
|
if (this.config.simulation?.maxTicks && this.state.tick >= this.config.simulation.maxTicks) {
|
|
1950
|
-
|
|
1024
|
+
logger4.info("Max ticks reached, stopping world");
|
|
1951
1025
|
await this.stop();
|
|
1952
1026
|
}
|
|
1953
1027
|
}, interval);
|
|
1954
|
-
|
|
1028
|
+
logger4.info(`Simulation ticking enabled (interval: ${interval}ms)`);
|
|
1955
1029
|
}
|
|
1956
1030
|
};
|
|
1957
1031
|
|
|
1958
|
-
// src/index.ts
|
|
1959
|
-
init_CardFetcher();
|
|
1960
|
-
|
|
1961
1032
|
// src/server/app.ts
|
|
1962
|
-
init_logger();
|
|
1963
1033
|
import express from "express";
|
|
1964
|
-
var
|
|
1034
|
+
var logger5 = createLogger("WorldServer");
|
|
1965
1035
|
function createWorldApp(world) {
|
|
1966
1036
|
const app = express();
|
|
1967
1037
|
app.use(express.json());
|
|
1968
1038
|
app.use(express.urlencoded({ extended: true }));
|
|
1969
1039
|
app.use((req, res, next) => {
|
|
1970
|
-
|
|
1040
|
+
logger5.debug(`${req.method} ${req.path}`, {
|
|
1971
1041
|
query: req.query,
|
|
1972
1042
|
ip: req.ip
|
|
1973
1043
|
});
|
|
@@ -1997,10 +1067,10 @@ function createWorldApp(world) {
|
|
|
1997
1067
|
error: "agentUrl is required"
|
|
1998
1068
|
});
|
|
1999
1069
|
}
|
|
2000
|
-
|
|
1070
|
+
logger5.info(`Agent join request from: ${agentUrl}`, {
|
|
2001
1071
|
wallet: walletAddress || "none"
|
|
2002
1072
|
});
|
|
2003
|
-
const cardFetcher = new (await
|
|
1073
|
+
const cardFetcher = new (await import("./CardFetcher-3QKJ2I5P.js")).CardFetcher();
|
|
2004
1074
|
const result = await cardFetcher.fetchCard(agentUrl);
|
|
2005
1075
|
if (!result.success || !result.card) {
|
|
2006
1076
|
return res.status(400).json({
|
|
@@ -2018,7 +1088,7 @@ function createWorldApp(world) {
|
|
|
2018
1088
|
}
|
|
2019
1089
|
});
|
|
2020
1090
|
} catch (error) {
|
|
2021
|
-
|
|
1091
|
+
logger5.error("Failed to process join request:", error);
|
|
2022
1092
|
res.status(400).json({
|
|
2023
1093
|
success: false,
|
|
2024
1094
|
error: error.message || "Failed to join world"
|
|
@@ -2095,7 +1165,7 @@ function createWorldApp(world) {
|
|
|
2095
1165
|
});
|
|
2096
1166
|
});
|
|
2097
1167
|
app.use((err, req, res, next) => {
|
|
2098
|
-
|
|
1168
|
+
logger5.error("Server error:", err);
|
|
2099
1169
|
res.status(500).json({
|
|
2100
1170
|
error: "Internal server error",
|
|
2101
1171
|
message: err.message
|
|
@@ -2107,27 +1177,27 @@ async function startWorldServer(world) {
|
|
|
2107
1177
|
const app = createWorldApp(world);
|
|
2108
1178
|
const server = app.listen(world.config.server.port, world.config.server.host, () => {
|
|
2109
1179
|
const { host, port } = world.config.server;
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
1180
|
+
logger5.info(`World "${world.config.name}" server started`);
|
|
1181
|
+
logger5.info(` http://${host}:${port}`);
|
|
1182
|
+
logger5.info("");
|
|
1183
|
+
logger5.info("Endpoints:");
|
|
1184
|
+
logger5.info(` GET / - World info`);
|
|
1185
|
+
logger5.info(` POST /world/join - Agent join request`);
|
|
1186
|
+
logger5.info(` GET /world/agents - List agents`);
|
|
1187
|
+
logger5.info(` GET /world/state - World state`);
|
|
1188
|
+
logger5.info(` POST /world/start - Start simulation`);
|
|
1189
|
+
logger5.info(` POST /world/stop - Stop simulation`);
|
|
1190
|
+
logger5.info(` DELETE /world/agents/:url - Remove agent`);
|
|
2121
1191
|
});
|
|
2122
1192
|
process.on("SIGTERM", async () => {
|
|
2123
|
-
|
|
1193
|
+
logger5.info("SIGTERM received, shutting down gracefully...");
|
|
2124
1194
|
server.close(async () => {
|
|
2125
1195
|
await world.stop();
|
|
2126
1196
|
process.exit(0);
|
|
2127
1197
|
});
|
|
2128
1198
|
});
|
|
2129
1199
|
process.on("SIGINT", async () => {
|
|
2130
|
-
|
|
1200
|
+
logger5.info("SIGINT received, shutting down gracefully...");
|
|
2131
1201
|
server.close(async () => {
|
|
2132
1202
|
await world.stop();
|
|
2133
1203
|
process.exit(0);
|