@moltium/core 0.1.19 → 0.1.21

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.mjs CHANGED
@@ -424,6 +424,140 @@ var moltbookActions = [
424
424
  readConversationAction
425
425
  ];
426
426
 
427
+ // src/actions/built-in/world.ts
428
+ function createJoinWorldAction(config) {
429
+ return {
430
+ name: "join_world",
431
+ description: `Join a world by URL. The world will fetch this agent's A2A Agent Card and evaluate admission. Parameters: worldUrl (string${config?.defaultWorldUrl ? ", optional" : ", required"}) - the world server URL${config?.defaultWorldUrl ? ` (defaults to ${config.defaultWorldUrl})` : ""}, walletAddress (string, optional) - wallet address for blockchain worlds.`,
432
+ async execute(context) {
433
+ const { parameters, agent } = context;
434
+ const worldUrl = parameters.worldUrl || config?.defaultWorldUrl;
435
+ if (!worldUrl) {
436
+ return { success: false, error: 'Parameter "worldUrl" is required' };
437
+ }
438
+ const agentPort = process.env.PORT || "3000";
439
+ const agentHost = process.env.HOST || "localhost";
440
+ const agentUrl = `http://${agentHost}:${agentPort}`;
441
+ try {
442
+ const { default: axios2 } = await import("axios");
443
+ const response = await axios2.post(`${worldUrl}/world/join`, {
444
+ agentUrl,
445
+ walletAddress: parameters.walletAddress || agent?.config?.world?.walletAddress
446
+ }, { timeout: 1e4 });
447
+ return {
448
+ success: true,
449
+ data: response.data
450
+ };
451
+ } catch (error) {
452
+ const msg = error?.response?.data?.error || error?.message || String(error);
453
+ return { success: false, error: `Failed to join world: ${msg}` };
454
+ }
455
+ }
456
+ };
457
+ }
458
+ function createLeaveWorldAction(config) {
459
+ return {
460
+ name: "leave_world",
461
+ description: `Leave a world. Parameters: worldUrl (string${config?.defaultWorldUrl ? ", optional" : ", required"}) - the world server URL.`,
462
+ async execute(context) {
463
+ const { parameters } = context;
464
+ const worldUrl = parameters.worldUrl || config?.defaultWorldUrl;
465
+ if (!worldUrl) {
466
+ return { success: false, error: 'Parameter "worldUrl" is required' };
467
+ }
468
+ const agentPort = process.env.PORT || "3000";
469
+ const agentHost = process.env.HOST || "localhost";
470
+ const agentUrl = `http://${agentHost}:${agentPort}`;
471
+ try {
472
+ const { default: axios2 } = await import("axios");
473
+ const response = await axios2.delete(
474
+ `${worldUrl}/world/agents/${encodeURIComponent(agentUrl)}`,
475
+ { timeout: 1e4 }
476
+ );
477
+ return {
478
+ success: true,
479
+ data: response.data
480
+ };
481
+ } catch (error) {
482
+ const msg = error?.response?.data?.error || error?.message || String(error);
483
+ return { success: false, error: `Failed to leave world: ${msg}` };
484
+ }
485
+ }
486
+ };
487
+ }
488
+ function createQueryWorldAction(config) {
489
+ return {
490
+ name: "query_world",
491
+ description: `Query a world's state, agents, and available actions. Parameters: worldUrl (string${config?.defaultWorldUrl ? ", optional" : ", required"}) - the world server URL, endpoint (string, optional) - specific endpoint: "state", "agents", "actions", or "info" (default: "info").`,
492
+ async execute(context) {
493
+ const { parameters } = context;
494
+ const worldUrl = parameters.worldUrl || config?.defaultWorldUrl;
495
+ if (!worldUrl) {
496
+ return { success: false, error: 'Parameter "worldUrl" is required' };
497
+ }
498
+ const endpoint = parameters.endpoint || "info";
499
+ const pathMap = {
500
+ info: "/",
501
+ state: "/world/state",
502
+ agents: "/world/agents",
503
+ actions: "/world/actions"
504
+ };
505
+ const path = pathMap[endpoint] || "/";
506
+ try {
507
+ const { default: axios2 } = await import("axios");
508
+ const response = await axios2.get(`${worldUrl}${path}`, { timeout: 1e4 });
509
+ return {
510
+ success: true,
511
+ data: response.data
512
+ };
513
+ } catch (error) {
514
+ const msg = error?.response?.data?.error || error?.message || String(error);
515
+ return { success: false, error: `Failed to query world: ${msg}` };
516
+ }
517
+ }
518
+ };
519
+ }
520
+ function createSendWorldMessageAction(config) {
521
+ return {
522
+ name: "send_world_message",
523
+ description: `Send a message to another agent through the world hub. Parameters: worldUrl (string${config?.defaultWorldUrl ? ", optional" : ", required"}) - the world server URL, toAgentUrl (string, optional) - target agent URL (omit to broadcast to all), message (string, required) - the message to send.`,
524
+ async execute(context) {
525
+ const { parameters } = context;
526
+ const worldUrl = parameters.worldUrl || config?.defaultWorldUrl;
527
+ if (!worldUrl) {
528
+ return { success: false, error: 'Parameter "worldUrl" is required' };
529
+ }
530
+ if (!parameters.message) {
531
+ return { success: false, error: 'Parameter "message" is required' };
532
+ }
533
+ const agentPort = process.env.PORT || "3000";
534
+ const agentHost = process.env.HOST || "localhost";
535
+ const agentUrl = `http://${agentHost}:${agentPort}`;
536
+ try {
537
+ const { default: axios2 } = await import("axios");
538
+ const response = await axios2.post(`${worldUrl}/world/message`, {
539
+ fromAgentUrl: agentUrl,
540
+ toAgentUrl: parameters.toAgentUrl,
541
+ message: parameters.message
542
+ }, { timeout: 15e3 });
543
+ return {
544
+ success: true,
545
+ data: response.data
546
+ };
547
+ } catch (error) {
548
+ const msg = error?.response?.data?.error || error?.message || String(error);
549
+ return { success: false, error: `Failed to send world message: ${msg}` };
550
+ }
551
+ }
552
+ };
553
+ }
554
+ var worldActions = {
555
+ createJoinWorldAction,
556
+ createLeaveWorldAction,
557
+ createQueryWorldAction,
558
+ createSendWorldMessageAction
559
+ };
560
+
427
561
  // src/actions/built-in/index.ts
