@moltium/world-core 0.1.23 → 0.1.24

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
@@ -1335,12 +1335,32 @@ var MessageRouter = class {
1335
1335
  this.a2aClient = a2aClient;
1336
1336
  this.getAgents = getAgents;
1337
1337
  }
1338
+ /**
1339
+ * Extract base URL (protocol://host:port) from a full URL for comparison.
1340
+ * Agent cards use full URLs (e.g. http://localhost:3001/a2a/jsonrpc)
1341
+ * while agents send base URLs (e.g. http://localhost:3001).
1342
+ */
1343
+ extractBaseUrl(url) {
1344
+ try {
1345
+ const parsed = new URL(url);
1346
+ return `${parsed.protocol}//${parsed.host}`;
1347
+ } catch {
1348
+ return url;
1349
+ }
1350
+ }
1351
+ /**
1352
+ * Find an agent by URL, normalizing both sides to base URL for comparison
1353
+ */
1354
+ findAgent(agents, url) {
1355
+ const baseUrl = this.extractBaseUrl(url);
1356
+ return agents.find((a) => this.extractBaseUrl(a.url) === baseUrl);
1357
+ }
1338
1358
  /**
1339
1359
  * Route a message from one agent to another
1340
1360
  */
1341
1361
  async route(fromAgentUrl, toAgentUrl, message) {
1342
1362
  const agents = this.getAgents();
1343
- const sender = agents.find((a) => a.url === fromAgentUrl);
1363
+ const sender = this.findAgent(agents, fromAgentUrl);
1344
1364
  if (!sender) {
1345
1365
  logger8.warn(`Message rejected \u2014 sender not in world: ${fromAgentUrl}`);
1346
1366
  return {
@@ -1348,7 +1368,7 @@ var MessageRouter = class {
1348
1368
  error: `Sender not in world: ${fromAgentUrl}`
1349
1369
  };
1350
1370
  }
1351
- const recipient = agents.find((a) => a.url === toAgentUrl);
1371
+ const recipient = this.findAgent(agents, toAgentUrl);
1352
1372
  if (!recipient) {
1353
1373
  logger8.warn(`Message rejected \u2014 recipient not in world: ${toAgentUrl}`);
1354
1374
  return {
@@ -1396,7 +1416,7 @@ ${c.green}\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u25
1396
1416
  */
1397
1417
  async routeToAll(fromAgentUrl, message) {
1398
1418
  const agents = this.getAgents();
1399
- const sender = agents.find((a) => a.url === fromAgentUrl);
1419
+ const sender = this.findAgent(agents, fromAgentUrl);
1400
1420
  if (!sender) {
1401
1421
  logger8.warn(`Broadcast rejected \u2014 sender not in world: ${fromAgentUrl}`);
1402
1422
  const result = /* @__PURE__ */ new Map();
@@ -1406,7 +1426,8 @@ ${c.green}\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u25
1406
1426
  });
1407
1427
  return result;
1408
1428
  }
1409
- const recipients = agents.filter((a) => a.url !== fromAgentUrl);
1429
+ const senderBaseUrl = this.extractBaseUrl(fromAgentUrl);
1430
+ const recipients = agents.filter((a) => this.extractBaseUrl(a.url) !== senderBaseUrl);
1410
1431
  console.log(
1411
1432
  `
1412
1433
  ${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 +1642,10 @@ var World = class {
1621
1642
  * Admit an agent to the world
1622
1643
  */
1623
1644
  async admitAgent(card, walletAddress, paymentTxHash) {
1645
+ if (this.agents.has(card.url)) {
1646
+ logger9.info(`Agent already in world, skipping re-admission: ${card.name}`);
1647
+ return;
1648
+ }
1624
1649
  const decision = await this.evaluator.evaluate(card, this.agents.size, walletAddress);
1625
1650
  if (!decision.admitted) {
1626
1651
  throw new Error(`Agent admission denied: ${decision.reason}`);
@@ -1632,7 +1657,12 @@ var World = class {
1632
1657
  }
1633
1658
  logger9.info(`Agent validated on-chain: ${card.name}`);
1634
1659
  }
1635
- if (this.blockchainClient && this.config.blockchain?.requireMembership && walletAddress) {
1660
+ if (this.blockchainClient && this.config.blockchain?.requireMembership) {
1661
+ if (!walletAddress) {
1662
+ throw new Error(
1663
+ "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."
1664
+ );
1665
+ }
1636
1666
  const hasMembership = await this.blockchainClient.hasMembership(walletAddress);
1637
1667
  if (!hasMembership) {
1638
1668
  const entryFeeWei = await this.blockchainClient.getEntryFeeWei();