@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/brooklyn/Desktop/SchrodingerLabs/Byzantium/packages/world-core/dist/RedisAdapter-CT3SNBIS.cjs","../src/persistence/adapters/RedisAdapter.ts"],"names":[],"mappings":"AAAA;ACEA,kCAAsB;AAmBf,IAAM,aAAA,YAAN,MAAiD;AAAA,EAKtD,WAAA,CAAoB,MAAA,EAAqB;AAArB,IAAA,IAAA,CAAA,OAAA,EAAA,MAAA;AAClB,IAAA,IAAA,CAAK,UAAA,EAAY,MAAA,CAAO,UAAA,GAAa,QAAA;AACrC,IAAA,IAAA,CAAK,OAAA,EAAS,IAAI,mBAAA,CAAM;AAAA,MACtB,IAAA,EAAM,MAAA,CAAO,IAAA;AAAA,MACb,IAAA,EAAM,MAAA,CAAO,KAAA,GAAQ,IAAA;AAAA,MACrB,QAAA,EAAU,MAAA,CAAO,QAAA;AAAA,MACjB,EAAA,EAAI,MAAA,CAAO,GAAA,GAAM;AAAA,IACnB,CAAC,CAAA;AAAA,EACH;AAAA,EAZQ;AAAA,iBACA,UAAA,EAAY,MAAA;AAAA,EACZ;AAAA,EAYR,MAAM,OAAA,CAAA,EAAyB;AAC7B,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,CAAA;AACvB,MAAA,IAAA,CAAK,UAAA,EAAY,IAAA;AAAA,IACnB,EAAA,MAAA,CAAS,KAAA,EAAY;AACnB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,KAAA,CAAM,OAAO,CAAA,CAAA;AAC3D,IAAA;AACF,EAAA;AAE0D,EAAA;AAC3B,IAAA;AACmB,IAAA;AAGZ,IAAA;AACqB,IAAA;AAC3D,EAAA;AAEsD,EAAA;AACvB,IAAA;AACS,IAAA;AAE3B,IAAA;AACF,MAAA;AACT,IAAA;AAEsB,IAAA;AACxB,EAAA;AAEkD,EAAA;AAEb,IAAA;AACqB,IAAA;AAGE,IAAA;AACJ,IAAA;AAGlC,IAAA;AACsC,MAAA;AACD,MAAA;AACzD,IAAA;AACF,EAAA;AAE6D,EAAA;AAChC,IAAA;AAGT,IAAA;AACiC,MAAA;AACtB,IAAA;AAC2B,MAAA;AACxD,IAAA;AAE6B,IAAA;AACA,IAAA;AACE,IAAA;AAGG,IAAA;AAChC,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACqB,MAAA;AACvB,IAAA;AAEqC,IAAA;AACvC,EAAA;AAEsD,EAAA;AACH,IAAA;AACC,IAAA;AAGf,IAAA;AACU,IAAA;AAC/C,EAAA;AAEmD,EAAA;AACH,IAAA;AACrB,IAAA;AAGU,IAAA;AACO,IAAA;AAC5C,EAAA;AAE2C,EAAA;AACN,IAAA;AACc,IAAA;AAE1B,IAAA;AACb,MAAA;AACV,IAAA;AAE0D,IAAA;AACZ,IAAA;AAI7B,IAAA;AACnB,EAAA;AAE+D,EAAA;AACf,IAAA;AACR,IAAA;AAE3B,IAAA;AACF,MAAA;AACT,IAAA;AAEsB,IAAA;AACxB,EAAA;AAEkC,EAAA;AACT,IAAA;AACN,IAAA;AACnB,EAAA;AAEsC,EAAA;AAChC,IAAA;AACqB,MAAA;AAChB,MAAA;AACD,IAAA;AACC,MAAA;AACT,IAAA;AACF,EAAA;AAE6B,EAAA;AACM,IAAA;AACU,IAAA;AAEtB,IAAA;AACU,MAAA;AAC/B,IAAA;AACF,EAAA;AACF;ADzDgE;AACA;AACA","file":"/Users/brooklyn/Desktop/SchrodingerLabs/Byzantium/packages/world-core/dist/RedisAdapter-CT3SNBIS.cjs","sourcesContent":[null,"import type { PersistenceAdapter, EventFilter } from '../PersistenceAdapter.js';\nimport type { WorldStateSnapshot, WorldEvent, AgentProfile } from '../../config/types.js';\nimport { Redis } from 'ioredis';\n\n/**\n * ============================================================================\n * REDIS ADAPTER\n * ============================================================================\n * \n * High-speed in-memory persistence using Redis.\n * Features: Ultra-fast reads/writes, pub/sub support, TTL support.\n */\n\nexport interface RedisConfig {\n host: string;\n port?: number;\n password?: string;\n db?: number;\n keyPrefix?: string;\n}\n\nexport class RedisAdapter implements PersistenceAdapter {\n private client: Redis;\n private connected = false;\n private keyPrefix: string;\n\n constructor(private config: RedisConfig) {\n this.keyPrefix = config.keyPrefix || 'world:';\n this.client = new Redis({\n host: config.host,\n port: config.port || 6379,\n password: config.password,\n db: config.db || 0,\n });\n }\n\n async connect(): Promise<void> {\n try {\n await this.client.ping();\n this.connected = true;\n } catch (error: any) {\n throw new Error(`Redis connection failed: ${error.message}`);\n }\n }\n\n async saveState(state: WorldStateSnapshot): Promise<void> {\n const key = `${this.keyPrefix}state`;\n await this.client.set(key, JSON.stringify(state));\n \n // Also save to history with timestamp\n const historyKey = `${this.keyPrefix}state:history`;\n await this.client.zadd(historyKey, state.timestamp, JSON.stringify(state));\n }\n\n async loadState(): Promise<WorldStateSnapshot | null> {\n const key = `${this.keyPrefix}state`;\n const data = await this.client.get(key);\n \n if (!data) {\n return null;\n }\n \n return JSON.parse(data);\n }\n\n async saveEvent(event: WorldEvent): Promise<void> {\n // Save to events list\n const eventsKey = `${this.keyPrefix}events`;\n await this.client.zadd(eventsKey, event.timestamp, JSON.stringify(event));\n \n // Save to type-specific sorted set for faster filtering\n const typeKey = `${this.keyPrefix}events:type:${event.type}`;\n await this.client.zadd(typeKey, event.timestamp, JSON.stringify(event));\n \n // If agent-specific, also index by agent\n if (event.agentUrl) {\n const agentKey = `${this.keyPrefix}events:agent:${event.agentUrl}`;\n await this.client.zadd(agentKey, event.timestamp, JSON.stringify(event));\n }\n }\n\n async getEvents(filter?: EventFilter): Promise<WorldEvent[]> {\n let key = `${this.keyPrefix}events`;\n \n // Use type-specific key if filtering by type\n if (filter?.type) {\n key = `${this.keyPrefix}events:type:${filter.type}`;\n } else if (filter?.agentUrl) {\n key = `${this.keyPrefix}events:agent:${filter.agentUrl}`;\n }\n \n const min = filter?.since || '-inf';\n const max = filter?.until || '+inf';\n const count = filter?.limit || -1;\n \n // Get events in reverse chronological order\n const results = await this.client.zrevrangebyscore(\n key,\n max,\n min,\n 'LIMIT',\n 0,\n count === -1 ? 100 : count\n );\n \n return results.map(r => JSON.parse(r));\n }\n\n async saveAgent(profile: AgentProfile): Promise<void> {\n const key = `${this.keyPrefix}agent:${profile.url}`;\n await this.client.set(key, JSON.stringify(profile));\n \n // Add to agents set\n const agentsKey = `${this.keyPrefix}agents`;\n await this.client.sadd(agentsKey, profile.url);\n }\n\n async removeAgent(agentUrl: string): Promise<void> {\n const key = `${this.keyPrefix}agent:${agentUrl}`;\n await this.client.del(key);\n \n // Remove from agents set\n const agentsKey = `${this.keyPrefix}agents`;\n await this.client.srem(agentsKey, agentUrl);\n }\n\n async getAgents(): Promise<AgentProfile[]> {\n const agentsKey = `${this.keyPrefix}agents`;\n const urls = await this.client.smembers(agentsKey);\n \n if (urls.length === 0) {\n return [];\n }\n \n const keys = urls.map(url => `${this.keyPrefix}agent:${url}`);\n const results = await this.client.mget(...keys);\n \n return results\n .filter(r => r !== null)\n .map(r => JSON.parse(r!));\n }\n\n async getAgent(agentUrl: string): Promise<AgentProfile | null> {\n const key = `${this.keyPrefix}agent:${agentUrl}`;\n const data = await this.client.get(key);\n \n if (!data) {\n return null;\n }\n \n return JSON.parse(data);\n }\n\n async disconnect(): Promise<void> {\n await this.client.quit();\n this.connected = false;\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n await this.client.ping();\n return true;\n } catch {\n return false;\n }\n }\n\n async clear(): Promise<void> {\n const pattern = `${this.keyPrefix}*`;\n const keys = await this.client.keys(pattern);\n \n if (keys.length > 0) {\n await this.client.del(...keys);\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// src/persistence/adapters/RedisAdapter.ts
|
|
2
|
+
import { Redis } from "ioredis";
|
|
3
|
+
var RedisAdapter = class {
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.config = config;
|
|
6
|
+
this.keyPrefix = config.keyPrefix || "world:";
|
|
7
|
+
this.client = new Redis({
|
|
8
|
+
host: config.host,
|
|
9
|
+
port: config.port || 6379,
|
|
10
|
+
password: config.password,
|
|
11
|
+
db: config.db || 0
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
client;
|
|
15
|
+
connected = false;
|
|
16
|
+
keyPrefix;
|
|
17
|
+
async connect() {
|
|
18
|
+
try {
|
|
19
|
+
await this.client.ping();
|
|
20
|
+
this.connected = true;
|
|
21
|
+
} catch (error) {
|
|
22
|
+
throw new Error(`Redis connection failed: ${error.message}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async saveState(state) {
|
|
26
|
+
const key = `${this.keyPrefix}state`;
|
|
27
|
+
await this.client.set(key, JSON.stringify(state));
|
|
28
|
+
const historyKey = `${this.keyPrefix}state:history`;
|
|
29
|
+
await this.client.zadd(historyKey, state.timestamp, JSON.stringify(state));
|
|
30
|
+
}
|
|
31
|
+
async loadState() {
|
|
32
|
+
const key = `${this.keyPrefix}state`;
|
|
33
|
+
const data = await this.client.get(key);
|
|
34
|
+
if (!data) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return JSON.parse(data);
|
|
38
|
+
}
|
|
39
|
+
async saveEvent(event) {
|
|
40
|
+
const eventsKey = `${this.keyPrefix}events`;
|
|
41
|
+
await this.client.zadd(eventsKey, event.timestamp, JSON.stringify(event));
|
|
42
|
+
const typeKey = `${this.keyPrefix}events:type:${event.type}`;
|
|
43
|
+
await this.client.zadd(typeKey, event.timestamp, JSON.stringify(event));
|
|
44
|
+
if (event.agentUrl) {
|
|
45
|
+
const agentKey = `${this.keyPrefix}events:agent:${event.agentUrl}`;
|
|
46
|
+
await this.client.zadd(agentKey, event.timestamp, JSON.stringify(event));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async getEvents(filter) {
|
|
50
|
+
let key = `${this.keyPrefix}events`;
|
|
51
|
+
if (filter?.type) {
|
|
52
|
+
key = `${this.keyPrefix}events:type:${filter.type}`;
|
|
53
|
+
} else if (filter?.agentUrl) {
|
|
54
|
+
key = `${this.keyPrefix}events:agent:${filter.agentUrl}`;
|
|
55
|
+
}
|
|
56
|
+
const min = filter?.since || "-inf";
|
|
57
|
+
const max = filter?.until || "+inf";
|
|
58
|
+
const count = filter?.limit || -1;
|
|
59
|
+
const results = await this.client.zrevrangebyscore(
|
|
60
|
+
key,
|
|
61
|
+
max,
|
|
62
|
+
min,
|
|
63
|
+
"LIMIT",
|
|
64
|
+
0,
|
|
65
|
+
count === -1 ? 100 : count
|
|
66
|
+
);
|
|
67
|
+
return results.map((r) => JSON.parse(r));
|
|
68
|
+
}
|
|
69
|
+
async saveAgent(profile) {
|
|
70
|
+
const key = `${this.keyPrefix}agent:${profile.url}`;
|
|
71
|
+
await this.client.set(key, JSON.stringify(profile));
|
|
72
|
+
const agentsKey = `${this.keyPrefix}agents`;
|
|
73
|
+
await this.client.sadd(agentsKey, profile.url);
|
|
74
|
+
}
|
|
75
|
+
async removeAgent(agentUrl) {
|
|
76
|
+
const key = `${this.keyPrefix}agent:${agentUrl}`;
|
|
77
|
+
await this.client.del(key);
|
|
78
|
+
const agentsKey = `${this.keyPrefix}agents`;
|
|
79
|
+
await this.client.srem(agentsKey, agentUrl);
|
|
80
|
+
}
|
|
81
|
+
async getAgents() {
|
|
82
|
+
const agentsKey = `${this.keyPrefix}agents`;
|
|
83
|
+
const urls = await this.client.smembers(agentsKey);
|
|
84
|
+
if (urls.length === 0) {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
const keys = urls.map((url) => `${this.keyPrefix}agent:${url}`);
|
|
88
|
+
const results = await this.client.mget(...keys);
|
|
89
|
+
return results.filter((r) => r !== null).map((r) => JSON.parse(r));
|
|
90
|
+
}
|
|
91
|
+
async getAgent(agentUrl) {
|
|
92
|
+
const key = `${this.keyPrefix}agent:${agentUrl}`;
|
|
93
|
+
const data = await this.client.get(key);
|
|
94
|
+
if (!data) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
return JSON.parse(data);
|
|
98
|
+
}
|
|
99
|
+
async disconnect() {
|
|
100
|
+
await this.client.quit();
|
|
101
|
+
this.connected = false;
|
|
102
|
+
}
|
|
103
|
+
async healthCheck() {
|
|
104
|
+
try {
|
|
105
|
+
await this.client.ping();
|
|
106
|
+
return true;
|
|
107
|
+
} catch {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async clear() {
|
|
112
|
+
const pattern = `${this.keyPrefix}*`;
|
|
113
|
+
const keys = await this.client.keys(pattern);
|
|
114
|
+
if (keys.length > 0) {
|
|
115
|
+
await this.client.del(...keys);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
export {
|
|
120
|
+
RedisAdapter
|
|
121
|
+
};
|
|
122
|
+
//# sourceMappingURL=RedisAdapter-OL4FVEGL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/persistence/adapters/RedisAdapter.ts"],"sourcesContent":["import type { PersistenceAdapter, EventFilter } from '../PersistenceAdapter.js';\nimport type { WorldStateSnapshot, WorldEvent, AgentProfile } from '../../config/types.js';\nimport { Redis } from 'ioredis';\n\n/**\n * ============================================================================\n * REDIS ADAPTER\n * ============================================================================\n * \n * High-speed in-memory persistence using Redis.\n * Features: Ultra-fast reads/writes, pub/sub support, TTL support.\n */\n\nexport interface RedisConfig {\n host: string;\n port?: number;\n password?: string;\n db?: number;\n keyPrefix?: string;\n}\n\nexport class RedisAdapter implements PersistenceAdapter {\n private client: Redis;\n private connected = false;\n private keyPrefix: string;\n\n constructor(private config: RedisConfig) {\n this.keyPrefix = config.keyPrefix || 'world:';\n this.client = new Redis({\n host: config.host,\n port: config.port || 6379,\n password: config.password,\n db: config.db || 0,\n });\n }\n\n async connect(): Promise<void> {\n try {\n await this.client.ping();\n this.connected = true;\n } catch (error: any) {\n throw new Error(`Redis connection failed: ${error.message}`);\n }\n }\n\n async saveState(state: WorldStateSnapshot): Promise<void> {\n const key = `${this.keyPrefix}state`;\n await this.client.set(key, JSON.stringify(state));\n \n // Also save to history with timestamp\n const historyKey = `${this.keyPrefix}state:history`;\n await this.client.zadd(historyKey, state.timestamp, JSON.stringify(state));\n }\n\n async loadState(): Promise<WorldStateSnapshot | null> {\n const key = `${this.keyPrefix}state`;\n const data = await this.client.get(key);\n \n if (!data) {\n return null;\n }\n \n return JSON.parse(data);\n }\n\n async saveEvent(event: WorldEvent): Promise<void> {\n // Save to events list\n const eventsKey = `${this.keyPrefix}events`;\n await this.client.zadd(eventsKey, event.timestamp, JSON.stringify(event));\n \n // Save to type-specific sorted set for faster filtering\n const typeKey = `${this.keyPrefix}events:type:${event.type}`;\n await this.client.zadd(typeKey, event.timestamp, JSON.stringify(event));\n \n // If agent-specific, also index by agent\n if (event.agentUrl) {\n const agentKey = `${this.keyPrefix}events:agent:${event.agentUrl}`;\n await this.client.zadd(agentKey, event.timestamp, JSON.stringify(event));\n }\n }\n\n async getEvents(filter?: EventFilter): Promise<WorldEvent[]> {\n let key = `${this.keyPrefix}events`;\n \n // Use type-specific key if filtering by type\n if (filter?.type) {\n key = `${this.keyPrefix}events:type:${filter.type}`;\n } else if (filter?.agentUrl) {\n key = `${this.keyPrefix}events:agent:${filter.agentUrl}`;\n }\n \n const min = filter?.since || '-inf';\n const max = filter?.until || '+inf';\n const count = filter?.limit || -1;\n \n // Get events in reverse chronological order\n const results = await this.client.zrevrangebyscore(\n key,\n max,\n min,\n 'LIMIT',\n 0,\n count === -1 ? 100 : count\n );\n \n return results.map(r => JSON.parse(r));\n }\n\n async saveAgent(profile: AgentProfile): Promise<void> {\n const key = `${this.keyPrefix}agent:${profile.url}`;\n await this.client.set(key, JSON.stringify(profile));\n \n // Add to agents set\n const agentsKey = `${this.keyPrefix}agents`;\n await this.client.sadd(agentsKey, profile.url);\n }\n\n async removeAgent(agentUrl: string): Promise<void> {\n const key = `${this.keyPrefix}agent:${agentUrl}`;\n await this.client.del(key);\n \n // Remove from agents set\n const agentsKey = `${this.keyPrefix}agents`;\n await this.client.srem(agentsKey, agentUrl);\n }\n\n async getAgents(): Promise<AgentProfile[]> {\n const agentsKey = `${this.keyPrefix}agents`;\n const urls = await this.client.smembers(agentsKey);\n \n if (urls.length === 0) {\n return [];\n }\n \n const keys = urls.map(url => `${this.keyPrefix}agent:${url}`);\n const results = await this.client.mget(...keys);\n \n return results\n .filter(r => r !== null)\n .map(r => JSON.parse(r!));\n }\n\n async getAgent(agentUrl: string): Promise<AgentProfile | null> {\n const key = `${this.keyPrefix}agent:${agentUrl}`;\n const data = await this.client.get(key);\n \n if (!data) {\n return null;\n }\n \n return JSON.parse(data);\n }\n\n async disconnect(): Promise<void> {\n await this.client.quit();\n this.connected = false;\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n await this.client.ping();\n return true;\n } catch {\n return false;\n }\n }\n\n async clear(): Promise<void> {\n const pattern = `${this.keyPrefix}*`;\n const keys = await this.client.keys(pattern);\n \n if (keys.length > 0) {\n await this.client.del(...keys);\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// src/logger.ts
|
|
2
|
+
import winston from "winston";
|
|
3
|
+
var logLevel = process.env.LOG_LEVEL || "info";
|
|
4
|
+
var logger = winston.createLogger({
|
|
5
|
+
level: logLevel,
|
|
6
|
+
format: winston.format.combine(
|
|
7
|
+
winston.format.timestamp(),
|
|
8
|
+
winston.format.colorize(),
|
|
9
|
+
winston.format.printf(({ level, message, timestamp, ...meta }) => {
|
|
10
|
+
const metaStr = Object.keys(meta).length ? ` ${JSON.stringify(meta)}` : "";
|
|
11
|
+
return `${timestamp} [${level}] ${message}${metaStr}`;
|
|
12
|
+
})
|
|
13
|
+
),
|
|
14
|
+
transports: [new winston.transports.Console()]
|
|
15
|
+
});
|
|
16
|
+
function createLogger(moduleName) {
|
|
17
|
+
return logger.child({ module: moduleName });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// src/discovery/CardFetcher.ts
|
|
21
|
+
var logger2 = createLogger("CardFetcher");
|
|
22
|
+
var CardFetcher = class {
|
|
23
|
+
/**
|
|
24
|
+
* Fetch an agent's card from their A2A endpoint.
|
|
25
|
+
*
|
|
26
|
+
* @param agentUrl Base URL of the agent (e.g., http://localhost:3000)
|
|
27
|
+
* @returns Fetch result with card or error
|
|
28
|
+
*/
|
|
29
|
+
async fetchCard(agentUrl) {
|
|
30
|
+
try {
|
|
31
|
+
const cardUrl = new URL("/.well-known/agent-card.json", agentUrl).toString();
|
|
32
|
+
logger2.debug(`Fetching agent card from ${cardUrl}`);
|
|
33
|
+
const response = await fetch(cardUrl, {
|
|
34
|
+
method: "GET",
|
|
35
|
+
headers: {
|
|
36
|
+
"Accept": "application/json",
|
|
37
|
+
"User-Agent": "@moltium/world-core/0.1.0"
|
|
38
|
+
},
|
|
39
|
+
signal: AbortSignal.timeout(5e3)
|
|
40
|
+
// 5 second timeout
|
|
41
|
+
});
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
return {
|
|
44
|
+
success: false,
|
|
45
|
+
error: `HTTP ${response.status}: ${response.statusText}`
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const card = await response.json();
|
|
49
|
+
if (!card.name || !card.protocolVersion || !card.url || !card.skills) {
|
|
50
|
+
return {
|
|
51
|
+
success: false,
|
|
52
|
+
error: "Invalid agent card: missing required fields"
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
logger2.info(`Successfully fetched card for agent: ${card.name}`, {
|
|
56
|
+
protocolVersion: card.protocolVersion,
|
|
57
|
+
skillCount: card.skills.length
|
|
58
|
+
});
|
|
59
|
+
return {
|
|
60
|
+
success: true,
|
|
61
|
+
card
|
|
62
|
+
};
|
|
63
|
+
} catch (error) {
|
|
64
|
+
logger2.error(`Failed to fetch agent card from ${agentUrl}:`, error.message);
|
|
65
|
+
return {
|
|
66
|
+
success: false,
|
|
67
|
+
error: error.message || "Unknown error"
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Fetch multiple agent cards in parallel.
|
|
73
|
+
*
|
|
74
|
+
* @param agentUrls Array of agent URLs
|
|
75
|
+
* @returns Array of fetch results
|
|
76
|
+
*/
|
|
77
|
+
async fetchCards(agentUrls) {
|
|
78
|
+
logger2.info(`Fetching ${agentUrls.length} agent cards...`);
|
|
79
|
+
const results = await Promise.all(
|
|
80
|
+
agentUrls.map((url) => this.fetchCard(url))
|
|
81
|
+
);
|
|
82
|
+
const successCount = results.filter((r) => r.success).length;
|
|
83
|
+
logger2.info(`Fetched ${successCount}/${agentUrls.length} agent cards successfully`);
|
|
84
|
+
return results;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Verify that an agent card is valid for A2A protocol v0.3.0.
|
|
88
|
+
*
|
|
89
|
+
* @param card Agent card to verify
|
|
90
|
+
* @returns True if valid
|
|
91
|
+
*/
|
|
92
|
+
verifyCard(card) {
|
|
93
|
+
if (!card.name || !card.protocolVersion || !card.url || !card.skills) {
|
|
94
|
+
logger2.warn("Agent card missing required fields", { name: card.name });
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
if (!card.protocolVersion.startsWith("0.3")) {
|
|
98
|
+
logger2.warn("Agent card has incompatible protocol version", {
|
|
99
|
+
name: card.name,
|
|
100
|
+
version: card.protocolVersion
|
|
101
|
+
});
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
if (!Array.isArray(card.skills) || card.skills.length === 0) {
|
|
105
|
+
logger2.warn("Agent card has no skills", { name: card.name });
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
if (!card.capabilities || typeof card.capabilities !== "object") {
|
|
109
|
+
logger2.warn("Agent card missing capabilities", { name: card.name });
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
function normalizeAgentUrl(url) {
|
|
116
|
+
try {
|
|
117
|
+
const parsed = new URL(url);
|
|
118
|
+
return `${parsed.protocol}//${parsed.host}`;
|
|
119
|
+
} catch {
|
|
120
|
+
return url;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export {
|
|
125
|
+
logger,
|
|
126
|
+
createLogger,
|
|
127
|
+
CardFetcher,
|
|
128
|
+
normalizeAgentUrl
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=chunk-JW3PZRCW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/logger.ts","../src/discovery/CardFetcher.ts"],"sourcesContent":["import winston from 'winston';\n\n/**\n * ============================================================================\n * WORLD SDK LOGGER\n * ============================================================================\n * \n * Winston-based logger for World SDK.\n * Follows the same pattern as @moltium/core logger.\n */\n\nconst logLevel = process.env.LOG_LEVEL || 'info';\n\nexport const logger = winston.createLogger({\n level: logLevel,\n format: winston.format.combine(\n winston.format.timestamp(),\n winston.format.colorize(),\n winston.format.printf(({ level, message, timestamp, ...meta }) => {\n const metaStr = Object.keys(meta).length ? ` ${JSON.stringify(meta)}` : '';\n return `${timestamp} [${level}] ${message}${metaStr}`;\n })\n ),\n transports: [new winston.transports.Console()],\n});\n\n/**\n * Create a child logger with a specific module name\n */\nexport function createLogger(moduleName: string): winston.Logger {\n return logger.child({ module: moduleName });\n}\n","import type { AgentCard } from '@a2a-js/sdk';\nimport { createLogger } from '../logger.js';\n\nconst logger = createLogger('CardFetcher');\n\n/**\n * ============================================================================\n * AGENT CARD FETCHER\n * ============================================================================\n * \n * Discovers agents by fetching their A2A Agent Cards.\n * Follows the A2A protocol specification.\n */\n\nexport interface FetchResult {\n success: boolean;\n card?: AgentCard;\n error?: string;\n}\n\nexport class CardFetcher {\n /**\n * Fetch an agent's card from their A2A endpoint.\n * \n * @param agentUrl Base URL of the agent (e.g., http://localhost:3000)\n * @returns Fetch result with card or error\n */\n async fetchCard(agentUrl: string): Promise<FetchResult> {\n try {\n // A2A spec: Agent Card is available at /.well-known/agent-card.json\n const cardUrl = new URL('/.well-known/agent-card.json', agentUrl).toString();\n \n logger.debug(`Fetching agent card from ${cardUrl}`);\n \n const response = await fetch(cardUrl, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'User-Agent': '@moltium/world-core/0.1.0',\n },\n signal: AbortSignal.timeout(5000), // 5 second timeout\n });\n \n if (!response.ok) {\n return {\n success: false,\n error: `HTTP ${response.status}: ${response.statusText}`,\n };\n }\n \n const card = await response.json() as AgentCard;\n \n // Basic validation\n if (!card.name || !card.protocolVersion || !card.url || !card.skills) {\n return {\n success: false,\n error: 'Invalid agent card: missing required fields',\n };\n }\n \n logger.info(`Successfully fetched card for agent: ${card.name}`, {\n protocolVersion: card.protocolVersion,\n skillCount: card.skills.length,\n });\n \n return {\n success: true,\n card,\n };\n } catch (error: any) {\n logger.error(`Failed to fetch agent card from ${agentUrl}:`, error.message);\n \n return {\n success: false,\n error: error.message || 'Unknown error',\n };\n }\n }\n \n /**\n * Fetch multiple agent cards in parallel.\n * \n * @param agentUrls Array of agent URLs\n * @returns Array of fetch results\n */\n async fetchCards(agentUrls: string[]): Promise<FetchResult[]> {\n logger.info(`Fetching ${agentUrls.length} agent cards...`);\n \n const results = await Promise.all(\n agentUrls.map(url => this.fetchCard(url))\n );\n \n const successCount = results.filter(r => r.success).length;\n logger.info(`Fetched ${successCount}/${agentUrls.length} agent cards successfully`);\n \n return results;\n }\n \n /**\n * Verify that an agent card is valid for A2A protocol v0.3.0.\n * \n * @param card Agent card to verify\n * @returns True if valid\n */\n verifyCard(card: AgentCard): boolean {\n // Check required fields\n if (!card.name || !card.protocolVersion || !card.url || !card.skills) {\n logger.warn('Agent card missing required fields', { name: card.name });\n return false;\n }\n \n // Check protocol version compatibility\n if (!card.protocolVersion.startsWith('0.3')) {\n logger.warn('Agent card has incompatible protocol version', {\n name: card.name,\n version: card.protocolVersion,\n });\n return false;\n }\n \n // Check skills array\n if (!Array.isArray(card.skills) || card.skills.length === 0) {\n logger.warn('Agent card has no skills', { name: card.name });\n return false;\n }\n \n // Check capabilities\n if (!card.capabilities || typeof card.capabilities !== 'object') {\n logger.warn('Agent card missing capabilities', { name: card.name });\n return false;\n }\n \n return true;\n }\n}\n\n/**\n * Helper to extract base URL from various formats\n */\nexport function normalizeAgentUrl(url: string): string {\n try {\n const parsed = new URL(url);\n return `${parsed.protocol}//${parsed.host}`;\n } catch {\n // If already in base format, return as-is\n return url;\n }\n}\n"],"mappings":"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","names":["logger"]}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }// src/logger.ts
|
|
2
|
+
var _winston = require('winston'); var _winston2 = _interopRequireDefault(_winston);
|
|
3
|
+
var logLevel = process.env.LOG_LEVEL || "info";
|
|
4
|
+
var logger = _winston2.default.createLogger({
|
|
5
|
+
level: logLevel,
|
|
6
|
+
format: _winston2.default.format.combine(
|
|
7
|
+
_winston2.default.format.timestamp(),
|
|
8
|
+
_winston2.default.format.colorize(),
|
|
9
|
+
_winston2.default.format.printf(({ level, message, timestamp, ...meta }) => {
|
|
10
|
+
const metaStr = Object.keys(meta).length ? ` ${JSON.stringify(meta)}` : "";
|
|
11
|
+
return `${timestamp} [${level}] ${message}${metaStr}`;
|
|
12
|
+
})
|
|
13
|
+
),
|
|
14
|
+
transports: [new _winston2.default.transports.Console()]
|
|
15
|
+
});
|
|
16
|
+
function createLogger(moduleName) {
|
|
17
|
+
return logger.child({ module: moduleName });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// src/discovery/CardFetcher.ts
|
|
21
|
+
var logger2 = createLogger("CardFetcher");
|
|
22
|
+
var CardFetcher = class {
|
|
23
|
+
/**
|
|
24
|
+
* Fetch an agent's card from their A2A endpoint.
|
|
25
|
+
*
|
|
26
|
+
* @param agentUrl Base URL of the agent (e.g., http://localhost:3000)
|
|
27
|
+
* @returns Fetch result with card or error
|
|
28
|
+
*/
|
|
29
|
+
async fetchCard(agentUrl) {
|
|
30
|
+
try {
|
|
31
|
+
const cardUrl = new URL("/.well-known/agent-card.json", agentUrl).toString();
|
|
32
|
+
logger2.debug(`Fetching agent card from ${cardUrl}`);
|
|
33
|
+
const response = await fetch(cardUrl, {
|
|
34
|
+
method: "GET",
|
|
35
|
+
headers: {
|
|
36
|
+
"Accept": "application/json",
|
|
37
|
+
"User-Agent": "@moltium/world-core/0.1.0"
|
|
38
|
+
},
|
|
39
|
+
signal: AbortSignal.timeout(5e3)
|
|
40
|
+
// 5 second timeout
|
|
41
|
+
});
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
return {
|
|
44
|
+
success: false,
|
|
45
|
+
error: `HTTP ${response.status}: ${response.statusText}`
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const card = await response.json();
|
|
49
|
+
if (!card.name || !card.protocolVersion || !card.url || !card.skills) {
|
|
50
|
+
return {
|
|
51
|
+
success: false,
|
|
52
|
+
error: "Invalid agent card: missing required fields"
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
logger2.info(`Successfully fetched card for agent: ${card.name}`, {
|
|
56
|
+
protocolVersion: card.protocolVersion,
|
|
57
|
+
skillCount: card.skills.length
|
|
58
|
+
});
|
|
59
|
+
return {
|
|
60
|
+
success: true,
|
|
61
|
+
card
|
|
62
|
+
};
|
|
63
|
+
} catch (error) {
|
|
64
|
+
logger2.error(`Failed to fetch agent card from ${agentUrl}:`, error.message);
|
|
65
|
+
return {
|
|
66
|
+
success: false,
|
|
67
|
+
error: error.message || "Unknown error"
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Fetch multiple agent cards in parallel.
|
|
73
|
+
*
|
|
74
|
+
* @param agentUrls Array of agent URLs
|
|
75
|
+
* @returns Array of fetch results
|
|
76
|
+
*/
|
|
77
|
+
async fetchCards(agentUrls) {
|
|
78
|
+
logger2.info(`Fetching ${agentUrls.length} agent cards...`);
|
|
79
|
+
const results = await Promise.all(
|
|
80
|
+
agentUrls.map((url) => this.fetchCard(url))
|
|
81
|
+
);
|
|
82
|
+
const successCount = results.filter((r) => r.success).length;
|
|
83
|
+
logger2.info(`Fetched ${successCount}/${agentUrls.length} agent cards successfully`);
|
|
84
|
+
return results;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Verify that an agent card is valid for A2A protocol v0.3.0.
|
|
88
|
+
*
|
|
89
|
+
* @param card Agent card to verify
|
|
90
|
+
* @returns True if valid
|
|
91
|
+
*/
|
|
92
|
+
verifyCard(card) {
|
|
93
|
+
if (!card.name || !card.protocolVersion || !card.url || !card.skills) {
|
|
94
|
+
logger2.warn("Agent card missing required fields", { name: card.name });
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
if (!card.protocolVersion.startsWith("0.3")) {
|
|
98
|
+
logger2.warn("Agent card has incompatible protocol version", {
|
|
99
|
+
name: card.name,
|
|
100
|
+
version: card.protocolVersion
|
|
101
|
+
});
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
if (!Array.isArray(card.skills) || card.skills.length === 0) {
|
|
105
|
+
logger2.warn("Agent card has no skills", { name: card.name });
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
if (!card.capabilities || typeof card.capabilities !== "object") {
|
|
109
|
+
logger2.warn("Agent card missing capabilities", { name: card.name });
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
function normalizeAgentUrl(url) {
|
|
116
|
+
try {
|
|
117
|
+
const parsed = new URL(url);
|
|
118
|
+
return `${parsed.protocol}//${parsed.host}`;
|
|
119
|
+
} catch (e) {
|
|
120
|
+
return url;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
exports.logger = logger; exports.createLogger = createLogger; exports.CardFetcher = CardFetcher; exports.normalizeAgentUrl = normalizeAgentUrl;
|
|
130
|
+
//# sourceMappingURL=chunk-NEXCYEQT.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/brooklyn/Desktop/SchrodingerLabs/Byzantium/packages/world-core/dist/chunk-NEXCYEQT.cjs","../src/logger.ts","../src/discovery/CardFetcher.ts"],"names":[],"mappings":"AAAA;ACAA,oFAAoB;AAWpB,IAAM,SAAA,EAAW,OAAA,CAAQ,GAAA,CAAI,UAAA,GAAa,MAAA;AAEnC,IAAM,OAAA,EAAS,iBAAA,CAAQ,YAAA,CAAa;AAAA,EACzC,KAAA,EAAO,QAAA;AAAA,EACP,MAAA,EAAQ,iBAAA,CAAQ,MAAA,CAAO,OAAA;AAAA,IACrB,iBAAA,CAAQ,MAAA,CAAO,SAAA,CAAU,CAAA;AAAA,IACzB,iBAAA,CAAQ,MAAA,CAAO,QAAA,CAAS,CAAA;AAAA,IACxB,iBAAA,CAAQ,MAAA,CAAO,MAAA,CAAO,CAAC,EAAE,KAAA,EAAO,OAAA,EAAS,SAAA,EAAW,GAAG,KAAK,CAAA,EAAA,GAAM;AAChE,MAAA,MAAM,QAAA,EAAU,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,CAAE,OAAA,EAAS,CAAA,CAAA,EAAI,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA,EAAA;AAChB,MAAA;AACpD,IAAA;AACH,EAAA;AAC6C,EAAA;AAC9C;AAKgE;AACrB,EAAA;AAC5C;ADb0E;AACA;AEhBjC;AAiBhB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOiC,EAAA;AAClD,IAAA;AAEgE,MAAA;AAEhB,MAAA;AAEZ,MAAA;AAC5B,QAAA;AACC,QAAA;AACG,UAAA;AACI,UAAA;AAChB,QAAA;AACgC,QAAA;AAAA;AACjC,MAAA;AAEiB,MAAA;AACT,QAAA;AACI,UAAA;AAC6C,UAAA;AACxD,QAAA;AACF,MAAA;AAEiC,MAAA;AAG6B,MAAA;AACrD,QAAA;AACI,UAAA;AACF,UAAA;AACT,QAAA;AACF,MAAA;AAEiE,MAAA;AACzC,QAAA;AACE,QAAA;AACzB,MAAA;AAEM,MAAA;AACI,QAAA;AACT,QAAA;AACF,MAAA;AACmB,IAAA;AACgD,MAAA;AAE5D,MAAA;AACI,QAAA;AACe,QAAA;AAC1B,MAAA;AACF,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQ8D,EAAA;AACH,IAAA;AAE3B,IAAA;AACY,MAAA;AAC1C,IAAA;AAEoD,IAAA;AACG,IAAA;AAEhD,IAAA;AACT,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQqC,EAAA;AAEmC,IAAA;AACL,MAAA;AACxD,MAAA;AACT,IAAA;AAG6C,IAAA;AACiB,MAAA;AAC/C,QAAA;AACG,QAAA;AACf,MAAA;AACM,MAAA;AACT,IAAA;AAG6D,IAAA;AACA,MAAA;AACpD,MAAA;AACT,IAAA;AAGiE,IAAA;AACG,MAAA;AAC3D,MAAA;AACT,IAAA;AAEO,IAAA;AACT,EAAA;AACF;AAKuD;AACjD,EAAA;AACwB,IAAA;AACe,IAAA;AACnC,EAAA;AAEC,IAAA;AACT,EAAA;AACF;AFzB0E;AACA;AACA;AACA;AACA;AACA;AACA","file":"/Users/brooklyn/Desktop/SchrodingerLabs/Byzantium/packages/world-core/dist/chunk-NEXCYEQT.cjs","sourcesContent":[null,"import winston from 'winston';\n\n/**\n * ============================================================================\n * WORLD SDK LOGGER\n * ============================================================================\n * \n * Winston-based logger for World SDK.\n * Follows the same pattern as @moltium/core logger.\n */\n\nconst logLevel = process.env.LOG_LEVEL || 'info';\n\nexport const logger = winston.createLogger({\n level: logLevel,\n format: winston.format.combine(\n winston.format.timestamp(),\n winston.format.colorize(),\n winston.format.printf(({ level, message, timestamp, ...meta }) => {\n const metaStr = Object.keys(meta).length ? ` ${JSON.stringify(meta)}` : '';\n return `${timestamp} [${level}] ${message}${metaStr}`;\n })\n ),\n transports: [new winston.transports.Console()],\n});\n\n/**\n * Create a child logger with a specific module name\n */\nexport function createLogger(moduleName: string): winston.Logger {\n return logger.child({ module: moduleName });\n}\n","import type { AgentCard } from '@a2a-js/sdk';\nimport { createLogger } from '../logger.js';\n\nconst logger = createLogger('CardFetcher');\n\n/**\n * ============================================================================\n * AGENT CARD FETCHER\n * ============================================================================\n * \n * Discovers agents by fetching their A2A Agent Cards.\n * Follows the A2A protocol specification.\n */\n\nexport interface FetchResult {\n success: boolean;\n card?: AgentCard;\n error?: string;\n}\n\nexport class CardFetcher {\n /**\n * Fetch an agent's card from their A2A endpoint.\n * \n * @param agentUrl Base URL of the agent (e.g., http://localhost:3000)\n * @returns Fetch result with card or error\n */\n async fetchCard(agentUrl: string): Promise<FetchResult> {\n try {\n // A2A spec: Agent Card is available at /.well-known/agent-card.json\n const cardUrl = new URL('/.well-known/agent-card.json', agentUrl).toString();\n \n logger.debug(`Fetching agent card from ${cardUrl}`);\n \n const response = await fetch(cardUrl, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'User-Agent': '@moltium/world-core/0.1.0',\n },\n signal: AbortSignal.timeout(5000), // 5 second timeout\n });\n \n if (!response.ok) {\n return {\n success: false,\n error: `HTTP ${response.status}: ${response.statusText}`,\n };\n }\n \n const card = await response.json() as AgentCard;\n \n // Basic validation\n if (!card.name || !card.protocolVersion || !card.url || !card.skills) {\n return {\n success: false,\n error: 'Invalid agent card: missing required fields',\n };\n }\n \n logger.info(`Successfully fetched card for agent: ${card.name}`, {\n protocolVersion: card.protocolVersion,\n skillCount: card.skills.length,\n });\n \n return {\n success: true,\n card,\n };\n } catch (error: any) {\n logger.error(`Failed to fetch agent card from ${agentUrl}:`, error.message);\n \n return {\n success: false,\n error: error.message || 'Unknown error',\n };\n }\n }\n \n /**\n * Fetch multiple agent cards in parallel.\n * \n * @param agentUrls Array of agent URLs\n * @returns Array of fetch results\n */\n async fetchCards(agentUrls: string[]): Promise<FetchResult[]> {\n logger.info(`Fetching ${agentUrls.length} agent cards...`);\n \n const results = await Promise.all(\n agentUrls.map(url => this.fetchCard(url))\n );\n \n const successCount = results.filter(r => r.success).length;\n logger.info(`Fetched ${successCount}/${agentUrls.length} agent cards successfully`);\n \n return results;\n }\n \n /**\n * Verify that an agent card is valid for A2A protocol v0.3.0.\n * \n * @param card Agent card to verify\n * @returns True if valid\n */\n verifyCard(card: AgentCard): boolean {\n // Check required fields\n if (!card.name || !card.protocolVersion || !card.url || !card.skills) {\n logger.warn('Agent card missing required fields', { name: card.name });\n return false;\n }\n \n // Check protocol version compatibility\n if (!card.protocolVersion.startsWith('0.3')) {\n logger.warn('Agent card has incompatible protocol version', {\n name: card.name,\n version: card.protocolVersion,\n });\n return false;\n }\n \n // Check skills array\n if (!Array.isArray(card.skills) || card.skills.length === 0) {\n logger.warn('Agent card has no skills', { name: card.name });\n return false;\n }\n \n // Check capabilities\n if (!card.capabilities || typeof card.capabilities !== 'object') {\n logger.warn('Agent card missing capabilities', { name: card.name });\n return false;\n }\n \n return true;\n }\n}\n\n/**\n * Helper to extract base URL from various formats\n */\nexport function normalizeAgentUrl(url: string): string {\n try {\n const parsed = new URL(url);\n return `${parsed.protocol}//${parsed.host}`;\n } catch {\n // If already in base format, return as-is\n return url;\n }\n}\n"]}
|