428
562
  var builtInActions = [
429
563
  postSocialUpdateAction,
@@ -1318,6 +1452,178 @@ var TwitterAdapter = class extends SocialAdapter {
1318
1452
  }
1319
1453
  };
1320
1454
 
1455
+ // src/a2a/client.ts
1456
+ import { A2AClient as SDKClient } from "@a2a-js/sdk/client";
1457
+ import { v4 as uuidv4 } from "uuid";
1458
+ var A2AClient = class {
1459
+ sdkClient;
1460
+ config;
1461
+ constructor(config) {
1462
+ this.config = {
1463
+ agentUrl: config.agentUrl,
1464
+ agentCardPath: config.agentCardPath || ".well-known/agent-card.json",
1465
+ timeout: config.timeout || 3e4
1466
+ };
1467
+ const agentUrl = this.config.agentUrl;
1468
+ const agentCardPath = this.config.agentCardPath;
1469
+ this.sdkClient = new SDKClient(agentUrl, agentCardPath);
1470
+ }
1471
+ /**
1472
+ * Send a text message to the agent and get a response
1473
+ *
1474
+ * @param options Message options including text content
1475
+ * @returns Promise resolving to the agent's response
1476
+ *
1477
+ * @example
1478
+ * ```typescript
1479
+ * const response = await client.sendMessage({
1480
+ * text: 'What are your thoughts on AI?',
1481
+ * contextId: 'conversation-123'
1482
+ * });
1483
+ *
1484
+ * if (response.success) {
1485
+ * console.log('Agent replied:', response.reply);
1486
+ * }
1487
+ * ```
1488
+ */
1489
+ async sendMessage(options) {
1490
+ try {
1491
+ const response = await this.sdkClient.sendMessage({
1492
+ message: {
1493
+ kind: "message",
1494
+ messageId: uuidv4(),
1495
+ role: "user",
1496
+ contextId: options.contextId,
1497
+ metadata: options.metadata,
1498
+ parts: [
1499
+ {
1500
+ kind: "text",
1501
+ text: options.text
1502
+ }
1503
+ ]
1504
+ }
1505
+ });
1506
+ const reply = this.extractReply(response);
1507
+ return {
1508
+ success: true,
1509
+ reply,
1510
+ agentUrl: this.config.agentUrl,
1511
+ raw: response
1512
+ };
1513
+ } catch (error) {
1514
+ return {
1515
+ success: false,
1516
+ error: error.message || "Unknown error occurred",
1517
+ agentUrl: this.config.agentUrl
1518
+ };
1519
+ }
1520
+ }
1521
+ /**
1522
+ * Extract text reply from A2A protocol response
1523
+ * Handles both Message and Task response types
1524
+ */
1525
+ extractReply(response) {
1526
+ if (!("result" in response) || !response.result) {
1527
+ return JSON.stringify(response);
1528
+ }
1529
+ const result = response.result;
1530
+ if ("kind" in result && result.kind === "message" && "parts" in result) {
1531
+ const textParts = result.parts.filter((part) => part.kind === "text").map((part) => part.text);
1532
+ return textParts.join("\n");
1533
+ }
1534
+ return typeof result === "string" ? result : JSON.stringify(result);
1535
+ }
1536
+ /**
1537
+ * Get the agent card information
1538
+ *
1539
+ * @returns Promise resolving to the agent card
1540
+ */
1541
+ async getAgentCard() {
1542
+ return this.sdkClient.getAgentCard();
1543
+ }
1544
+ /**
1545
+ * Get the base URL of the agent
1546
+ */
1547
+ getAgentUrl() {
1548
+ return this.config.agentUrl;
1549
+ }
1550
+ };
1551
+ function createA2AClient(agentUrlOrConfig) {
1552
+ const config = typeof agentUrlOrConfig === "string" ? { agentUrl: agentUrlOrConfig } : agentUrlOrConfig;
1553
+ return new A2AClient(config);
1554
+ }
1555
+
1556
+ // src/a2a/actions.ts
1557
+ function createA2ACommunicationAction(config = {}) {
1558
+ const {
1559
+ defaultAgentUrl,
1560
+ actionName = "talk_to_agent",
1561
+ description,
1562
+ verbose = false
1563
+ } = config;
1564
+ const defaultDescription = description || `Send a message to another A2A-compliant agent and receive their response. Parameters: message (required string) - the message to send, agentUrl (optional string) - target agent URL${defaultAgentUrl ? ` (defaults to ${defaultAgentUrl})` : ""}`;
1565
+ return {
1566
+ name: actionName,
1567
+ description: defaultDescription,
1568
+ async execute(context) {
1569
+ const { parameters } = context;
1570
+ const message = parameters.message;
1571
+ const agentUrl = parameters.agentUrl || defaultAgentUrl;
1572
+ if (!message) {
1573
+ return {
1574
+ success: false,
1575
+ error: 'Parameter "message" is required'
1576
+ };
1577
+ }
1578
+ if (!agentUrl) {
1579
+ return {
1580
+ success: false,
1581
+ error: 'Parameter "agentUrl" is required or defaultAgentUrl must be configured'
1582
+ };
1583
+ }
1584
+ if (verbose) {
1585
+ console.log(`[A2A] Sending message to ${agentUrl}:`, message);
1586
+ }
1587
+ try {
1588
+ const client = new A2AClient({ agentUrl });
1589
+ const response = await client.sendMessage({ text: message });
1590
+ if (verbose) {
1591
+ console.log(`[A2A] Response from ${agentUrl}:`, response.reply);
1592
+ }
1593
+ if (!response.success) {
1594
+ return {
1595
+ success: false,
1596
+ error: response.error || "Failed to communicate with agent"
1597
+ };
1598
+ }
1599
+ return {
1600
+ success: true,
1601
+ data: {
1602
+ reply: response.reply,
1603
+ agentUrl: response.agentUrl
1604
+ }
1605
+ };
1606
+ } catch (error) {
1607
+ if (verbose) {
1608
+ console.error(`[A2A] Error:`, error);
1609
+ }
1610
+ return {
1611
+ success: false,
1612
+ error: error.message || "Unknown error occurred"
1613
+ };
1614
+ }
1615
+ }
1616
+ };
1617
+ }
1618
+ function createMultipleA2AActions(configs) {
1619
+ return Object.entries(configs).map(
1620
+ ([name, config]) => createA2ACommunicationAction({
1621
+ ...config,
1622
+ actionName: name
1623
+ })
1624
+ );
1625
+ }
1626
+
1321
1627
  // src/agent/Agent.ts
