@moltium/world-core 0.1.23 → 0.1.25

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/index.d.cts CHANGED
@@ -1359,6 +1359,16 @@ declare class MessageRouter {
1359
1359
  private a2aClient;
1360
1360
  private getAgents;
1361
1361
  constructor(a2aClient: WorldA2AClient, getAgents: () => AgentProfile[]);
1362
+ /**
1363
+ * Extract base URL (protocol://host:port) from a full URL for comparison.
1364
+ * Agent cards use full URLs (e.g. http://localhost:3001/a2a/jsonrpc)
1365
+ * while agents send base URLs (e.g. http://localhost:3001).
1366
+ */
1367
+ private extractBaseUrl;
1368
+ /**
1369
+ * Find an agent by URL, normalizing both sides to base URL for comparison
1370
+ */
1371
+ private findAgent;
1362
1372
  /**
1363
1373
  * Route a message from one agent to another
1364
1374
  */
package/dist/index.d.ts CHANGED
@@ -1359,6 +1359,16 @@ declare class MessageRouter {
1359
1359
  private a2aClient;
1360
1360
  private getAgents;
1361
1361
  constructor(a2aClient: WorldA2AClient, getAgents: () => AgentProfile[]);
1362
+ /**
1363
+ * Extract base URL (protocol://host:port) from a full URL for comparison.
1364
+ * Agent cards use full URLs (e.g. http://localhost:3001/a2a/jsonrpc)
1365
+ * while agents send base URLs (e.g. http://localhost:3001).
1366
+ */
1367
+ private extractBaseUrl;
1368
+ /**
1369
+ * Find an agent by URL, normalizing both sides to base URL for comparison
1370
+ */
1371
+ private findAgent;
1362
1372
  /**
1363
1373
  * Route a message from one agent to another
1364
1374
  */
package/dist/index.js CHANGED
@@ -876,14 +876,16 @@ var WorldA2AClient = class {
876
876
  * Remove an agent from the client pool
877
877
  */
878
878
  removeAgent(agentUrl) {
879
- this.clients.delete(agentUrl);
880
- logger4.info(`Removed agent from A2A client pool: ${agentUrl}`);
879
+ const baseUrl = this.extractBaseUrl(agentUrl);
880
+ this.clients.delete(baseUrl);
881
+ logger4.info(`Removed agent from A2A client pool: ${baseUrl}`);
881
882
  }
882
883
  /**
883
884
  * Send an A2A message to a specific agent
884
885
  */
885
886
  async sendToAgent(agentUrl, message, metadata) {
886
- const client = this.clients.get(agentUrl);
887
+ const baseUrl = this.extractBaseUrl(agentUrl);
888
+ const client = this.clients.get(baseUrl);
887
889
  if (!client) {
888
890
  return {
889
891
  success: false,
@@ -932,7 +934,7 @@ var WorldA2AClient = class {
932
934
  * Check if an agent is in the pool
933
935
  */
934
936
  has(agentUrl) {
935
- return this.clients.has(agentUrl);
937
+ return this.clients.has(this.extractBaseUrl(agentUrl));
936
938
  }
937
939
  /**
938
940
  * Get all agent URLs in the pool
@@ -1335,12 +1337,32 @@ var MessageRouter = class {
1335
1337
  this.a2aClient = a2aClient;
1336
1338
  this.getAgents = getAgents;
1337
1339
  }
1340
+ /**
1341
+ * Extract base URL (protocol://host:port) from a full URL for comparison.
1342
+ * Agent cards use full URLs (e.g. http://localhost:3001/a2a/jsonrpc)
1343
+ * while agents send base URLs (e.g. http://localhost:3001).
1344
+ */
1345
+ extractBaseUrl(url) {
1346
+ try {
1347
+ const parsed = new URL(url);
1348
+ return `${parsed.protocol}//${parsed.host}`;
1349
+ } catch {
1350
+ return url;
1351
+ }
1352
+ }
1353
+ /**
1354
+ * Find an agent by URL, normalizing both sides to base URL for comparison
1355
+ */
1356
+ findAgent(agents, url) {
1357
+ const baseUrl = this.extractBaseUrl(url);
1358
+ return agents.find((a) => this.extractBaseUrl(a.url) === baseUrl);
1359
+ }
1338
1360
  /**
1339
1361
  * Route a message from one agent to another
1340
1362
  */
1341
1363
  async route(fromAgentUrl, toAgentUrl, message) {
1342
1364
  const agents = this.getAgents();
1343
- const sender = agents.find((a) => a.url === fromAgentUrl);
1365
+ const sender = this.findAgent(agents, fromAgentUrl);
1344
1366
  if (!sender) {
1345
1367
  logger8.warn(`Message rejected \u2014 sender not in world: ${fromAgentUrl}`);
1346
1368
  return {
@@ -1348,7 +1370,7 @@ var MessageRouter = class {
1348
1370
  error: `Sender not in world: ${fromAgentUrl}`
1349
1371
  };
1350
1372
  }
1351
- const recipient = agents.find((a) => a.url === toAgentUrl);
1373
+ const recipient = this.findAgent(agents, toAgentUrl);
1352
1374
  if (!recipient) {
1353
1375
  logger8.warn(`Message rejected \u2014 recipient not in world: ${toAgentUrl}`);
1354
1376
  return {
@@ -1396,7 +1418,7 @@ ${c.green}\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u25
1396
1418
  */
1397
1419
  async routeToAll(fromAgentUrl, message) {
1398
1420
  const agents = this.getAgents();
1399
- const sender = agents.find((a) => a.url === fromAgentUrl);
1421
+ const sender = this.findAgent(agents, fromAgentUrl);
1400
1422
  if (!sender) {
1401
1423
  logger8.warn(`Broadcast rejected \u2014 sender not in world: ${fromAgentUrl}`);
1402
1424
  const result = /* @__PURE__ */ new Map();
@@ -1406,7 +1428,8 @@ ${c.green}\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u25
1406
1428
  });
1407
1429
  return result;
1408
1430
  }
1409
- const recipients = agents.filter((a) => a.url !== fromAgentUrl);
1431
+ const senderBaseUrl = this.extractBaseUrl(fromAgentUrl);
1432
+ const recipients = agents.filter((a) => this.extractBaseUrl(a.url) !== senderBaseUrl);
1410
1433
  console.log(
1411
1434
  `
1412
1435
  ${c.yellow}\u2501\u2501\u2501 BROADCAST \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${c.reset}
@@ -1621,6 +1644,10 @@ var World = class {
1621
1644
  * Admit an agent to the world
1622
1645
  */
1623
1646
  async admitAgent(card, walletAddress, paymentTxHash) {
1647
+ if (this.agents.has(card.url)) {
1648
+ logger9.info(`Agent already in world, skipping re-admission: ${card.name}`);
1649
+ return;
1650
+ }
1624
1651
  const decision = await this.evaluator.evaluate(card, this.agents.size, walletAddress);
1625
1652
  if (!decision.admitted) {
1626
1653
  throw new Error(`Agent admission denied: ${decision.reason}`);
@@ -1632,7 +1659,12 @@ var World = class {
1632
1659
  }
1633
1660
  logger9.info(`Agent validated on-chain: ${card.name}`);
1634
1661
  }
1635
- if (this.blockchainClient && this.config.blockchain?.requireMembership && walletAddress) {
1662
+ if (this.blockchainClient && this.config.blockchain?.requireMembership) {
1663
+ if (!walletAddress) {
1664
+ throw new Error(
1665
+ "This world requires blockchain membership. Provide a walletAddress when joining. Set AGENT_WALLET_PRIVATE_KEY in your .env file to auto-derive a wallet address."
1666
+ );
1667
+ }
1636
1668
  const hasMembership = await this.blockchainClient.hasMembership(walletAddress);
1637
1669
  if (!hasMembership) {
1638
1670
  const entryFeeWei = await this.blockchainClient.getEntryFeeWei();