1322
1628
  var logger4 = createLogger("Agent");
1323
1629
  function parsePostFrequency(freq) {
@@ -1438,6 +1744,9 @@ var Agent = class {
1438
1744
  if (this.hooks.onStart) {
1439
1745
  await this.hooks.onStart(this);
1440
1746
  }
1747
+ if (this.config.world?.url && this.config.world.autoJoin !== false) {
1748
+ await this.autoJoinWorld();
1749
+ }
1441
1750
  this.scheduler.start();
1442
1751
  if (this.config.behaviors.autonomous) {
1443
1752
  this.startAutonomousLoop();
@@ -1571,6 +1880,53 @@ var Agent = class {
1571
1880
  }
1572
1881
  logger4.info(`Registered ${moltbookActions.length} Moltbook actions`);
1573
1882
  }
1883
+ const a2a = this.config.a2a;
1884
+ if (a2a && a2a.enabled !== false) {
1885
+ if (a2a.peers && Object.keys(a2a.peers).length > 0) {
1886
+ const peerActions = createMultipleA2AActions(
1887
+ Object.entries(a2a.peers).reduce((acc, [actionName, url]) => {
1888
+ acc[actionName] = {
1889
+ defaultAgentUrl: url,
1890
+ verbose: a2a.verbose,
1891
+ description: `Communicate with peer agent at ${url}`
1892
+ };
1893
+ return acc;
1894
+ }, {})
1895
+ );
1896
+ for (const action of peerActions) {
1897
+ if (!this.actionRegistry.has(action.name)) {
1898
+ this.actionRegistry.register(action);
1899
+ }
1900
+ }
1901
+ logger4.info(`Registered ${peerActions.length} A2A peer actions`);
1902
+ } else {
1903
+ const genericAction = createA2ACommunicationAction({
1904
+ defaultAgentUrl: a2a.defaultPeerUrl,
1905
+ actionName: a2a.genericActionName || "talk_to_agent",
1906
+ verbose: a2a.verbose
1907
+ });
1908
+ if (!this.actionRegistry.has(genericAction.name)) {
1909
+ this.actionRegistry.register(genericAction);
1910
+ }
1911
+ logger4.info(`Registered generic A2A action: ${genericAction.name}`);
1912
+ }
1913
+ }
1914
+ const world = this.config.world;
1915
+ if (world?.url) {
1916
+ const worldUrl = world.url;
1917
+ const worldActionsList = [
1918
+ createJoinWorldAction({ defaultWorldUrl: worldUrl }),
1919
+ createLeaveWorldAction({ defaultWorldUrl: worldUrl }),
1920
+ createQueryWorldAction({ defaultWorldUrl: worldUrl }),
1921
+ createSendWorldMessageAction({ defaultWorldUrl: worldUrl })
1922
+ ];
1923
+ for (const action of worldActionsList) {
1924
+ if (!this.actionRegistry.has(action.name)) {
1925
+ this.actionRegistry.register(action);
1926
+ }
1927
+ }
1928
+ logger4.info(`Registered 4 world actions (world: ${worldUrl})`);
1929
+ }
1574
1930
  if (this.config.customActions) {
1575
1931
  for (const action of this.config.customActions) {
1576
1932
  this.actionRegistry.register(action);
@@ -1857,6 +2213,23 @@ Decide what action to take. Respond with JSON:
1857
2213
  logger4.error(` ${platform}: Server error \u2014 the platform may be temporarily down.`);
1858
2214
  }
1859
2215
  }
2216
+ async autoJoinWorld() {
2217
+ const worldUrl = this.config.world.url;
2218
+ logger4.info(`Auto-joining world: ${worldUrl}`);
2219
+ try {
2220
+ const result = await this.act("join_world", {
2221
+ worldUrl,
2222
+ walletAddress: this.config.world.walletAddress
2223
+ });
2224
+ if (result.success) {
2225
+ logger4.info(`Successfully joined world: ${worldUrl}`);
2226
+ } else {
2227
+ logger4.warn(`Failed to join world: ${result.error}`);
2228
+ }
2229
+ } catch (error) {
2230
+ logger4.warn(`Auto-join world failed: ${error?.message || error}`);
2231
+ }
2232
+ }
1860
2233
  startAutonomousLoop() {
1861
2234
  const actionsPerHour = typeof this.config.behaviors.actionsPerHour === "function" ? this.config.behaviors.actionsPerHour({}) : this.config.behaviors.actionsPerHour || 5;
1862
2235
  const intervalMs = Math.floor(36e5 / actionsPerHour);
@@ -1919,6 +2292,7 @@ var MarkdownParser = class {
1919
2292
  const memory = this.findSection(sections, "Memory");
1920
2293
  const skills = this.findSection(sections, "Skills");
1921
2294
  const scheduling = this.findSection(sections, "Scheduling");
2295
+ const world = this.findSection(sections, "World");
1922
2296
  const identityData = this.parseIdentity(identity);
1923
2297
  const bioText = bio ? bio.content.trim() : identityData?.personality?.bio || "";
1924
2298
  const config = {
@@ -1930,6 +2304,7 @@ var MarkdownParser = class {
1930
2304
  ...social ? { social: this.parseSocial(social) } : {},
1931
2305
  ...behaviors ? { behaviors: this.parseBehaviors(behaviors) } : {},
1932
2306
  ...memory ? { memory: this.parseMemory(memory) } : {},
2307
+ ...world ? { world: this.parseWorld(world) } : {},
1933
2308
  actions: [],
1934
2309
  ...frontmatter
1935
2310
  };
@@ -2030,6 +2405,16 @@ var MarkdownParser = class {
2030
2405
  retention: fields["retention"]
2031
2406
  };
2032
2407
  }
2408
+ parseWorld(section) {
2409
+ const fields = this.parseKeyValueLines(section.content);
2410
+ const url = fields["url"];
2411
+ if (!url) return void 0;
2412
+ return {
2413
+ url,
2414
+ autoJoin: fields["auto_join"] !== "false",
2415
+ ...fields["wallet_address"] ? { walletAddress: fields["wallet_address"] } : {}
2416
+ };
2417
+ }
2033
2418
  parseSleepSchedule(value) {
2034
2419
  const match = value.match(/(\d{1,2}):?\d{0,2}\s*-\s*(\d{1,2}):?\d{0,2}\s*(.*)?/);
2035
2420
  if (!match) return { start: 22, end: 6 };
@@ -2560,27 +2945,516 @@ function authMiddleware(req, res, next) {
2560
2945
  next();
2561
2946
  }
2562
2947
 
2948
+ // src/a2a/AgentCardBuilder.ts
2949
+ var logger7 = createLogger("AgentCardBuilder");
2950
+ var AgentCardBuilder = class {
2951
+ /**
2952
+ * Creates an A2A AgentCard from Moltium configuration.
2953
+ * @param config The Moltium agent configuration
2954
+ * @param a2aConfig A2A-specific configuration (URLs, capabilities)
2955
+ * @returns A2A-compliant AgentCard
2956
+ */
2957
+ static build(config, a2aConfig) {
2958
+ const baseUrl = a2aConfig.baseUrl;
2959
+ const skills = this.buildSkills(config);
2960
+ const capabilities = {
2961
+ streaming: a2aConfig.streaming ?? true,
2962
+ pushNotifications: a2aConfig.pushNotifications ?? false,
2963
+ stateTransitionHistory: a2aConfig.stateTransitionHistory ?? true
2964
+ };
2965
+ const defaultInputModes = ["text"];
2966
+ const defaultOutputModes = ["text"];
2967
+ const agentCard = {
2968
+ name: config.name,
2969
+ description: config.personality.bio || `${config.name} - An autonomous AI agent`,
2970
+ protocolVersion: "0.3.0",
2971
+ version: "0.1.0",
2972
+ url: `${baseUrl}/a2a/jsonrpc`,
2973
+ skills,
2974
+ capabilities,
2975
+ defaultInputModes,
2976
+ defaultOutputModes,
2977
+ additionalInterfaces: [
2978
+ { url: `${baseUrl}/a2a/jsonrpc`, transport: "JSONRPC" },
2979
+ { url: `${baseUrl}/a2a/rest`, transport: "HTTP+JSON" }
2980
+ ]
2981
+ };
2982
+ logger7.debug("Built A2A AgentCard", {
2983
+ name: agentCard.name,
2984
+ skillCount: skills.length,
2985
+ baseUrl
2986
+ });
2987
+ return agentCard;
2988
+ }
2989
+ /**
2990
+ * Converts Moltium actions to A2A skills.
2991
+ */
2992
+ static buildSkills(config) {
2993
+ const skills = [];
2994
+ skills.push({
2995
+ id: "chat",
2996
+ name: "Chat",
2997
+ description: `Interact with ${config.name}. ${config.personality.bio || ""}`,
2998
+ tags: ["chat", "conversation"]
2999
+ });
3000
+ const hasPosting = config.actions.some(
3001
+ (a) => a.includes("post") || a.includes("update")
3002
+ );
3003
+ if (hasPosting) {
3004
+ skills.push({
3005
+ id: "social_posting",
3006
+ name: "Social Posting",
3007
+ description: "Post updates and content to social platforms",
3008
+ tags: ["social", "posting"]
3009
+ });
3010
+ }
3011
+ const hasEngagement = config.actions.some(
3012
+ (a) => a.includes("comment") || a.includes("reply") || a.includes("respond")
3013
+ );
3014
+ if (hasEngagement) {
3015
+ skills.push({
3016
+ id: "social_engagement",
3017
+ name: "Social Engagement",
3018
+ description: "Engage with others through comments and replies",
3019
+ tags: ["social", "engagement"]
3020
+ });
3021
+ }
3022
+ const hasSearch = config.actions.some(
3023
+ (a) => a.includes("search") || a.includes("check_feed") || a.includes("browse")
3024
+ );
3025
+ if (hasSearch) {
3026
+ skills.push({
3027
+ id: "content_discovery",
3028
+ name: "Content Discovery",
3029
+ description: "Search and discover relevant content",
3030
+ tags: ["search", "discovery"]
3031
+ });
3032
+ }
3033
+ const hasAnalysis = config.actions.some(
3034
+ (a) => a.includes("analyze") || a.includes("think") || a.includes("research")
3035
+ );
3036
+ if (hasAnalysis) {
3037
+ skills.push({
3038
+ id: "analysis",
3039
+ name: "Analysis & Research",
3040
+ description: "Analyze problems and conduct research",
3041
+ tags: ["analysis", "research", "thinking"]
3042
+ });
3043
+ }
3044
+ return skills;
3045
+ }
3046
+ /**
3047
+ * Updates an agent card with runtime information.
3048
+ */
3049
+ static updateWithRuntime(agentCard, actualPort, actualHost = "localhost") {
3050
+ const protocol = actualHost === "localhost" || actualHost === "127.0.0.1" ? "http" : "https";
3051
+ const baseUrl = `${protocol}://${actualHost}:${actualPort}`;
3052
+ return {
3053
+ ...agentCard,
3054
+ url: `${baseUrl}/a2a/jsonrpc`,
3055
+ additionalInterfaces: [
3056
+ { url: `${baseUrl}/a2a/jsonrpc`, transport: "JSONRPC" },
3057
+ { url: `${baseUrl}/a2a/rest`, transport: "HTTP+JSON" }
3058
+ ]
3059
+ };
3060
+ }
3061
+ };
3062
+
3063
+ // src/a2a/MoltiumExecutor.ts
3064
+ import { v4 as uuidv42 } from "uuid";
3065
+ var logger8 = createLogger("MoltiumExecutor");
3066
+ var MoltiumExecutor = class {
3067
+ agent;
3068
+ cancelledTasks = /* @__PURE__ */ new Set();
3069
+ constructor(agent) {
3070
+ this.agent = agent;
3071
+ }
3072
+ /**
3073
+ * Executes an A2A request using the Moltium agent.
3074
+ * Converts A2A messages to Moltium actions and publishes results back via the event bus.
3075
+ */
3076
+ async execute(requestContext, eventBus) {
3077
+ const { taskId, contextId, userMessage, task } = requestContext;
3078
+ try {
3079
+ logger8.info(`[A2A] Executing request for task ${taskId}`);
3080
+ if (!task) {
3081
+ const initialTask = {
3082
+ kind: "task",
3083
+ id: taskId,
3084
+ contextId,
3085
+ status: {
3086
+ state: "submitted",
3087
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
3088
+ },
3089
+ history: [userMessage]
3090
+ };
3091
+ eventBus.publish(initialTask);
3092
+ }
3093
+ if (this.cancelledTasks.has(taskId)) {
3094
+ this.publishCancellation(taskId, contextId, eventBus);
3095
+ return;
3096
+ }
3097
+ this.publishStatusUpdate(taskId, contextId, "working", eventBus, false);
3098
+ const userContent = this.extractMessageContent(userMessage);
3099
+ const isActionRequest = this.isActionRequest(userContent);
3100
+ let result;
3101
+ if (isActionRequest) {
3102
+ result = await this.executeAction(userContent, taskId);
3103
+ } else {
3104
+ result = await this.executeChat(userContent, taskId);
3105
+ }
3106
+ if (this.cancelledTasks.has(taskId)) {
3107
+ this.publishCancellation(taskId, contextId, eventBus);
3108
+ return;
3109
+ }
3110
+ if (result.success) {
3111
+ await this.publishResult(taskId, contextId, result, eventBus);
3112
+ } else {
3113
+ await this.publishError(taskId, contextId, result.error || "Unknown error", eventBus);
3114
+ }
3115
+ this.publishStatusUpdate(taskId, contextId, "completed", eventBus, true);
3116
+ eventBus.finished();
3117
+ logger8.info(`[A2A] Task ${taskId} completed successfully`);
3118
+ } catch (error) {
3119
+ logger8.error(`[A2A] Task ${taskId} failed`, {
3120
+ error: error instanceof Error ? error.message : String(error)
3121
+ });
3122
+ const errorMessage = error instanceof Error ? error.message : String(error);
3123
+ await this.publishError(taskId, contextId, errorMessage, eventBus);
3124
+ this.publishStatusUpdate(taskId, contextId, "failed", eventBus, true);
3125
+ eventBus.finished();
3126
+ } finally {
3127
+ this.cancelledTasks.delete(taskId);
3128
+ }
3129
+ }
3130
+ /**
3131
+ * Handles task cancellation requests.
3132
+ */
3133
+ async cancelTask(taskId, eventBus) {
3134
+ logger8.info(`[A2A] Cancellation requested for task ${taskId}`);
3135
+ this.cancelledTasks.add(taskId);
3136
+ }
3137
+ /**
3138
+ * Extracts text content from an A2A message.
3139
+ */
3140
+ extractMessageContent(message) {
3141
+ const textParts = message.parts.filter((part) => part.kind === "text");
3142
+ return textParts.map((part) => part.text).join("\n");
3143
+ }
3144
+ /**
3145
+ * Determines if the user message is requesting a specific action.
3146
+ */
3147
+ isActionRequest(content) {
3148
+ const actionKeywords = [
3149
+ "post",
3150
+ "search",
3151
+ "check feed",
3152
+ "browse",
3153
+ "comment",
3154
+ "upvote",
3155
+ "follow",
3156
+ "send dm"
3157
+ ];
3158
+ const lowerContent = content.toLowerCase();
3159
+ return actionKeywords.some((keyword) => lowerContent.includes(keyword));
3160
+ }
3161
+ /**
3162
+ * Executes a chat interaction using the agent's LLM.
3163
+ */
3164
+ async executeChat(userContent, taskId) {
3165
+ try {
3166
+ const llm = this.agent.getLLM();
3167
+ const systemPrompt = this.agent.getSystemPrompt();
3168
+ const response = await llm.generateText(userContent, {
3169
+ systemPrompt,
3170
+ temperature: this.agent.config.llm.temperature
3171
+ });
3172
+ return {
3173
+ success: true,
3174
+ data: { response, type: "chat" }
3175
+ };
3176
+ } catch (error) {
3177
+ return {
3178
+ success: false,
3179
+ error: `Chat execution failed: ${error instanceof Error ? error.message : String(error)}`
3180
+ };
3181
+ }
3182
+ }
3183
+ /**
3184
+ * Executes an action based on the user's request.
3185
+ */
3186
+ async executeAction(userContent, taskId) {
3187
+ try {
3188
+ const decision = await this.agent.think();
3189
+ const result = await this.agent.act(decision.action, decision.parameters);
3190
+ return {
3191
+ success: result.success,
3192
+ data: {
3193
+ action: decision.action,
3194
+ reasoning: decision.reasoning,
3195
+ result: result.data,
3196
+ type: "action"
3197
+ },
3198
+ error: result.error
3199
+ };
3200
+ } catch (error) {
3201
+ return {
3202
+ success: false,
3203
+ error: `Action execution failed: ${error instanceof Error ? error.message : String(error)}`
3204
+ };
3205
+ }
3206
+ }
3207
+ /**
3208
+ * Publishes a successful result as an A2A artifact.
3209
+ */
3210
+ async publishResult(taskId, contextId, result, eventBus) {
3211
+ const data = result.data;
3212
+ if (data?.type === "chat") {
3213
+ const artifactUpdate = {
3214
+ kind: "artifact-update",
3215
+ taskId,
3216
+ contextId,
3217
+ artifact: {
3218
+ artifactId: `response-${uuidv42()}`,
3219
+ name: "response.txt",
3220
+ parts: [{ kind: "text", text: data.response }]
3221
+ }
3222
+ };
3223
+ eventBus.publish(artifactUpdate);
3224
+ } else if (data?.type === "action") {
3225
+ const resultText = JSON.stringify(
3226
+ {
3227
+ action: data.action,
3228
+ reasoning: data.reasoning,
3229
+ result: data.result
3230
+ },
3231
+ null,
3232
+ 2
3233
+ );
3234
+ const artifactUpdate = {
3235
+ kind: "artifact-update",
3236
+ taskId,
3237
+ contextId,
3238
+ artifact: {
3239
+ artifactId: `action-result-${uuidv42()}`,
3240
+ name: "action_result.json",
3241
+ parts: [{ kind: "text", text: resultText }]
3242
+ }
3243
+ };
3244
+ eventBus.publish(artifactUpdate);
3245
+ } else {
3246
+ const resultText = typeof result.data === "string" ? result.data : JSON.stringify(result.data, null, 2);
3247
+ const artifactUpdate = {
3248
+ kind: "artifact-update",
3249
+ taskId,
3250
+ contextId,
3251
+ artifact: {
3252
+ artifactId: `result-${uuidv42()}`,
3253
+ name: "result.txt",
3254
+ parts: [{ kind: "text", text: resultText }]
3255
+ }
3256
+ };
3257
+ eventBus.publish(artifactUpdate);
3258
+ }
3259
+ }
3260
+ /**
3261
+ * Publishes an error as an A2A artifact.
3262
+ */
3263
+ async publishError(taskId, contextId, error, eventBus) {
3264
+ const artifactUpdate = {
3265
+ kind: "artifact-update",
3266
+ taskId,
3267
+ contextId,
3268
+ artifact: {
3269
+ artifactId: `error-${uuidv42()}`,
3270
+ name: "error.txt",
3271
+ parts: [{ kind: "text", text: `Error: ${error}` }]
3272
+ }
3273
+ };
3274
+ eventBus.publish(artifactUpdate);
3275
+ }
3276
+ /**
3277
+ * Publishes a status update event.
3278
+ */
3279
+ publishStatusUpdate(taskId, contextId, state, eventBus, final) {
3280
+ const statusUpdate = {
3281
+ kind: "status-update",
3282
+ taskId,
3283
+ contextId,
3284
+ status: {
3285
+ state,
3286
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
3287
+ },
3288
+ final
3289
+ };
3290
+ eventBus.publish(statusUpdate);
3291
+ }
3292
+ /**
3293
+ * Publishes a cancellation status.
3294
+ */
3295
+ publishCancellation(taskId, contextId, eventBus) {
3296
+ logger8.info(`[A2A] Publishing cancellation for task ${taskId}`);
3297
+ this.publishStatusUpdate(taskId, contextId, "canceled", eventBus, true);
3298
+ eventBus.finished();
3299
+ this.cancelledTasks.delete(taskId);
3300
+ }
3301
+ };
3302
+
3303
+ // src/a2a/integration.ts
3304
+ import { DefaultRequestHandler, InMemoryTaskStore, JsonRpcTransportHandler } from "@a2a-js/sdk/server";
3305
+ var logger9 = createLogger("A2AIntegration");
3306
+ var A2AIntegration = class {
3307
+ agent;
3308
+ agentCard;
3309
+ requestHandler;
3310
+ moltiumExecutor;
3311
+ constructor(agent, options) {
3312
+ this.agent = agent;
3313
+ this.agentCard = AgentCardBuilder.build(agent.config, options.a2aConfig);
3314
+ this.moltiumExecutor = new MoltiumExecutor(agent);
3315
+ this.requestHandler = new DefaultRequestHandler(
3316
+ this.agentCard,
3317
+ new InMemoryTaskStore(),
3318
+ this.moltiumExecutor
3319
+ );
3320
+ logger9.info("A2A integration initialized", {
3321
+ agentName: agent.name,
3322
+ baseUrl: options.a2aConfig.baseUrl
3323
+ });
3324
+ }
3325
+ /**
3326
+ * Creates Express middleware handlers for A2A endpoints.
3327
+ * Returns an object with individual handlers that can be mounted on specific routes.
3328
+ */
3329
+ getHandlers() {
3330
+ return {
3331
+ // Agent Card endpoint - serves the static agent card JSON
3332
+ agentCard: ((req, res) => {
3333
+ res.json(this.agentCard);
3334
+ }),
3335
+ // JSON-RPC endpoint - handles A2A protocol requests
3336
+ jsonRpc: (async (req, res) => {
3337
+ try {
3338
+ const jsonRpcHandler = new JsonRpcTransportHandler(this.requestHandler);
3339
+ const response = await jsonRpcHandler.handle(req.body);
3340
+ res.json(response);
3341
+ } catch (error) {
3342
+ logger9.error("JSON-RPC error:", error);
3343
+ res.status(500).json({
3344
+ jsonrpc: "2.0",
3345
+ error: {
3346
+ code: -32603,
3347
+ message: "Internal error",
3348
+ data: error.message
3349
+ },
3350
+ id: req.body?.id || null
3351
+ });
3352
+ }
3353
+ }),
3354
+ // REST endpoint - simplified HTTP+JSON interface
3355
+ rest: ((req, res) => {
3356
+ res.status(501).json({
3357
+ error: "REST transport not implemented in SDK v0.3.0",
3358
+ message: "Please use the JSON-RPC endpoint at /a2a/jsonrpc"
3359
+ });
3360
+ })
3361
+ };
3362
+ }
3363
+ /**
3364
+ * Updates the agent card with actual runtime information (host/port).
3365
+ */
3366
+ updateAgentCard(actualPort, actualHost = "localhost") {
3367
+ this.agentCard = AgentCardBuilder.updateWithRuntime(this.agentCard, actualPort, actualHost);
3368
+ this.requestHandler = new DefaultRequestHandler(
3369
+ this.agentCard,
3370
+ new InMemoryTaskStore(),
3371
+ this.moltiumExecutor
3372
+ );
3373
+ logger9.info("A2A agent card updated with runtime info", {
3374
+ host: actualHost,
3375
+ port: actualPort,
3376
+ url: this.agentCard.url
3377
+ });
3378
+ }
3379
+ /**
3380
+ * Gets the current agent card.
3381
+ */
3382
+ getAgentCard() {
3383
+ return this.agentCard;
3384
+ }
3385
+ /**
3386
+ * Logs A2A endpoint information.
3387
+ */
3388
+ logEndpoints(host, port) {
3389
+ const protocol = host === "localhost" || host === "127.0.0.1" ? "http" : "https";
3390
+ const baseUrl = `${protocol}://${host}:${port}`;
3391
+ logger9.info("A2A endpoints available:");
3392
+ logger9.info(` Agent Card: ${baseUrl}/.well-known/agent-card.json`);
3393
+ logger9.info(` JSON-RPC: ${baseUrl}/a2a/jsonrpc`);
3394
+ logger9.info(` HTTP+JSON: ${baseUrl}/a2a/rest`);
3395
+ }
3396
+ };
3397
+ function createA2AIntegration(agent, options = {}) {
3398
+ const a2aConfig = {
3399
+ enabled: true,
3400
+ baseUrl: options.a2aConfig?.baseUrl || "http://localhost:3000",
3401
+ pushNotifications: options.a2aConfig?.pushNotifications ?? false,
3402
+ streaming: options.a2aConfig?.streaming ?? true,
3403
+ stateTransitionHistory: options.a2aConfig?.stateTransitionHistory ?? true
3404
+ };
3405
+ return new A2AIntegration(agent, { a2aConfig, ...options });
3406
+ }
3407
+
2563
3408
  // src/server/app.ts
2564
- var logger7 = createLogger("Server");
2565
- function createApp(agent) {
3409
+ var logger10 = createLogger("Server");
3410
+ var AGENT_CARD_PATH = ".well-known/agent-card.json";
3411
+ function createApp(agent, options = {}) {
2566
3412
  const app = express();
2567
3413
  app.use(express.json());
2568
3414
  app.use(requestLogger);
2569
3415
  app.use(authMiddleware);
2570
3416
  app.use(createRoutes(agent));
3417
+ if (options.enableA2A !== false) {
3418
+ const port = options.port || parseInt(process.env.PORT || "3000", 10);
3419
+ const host = options.host || "0.0.0.0";
3420
+ const protocol = host === "localhost" || host === "127.0.0.1" || host === "0.0.0.0" ? "http" : "https";
3421
+ const baseUrl = options.a2aConfig?.baseUrl || `${protocol}://${host}:${port}`;
3422
+ const a2aIntegration = createA2AIntegration(agent, {
3423
+ a2aConfig: {
3424
+ enabled: true,
3425
+ baseUrl,
3426
+ pushNotifications: options.a2aConfig?.pushNotifications ?? false,
3427
+ streaming: options.a2aConfig?.streaming ?? true,
3428
+ stateTransitionHistory: options.a2aConfig?.stateTransitionHistory ?? true
3429
+ }
3430
+ });
3431
+ const handlers = a2aIntegration.getHandlers();
3432
+ app.use(`/${AGENT_CARD_PATH}`, handlers.agentCard);
3433
+ app.use("/a2a/jsonrpc", handlers.jsonRpc);
3434
+ app.use("/a2a/rest", handlers.rest);
3435
+ logger10.info("A2A protocol endpoints enabled");
3436
+ }
2571
3437
  app.use(errorHandler);
2572
3438
  return app;
2573
3439
  }
2574
3440
  async function startServer(agent, options = {}) {
2575
3441
  const port = options.port || parseInt(process.env.PORT || "3000", 10);
2576
3442
  const host = options.host || "0.0.0.0";
2577
- const app = createApp(agent);
3443
+ const app = createApp(agent, options);
2578
3444
  await agent.start();
2579
3445
  app.listen(port, host, () => {
2580
- logger7.info(`Agent "${agent.name}" running at http://${host}:${port}`);
3446
+ logger10.info(`Agent "${agent.name}" running at http://${host}:${port}`);
3447
+ if (options.enableA2A !== false) {
3448
+ const protocol = host === "localhost" || host === "127.0.0.1" ? "http" : "https";
3449
+ const baseUrl = `${protocol}://${host}:${port}`;
3450
+ logger10.info("A2A Protocol Endpoints:");
3451
+ logger10.info(` Agent Card: ${baseUrl}/.well-known/agent-card.json`);
3452
+ logger10.info(` JSON-RPC: ${baseUrl}/a2a/jsonrpc`);
3453
+ logger10.info(` HTTP+JSON: ${baseUrl}/a2a/rest`);
3454
+ }
2581
3455
  });
2582
3456
  const shutdown = async () => {
2583
- logger7.info("Received shutdown signal");
3457
+ logger10.info("Received shutdown signal");
2584
3458
  await agent.stop();
2585
3459
  process.exit(0);
2586
3460
  };
@@ -2588,9 +3462,12 @@ async function startServer(agent, options = {}) {
2588
3462
  process.on("SIGTERM", shutdown);
2589
3463
  }
2590
3464
  export {
3465
+ A2AClient,
3466
+ A2AIntegration,
2591
3467
  ActionHandler,
2592
3468
  ActionRegistry,
2593
3469
  Agent,
3470
+ AgentCardBuilder,
2594
3471
  AnthropicProvider,
2595
3472
  ConfigLoader,
2596
3473
  LLMProvider,
@@ -2598,6 +3475,7 @@ export {
2598
3475
  MarkdownParser,
2599
3476
  Memory,
2600
3477
  MoltbookAdapter,
3478
+ MoltiumExecutor,
2601
3479
  OpenAIProvider,
2602
3480
  Scheduler,
2603
3481
  ShortTermMemory,
@@ -2607,12 +3485,19 @@ export {
2607
3485
  buildSkillPrompt,
2608
3486
  buildSystemPrompt,
2609
3487
  builtInActions,
3488
+ createA2AClient,
3489
+ createA2AIntegration,
2610
3490
  createApp,
3491
+ createJoinWorldAction,
3492
+ createLeaveWorldAction,
2611
3493
  createLogger,
2612
3494
  createMarkdownAction,
3495
+ createQueryWorldAction,
2613
3496
  createRoutes,
3497
+ createSendWorldMessageAction,
2614
3498
  moltbookActions,
2615
3499
  startServer,
2616
- validateConfig
3500
+ validateConfig,
3501
+ worldActions
2617
3502
  };
2618
3503
  //# sourceMappingURL=index.mjs.map