@moltium/core 0.1.19 → 0.1.20

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
@@ -1318,6 +1318,174 @@ var TwitterAdapter = class extends SocialAdapter {
1318
1318
  }
1319
1319
  };
1320
1320
 
1321
+ // src/a2a/client.ts
1322
+ import { A2AClient as SDKClient } from "@a2a-js/sdk/client";
1323
+ import { v4 as uuidv4 } from "uuid";
1324
+ var A2AClient = class {
1325
+ sdkClient;
1326
+ config;
1327
+ constructor(config) {
1328
+ this.config = {
1329
+ agentUrl: config.agentUrl,
1330
+ agentCardPath: config.agentCardPath || ".well-known/agent-card.json",
1331
+ timeout: config.timeout || 3e4
1332
+ };
1333
+ const agentUrl = this.config.agentUrl;
1334
+ const agentCardPath = this.config.agentCardPath;
1335
+ this.sdkClient = new SDKClient(agentUrl, agentCardPath);
1336
+ }
1337
+ /**
1338
+ * Send a text message to the agent and get a response
1339
+ *
1340
+ * @param options Message options including text content
1341
+ * @returns Promise resolving to the agent's response
1342
+ *
1343
+ * @example
1344
+ * ```typescript
1345
+ * const response = await client.sendMessage({
1346
+ * text: 'What are your thoughts on AI?',
1347
+ * contextId: 'conversation-123'
1348
+ * });
1349
+ *
1350
+ * if (response.success) {
1351
+ * console.log('Agent replied:', response.reply);
1352
+ * }
1353
+ * ```
1354
+ */
1355
+ async sendMessage(options) {
1356
+ try {
1357
+ const response = await this.sdkClient.sendMessage({
1358
+ message: {
1359
+ kind: "message",
1360
+ messageId: uuidv4(),
1361
+ role: "user",
1362
+ contextId: options.contextId,
1363
+ metadata: options.metadata,
1364
+ parts: [
1365
+ {
1366
+ kind: "text",
1367
+ text: options.text
1368
+ }
1369
+ ]
1370
+ }
1371
+ });
1372
+ const reply = this.extractReply(response);
1373
+ return {
1374
+ success: true,
1375
+ reply,
1376
+ agentUrl: this.config.agentUrl,
1377
+ raw: response
1378
+ };
1379
+ } catch (error) {
1380
+ return {
1381
+ success: false,
1382
+ error: error.message || "Unknown error occurred",
1383
+ agentUrl: this.config.agentUrl
1384
+ };
1385
+ }
1386
+ }
1387
+ /**
1388
+ * Extract text reply from A2A protocol response
1389
+ * Handles both Message and Task response types
1390
+ */
1391
+ extractReply(response) {
1392
+ if (!("result" in response) || !response.result) {
1393
+ return JSON.stringify(response);
1394
+ }
1395
+ const result = response.result;
1396
+ if ("kind" in result && result.kind === "message" && "parts" in result) {
1397
+ const textParts = result.parts.filter((part) => part.kind === "text").map((part) => part.text);
1398
+ return textParts.join("\n");
1399
+ }
1400
+ return typeof result === "string" ? result : JSON.stringify(result);
1401
+ }
1402
+ /**
1403
+ * Get the agent card information
1404
+ *
1405
+ * @returns Promise resolving to the agent card
1406
+ */
1407
+ async getAgentCard() {
1408
+ return this.sdkClient.getAgentCard();
1409
+ }
1410
+ /**
1411
+ * Get the base URL of the agent
1412
+ */
1413
+ getAgentUrl() {
1414
+ return this.config.agentUrl;
1415
+ }
1416
+ };
1417
+
1418
+ // src/a2a/actions.ts
1419
+ function createA2ACommunicationAction(config = {}) {
1420
+ const {
1421
+ defaultAgentUrl,
1422
+ actionName = "talk_to_agent",
1423
+ description,
1424
+ verbose = false
1425
+ } = config;
1426
+ 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})` : ""}`;
1427
+ return {
1428
+ name: actionName,
1429
+ description: defaultDescription,
1430
+ async execute(context) {
1431
+ const { parameters } = context;
1432
+ const message = parameters.message;
1433
+ const agentUrl = parameters.agentUrl || defaultAgentUrl;
1434
+ if (!message) {
1435
+ return {
1436
+ success: false,
1437
+ error: 'Parameter "message" is required'
1438
+ };
1439
+ }
1440
+ if (!agentUrl) {
1441
+ return {
1442
+ success: false,
1443
+ error: 'Parameter "agentUrl" is required or defaultAgentUrl must be configured'
1444
+ };
1445
+ }
1446
+ if (verbose) {
1447
+ console.log(`[A2A] Sending message to ${agentUrl}:`, message);
1448
+ }
1449
+ try {
1450
+ const client = new A2AClient({ agentUrl });
1451
+ const response = await client.sendMessage({ text: message });
1452
+ if (verbose) {
1453
+ console.log(`[A2A] Response from ${agentUrl}:`, response.reply);
1454
+ }
1455
+ if (!response.success) {
1456
+ return {
1457
+ success: false,
1458
+ error: response.error || "Failed to communicate with agent"
1459
+ };
1460
+ }
1461
+ return {
1462
+ success: true,
1463
+ data: {
1464
+ reply: response.reply,
1465
+ agentUrl: response.agentUrl
1466
+ }
1467
+ };
1468
+ } catch (error) {
1469
+ if (verbose) {
1470
+ console.error(`[A2A] Error:`, error);
1471
+ }
1472
+ return {
1473
+ success: false,
1474
+ error: error.message || "Unknown error occurred"
1475
+ };
1476
+ }
1477
+ }
1478
+ };
1479
+ }
1480
+ function createMultipleA2AActions(configs) {
1481
+ return Object.entries(configs).map(
1482
+ ([name, config]) => createA2ACommunicationAction({
1483
+ ...config,
1484
+ actionName: name
1485
+ })
1486
+ );
1487
+ }
1488
+
1321
1489
  // src/agent/Agent.ts
1322
1490
  var logger4 = createLogger("Agent");
1323
1491
  function parsePostFrequency(freq) {
@@ -1571,6 +1739,37 @@ var Agent = class {
1571
1739
  }
1572
1740
  logger4.info(`Registered ${moltbookActions.length} Moltbook actions`);
1573
1741
  }
1742
+ const a2a = this.config.a2a;
1743
+ if (a2a && a2a.enabled !== false) {
1744
+ if (a2a.peers && Object.keys(a2a.peers).length > 0) {
1745
+ const peerActions = createMultipleA2AActions(
1746
+ Object.entries(a2a.peers).reduce((acc, [actionName, url]) => {
1747
+ acc[actionName] = {
1748
+ defaultAgentUrl: url,
1749
+ verbose: a2a.verbose,
1750
+ description: `Communicate with peer agent at ${url}`
1751
+ };
1752
+ return acc;
1753
+ }, {})
1754
+ );
1755
+ for (const action of peerActions) {
1756
+ if (!this.actionRegistry.has(action.name)) {
1757
+ this.actionRegistry.register(action);
1758
+ }
1759
+ }
1760
+ logger4.info(`Registered ${peerActions.length} A2A peer actions`);
1761
+ } else {
1762
+ const genericAction = createA2ACommunicationAction({
1763
+ defaultAgentUrl: a2a.defaultPeerUrl,
1764
+ actionName: a2a.genericActionName || "talk_to_agent",
1765
+ verbose: a2a.verbose
1766
+ });
1767
+ if (!this.actionRegistry.has(genericAction.name)) {
1768
+ this.actionRegistry.register(genericAction);
1769
+ }
1770
+ logger4.info(`Registered generic A2A action: ${genericAction.name}`);
1771
+ }
1772
+ }
1574
1773
  if (this.config.customActions) {
1575
1774
  for (const action of this.config.customActions) {
1576
1775
  this.actionRegistry.register(action);
@@ -2560,27 +2759,516 @@ function authMiddleware(req, res, next) {
2560
2759
  next();
2561
2760
  }
2562
2761
 
2762
+ // src/a2a/AgentCardBuilder.ts
2763
+ var logger7 = createLogger("AgentCardBuilder");
2764
+ var AgentCardBuilder = class {
2765
+ /**
2766
+ * Creates an A2A AgentCard from Moltium configuration.
2767
+ * @param config The Moltium agent configuration
2768
+ * @param a2aConfig A2A-specific configuration (URLs, capabilities)
2769
+ * @returns A2A-compliant AgentCard
2770
+ */
2771
+ static build(config, a2aConfig) {
2772
+ const baseUrl = a2aConfig.baseUrl;
2773
+ const skills = this.buildSkills(config);
2774
+ const capabilities = {
2775
+ streaming: a2aConfig.streaming ?? true,
2776
+ pushNotifications: a2aConfig.pushNotifications ?? false,
2777
+ stateTransitionHistory: a2aConfig.stateTransitionHistory ?? true
2778
+ };
2779
+ const defaultInputModes = ["text"];
2780
+ const defaultOutputModes = ["text"];
2781
+ const agentCard = {
2782
+ name: config.name,
2783
+ description: config.personality.bio || `${config.name} - An autonomous AI agent`,
2784
+ protocolVersion: "0.3.0",
2785
+ version: "0.1.0",
2786
+ url: `${baseUrl}/a2a/jsonrpc`,
2787
+ skills,
2788
+ capabilities,
2789
+ defaultInputModes,
2790
+ defaultOutputModes,
2791
+ additionalInterfaces: [
2792
+ { url: `${baseUrl}/a2a/jsonrpc`, transport: "JSONRPC" },
2793
+ { url: `${baseUrl}/a2a/rest`, transport: "HTTP+JSON" }
2794
+ ]
2795
+ };
2796
+ logger7.debug("Built A2A AgentCard", {
2797
+ name: agentCard.name,
2798
+ skillCount: skills.length,
2799
+ baseUrl
2800
+ });
2801
+ return agentCard;
2802
+ }
2803
+ /**
2804
+ * Converts Moltium actions to A2A skills.
2805
+ */
2806
+ static buildSkills(config) {
2807
+ const skills = [];
2808
+ skills.push({
2809
+ id: "chat",
2810
+ name: "Chat",
2811
+ description: `Interact with ${config.name}. ${config.personality.bio || ""}`,
2812
+ tags: ["chat", "conversation"]
2813
+ });
2814
+ const hasPosting = config.actions.some(
2815
+ (a) => a.includes("post") || a.includes("update")
2816
+ );
2817
+ if (hasPosting) {
2818
+ skills.push({
2819
+ id: "social_posting",
2820
+ name: "Social Posting",
2821
+ description: "Post updates and content to social platforms",
2822
+ tags: ["social", "posting"]
2823
+ });
2824
+ }
2825
+ const hasEngagement = config.actions.some(
2826
+ (a) => a.includes("comment") || a.includes("reply") || a.includes("respond")
2827
+ );
2828
+ if (hasEngagement) {
2829
+ skills.push({
2830
+ id: "social_engagement",
2831
+ name: "Social Engagement",
2832
+ description: "Engage with others through comments and replies",
2833
+ tags: ["social", "engagement"]
2834
+ });
2835
+ }
2836
+ const hasSearch = config.actions.some(
2837
+ (a) => a.includes("search") || a.includes("check_feed") || a.includes("browse")
2838
+ );
2839
+ if (hasSearch) {
2840
+ skills.push({
2841
+ id: "content_discovery",
2842
+ name: "Content Discovery",
2843
+ description: "Search and discover relevant content",
2844
+ tags: ["search", "discovery"]
2845
+ });
2846
+ }
2847
+ const hasAnalysis = config.actions.some(
2848
+ (a) => a.includes("analyze") || a.includes("think") || a.includes("research")
2849
+ );
2850
+ if (hasAnalysis) {
2851
+ skills.push({
2852
+ id: "analysis",
2853
+ name: "Analysis & Research",
2854
+ description: "Analyze problems and conduct research",
2855
+ tags: ["analysis", "research", "thinking"]
2856
+ });
2857
+ }
2858
+ return skills;
2859
+ }
2860
+ /**
2861
+ * Updates an agent card with runtime information.
2862
+ */
2863
+ static updateWithRuntime(agentCard, actualPort, actualHost = "localhost") {
2864
+ const protocol = actualHost === "localhost" || actualHost === "127.0.0.1" ? "http" : "https";
2865
+ const baseUrl = `${protocol}://${actualHost}:${actualPort}`;
2866
+ return {
2867
+ ...agentCard,
2868
+ url: `${baseUrl}/a2a/jsonrpc`,
2869
+ additionalInterfaces: [
2870
+ { url: `${baseUrl}/a2a/jsonrpc`, transport: "JSONRPC" },
2871
+ { url: `${baseUrl}/a2a/rest`, transport: "HTTP+JSON" }
2872
+ ]
2873
+ };
2874
+ }
2875
+ };
2876
+
2877
+ // src/a2a/MoltiumExecutor.ts
2878
+ import { v4 as uuidv42 } from "uuid";
2879
+ var logger8 = createLogger("MoltiumExecutor");
2880
+ var MoltiumExecutor = class {
2881
+ agent;
2882
+ cancelledTasks = /* @__PURE__ */ new Set();
2883
+ constructor(agent) {
2884
+ this.agent = agent;
2885
+ }
2886
+ /**
2887
+ * Executes an A2A request using the Moltium agent.
2888
+ * Converts A2A messages to Moltium actions and publishes results back via the event bus.
2889
+ */
2890
+ async execute(requestContext, eventBus) {
2891
+ const { taskId, contextId, userMessage, task } = requestContext;
2892
+ try {
2893
+ logger8.info(`[A2A] Executing request for task ${taskId}`);
2894
+ if (!task) {
2895
+ const initialTask = {
2896
+ kind: "task",
2897
+ id: taskId,
2898
+ contextId,
2899
+ status: {
2900
+ state: "submitted",
2901
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2902
+ },
2903
+ history: [userMessage]
2904
+ };
2905
+ eventBus.publish(initialTask);
2906
+ }
2907
+ if (this.cancelledTasks.has(taskId)) {
2908
+ this.publishCancellation(taskId, contextId, eventBus);
2909
+ return;
2910
+ }
2911
+ this.publishStatusUpdate(taskId, contextId, "working", eventBus, false);
2912
+ const userContent = this.extractMessageContent(userMessage);
2913
+ const isActionRequest = this.isActionRequest(userContent);
2914
+ let result;
2915
+ if (isActionRequest) {
2916
+ result = await this.executeAction(userContent, taskId);
2917
+ } else {
2918
+ result = await this.executeChat(userContent, taskId);
2919
+ }
2920
+ if (this.cancelledTasks.has(taskId)) {
2921
+ this.publishCancellation(taskId, contextId, eventBus);
2922
+ return;
2923
+ }
2924
+ if (result.success) {
2925
+ await this.publishResult(taskId, contextId, result, eventBus);
2926
+ } else {
2927
+ await this.publishError(taskId, contextId, result.error || "Unknown error", eventBus);
2928
+ }
2929
+ this.publishStatusUpdate(taskId, contextId, "completed", eventBus, true);
2930
+ eventBus.finished();
2931
+ logger8.info(`[A2A] Task ${taskId} completed successfully`);
2932
+ } catch (error) {
2933
+ logger8.error(`[A2A] Task ${taskId} failed`, {
2934
+ error: error instanceof Error ? error.message : String(error)
2935
+ });
2936
+ const errorMessage = error instanceof Error ? error.message : String(error);
2937
+ await this.publishError(taskId, contextId, errorMessage, eventBus);
2938
+ this.publishStatusUpdate(taskId, contextId, "failed", eventBus, true);
2939
+ eventBus.finished();
2940
+ } finally {
2941
+ this.cancelledTasks.delete(taskId);
2942
+ }
2943
+ }
2944
+ /**
2945
+ * Handles task cancellation requests.
2946
+ */
2947
+ async cancelTask(taskId, eventBus) {
2948
+ logger8.info(`[A2A] Cancellation requested for task ${taskId}`);
2949
+ this.cancelledTasks.add(taskId);
2950
+ }
2951
+ /**
2952
+ * Extracts text content from an A2A message.
2953
+ */
2954
+ extractMessageContent(message) {
2955
+ const textParts = message.parts.filter((part) => part.kind === "text");
2956
+ return textParts.map((part) => part.text).join("\n");
2957
+ }
2958
+ /**
2959
+ * Determines if the user message is requesting a specific action.
2960
+ */
2961
+ isActionRequest(content) {
2962
+ const actionKeywords = [
2963
+ "post",
2964
+ "search",
2965
+ "check feed",
2966
+ "browse",
2967
+ "comment",
2968
+ "upvote",
2969
+ "follow",
2970
+ "send dm"
2971
+ ];
2972
+ const lowerContent = content.toLowerCase();
2973
+ return actionKeywords.some((keyword) => lowerContent.includes(keyword));
2974
+ }
2975
+ /**
2976
+ * Executes a chat interaction using the agent's LLM.
2977
+ */
2978
+ async executeChat(userContent, taskId) {
2979
+ try {
2980
+ const llm = this.agent.getLLM();
2981
+ const systemPrompt = this.agent.getSystemPrompt();
2982
+ const response = await llm.generateText(userContent, {
2983
+ systemPrompt,
2984
+ temperature: this.agent.config.llm.temperature
2985
+ });
2986
+ return {
2987
+ success: true,
2988
+ data: { response, type: "chat" }
2989
+ };
2990
+ } catch (error) {
2991
+ return {
2992
+ success: false,
2993
+ error: `Chat execution failed: ${error instanceof Error ? error.message : String(error)}`
2994
+ };
2995
+ }
2996
+ }
2997
+ /**
2998
+ * Executes an action based on the user's request.
2999
+ */
3000
+ async executeAction(userContent, taskId) {
3001
+ try {
3002
+ const decision = await this.agent.think();
3003
+ const result = await this.agent.act(decision.action, decision.parameters);
3004
+ return {
3005
+ success: result.success,
3006
+ data: {
3007
+ action: decision.action,
3008
+ reasoning: decision.reasoning,
3009
+ result: result.data,
3010
+ type: "action"
3011
+ },
3012
+ error: result.error
3013
+ };
3014
+ } catch (error) {
3015
+ return {
3016
+ success: false,
3017
+ error: `Action execution failed: ${error instanceof Error ? error.message : String(error)}`
3018
+ };
3019
+ }
3020
+ }
3021
+ /**
3022
+ * Publishes a successful result as an A2A artifact.
3023
+ */
3024
+ async publishResult(taskId, contextId, result, eventBus) {
3025
+ const data = result.data;
3026
+ if (data?.type === "chat") {
3027
+ const artifactUpdate = {
3028
+ kind: "artifact-update",
3029
+ taskId,
3030
+ contextId,
3031
+ artifact: {
3032
+ artifactId: `response-${uuidv42()}`,
3033
+ name: "response.txt",
3034
+ parts: [{ kind: "text", text: data.response }]
3035
+ }
3036
+ };
3037
+ eventBus.publish(artifactUpdate);
3038
+ } else if (data?.type === "action") {
3039
+ const resultText = JSON.stringify(
3040
+ {
3041
+ action: data.action,
3042
+ reasoning: data.reasoning,
3043
+ result: data.result
3044
+ },
3045
+ null,
3046
+ 2
3047
+ );
3048
+ const artifactUpdate = {
3049
+ kind: "artifact-update",
3050
+ taskId,
3051
+ contextId,
3052
+ artifact: {
3053
+ artifactId: `action-result-${uuidv42()}`,
3054
+ name: "action_result.json",
3055
+ parts: [{ kind: "text", text: resultText }]
3056
+ }
3057
+ };
3058
+ eventBus.publish(artifactUpdate);
3059
+ } else {
3060
+ const resultText = typeof result.data === "string" ? result.data : JSON.stringify(result.data, null, 2);
3061
+ const artifactUpdate = {
3062
+ kind: "artifact-update",
3063
+ taskId,
3064
+ contextId,
3065
+ artifact: {
3066
+ artifactId: `result-${uuidv42()}`,
3067
+ name: "result.txt",
3068
+ parts: [{ kind: "text", text: resultText }]
3069
+ }
3070
+ };
3071
+ eventBus.publish(artifactUpdate);
3072
+ }
3073
+ }
3074
+ /**
3075
+ * Publishes an error as an A2A artifact.
3076
+ */
3077
+ async publishError(taskId, contextId, error, eventBus) {
3078
+ const artifactUpdate = {
3079
+ kind: "artifact-update",
3080
+ taskId,
3081
+ contextId,
3082
+ artifact: {
3083
+ artifactId: `error-${uuidv42()}`,
3084
+ name: "error.txt",
3085
+ parts: [{ kind: "text", text: `Error: ${error}` }]
3086
+ }
3087
+ };
3088
+ eventBus.publish(artifactUpdate);
3089
+ }
3090
+ /**
3091
+ * Publishes a status update event.
3092
+ */
3093
+ publishStatusUpdate(taskId, contextId, state, eventBus, final) {
3094
+ const statusUpdate = {
3095
+ kind: "status-update",
3096
+ taskId,
3097
+ contextId,
3098
+ status: {
3099
+ state,
3100
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
3101
+ },
3102
+ final
3103
+ };
3104
+ eventBus.publish(statusUpdate);
3105
+ }
3106
+ /**
3107
+ * Publishes a cancellation status.
3108
+ */
3109
+ publishCancellation(taskId, contextId, eventBus) {
3110
+ logger8.info(`[A2A] Publishing cancellation for task ${taskId}`);
3111
+ this.publishStatusUpdate(taskId, contextId, "canceled", eventBus, true);
3112
+ eventBus.finished();
3113
+ this.cancelledTasks.delete(taskId);
3114
+ }
3115
+ };
3116
+
3117
+ // src/a2a/integration.ts
3118
+ import { DefaultRequestHandler, InMemoryTaskStore, JsonRpcTransportHandler } from "@a2a-js/sdk/server";
3119
+ var logger9 = createLogger("A2AIntegration");
3120
+ var A2AIntegration = class {
3121
+ agent;
3122
+ agentCard;
3123
+ requestHandler;
3124
+ moltiumExecutor;
3125
+ constructor(agent, options) {
3126
+ this.agent = agent;
3127
+ this.agentCard = AgentCardBuilder.build(agent.config, options.a2aConfig);
3128
+ this.moltiumExecutor = new MoltiumExecutor(agent);
3129
+ this.requestHandler = new DefaultRequestHandler(
3130
+ this.agentCard,
3131
+ new InMemoryTaskStore(),
3132
+ this.moltiumExecutor
3133
+ );
3134
+ logger9.info("A2A integration initialized", {
3135
+ agentName: agent.name,
3136
+ baseUrl: options.a2aConfig.baseUrl
3137
+ });
3138
+ }
3139
+ /**
3140
+ * Creates Express middleware handlers for A2A endpoints.
3141
+ * Returns an object with individual handlers that can be mounted on specific routes.
3142
+ */
3143
+ getHandlers() {
3144
+ return {
3145
+ // Agent Card endpoint - serves the static agent card JSON
3146
+ agentCard: ((req, res) => {
3147
+ res.json(this.agentCard);
3148
+ }),
3149
+ // JSON-RPC endpoint - handles A2A protocol requests
3150
+ jsonRpc: (async (req, res) => {
3151
+ try {
3152
+ const jsonRpcHandler = new JsonRpcTransportHandler(this.requestHandler);
3153
+ const response = await jsonRpcHandler.handle(req.body);
3154
+ res.json(response);
3155
+ } catch (error) {
3156
+ logger9.error("JSON-RPC error:", error);
3157
+ res.status(500).json({
3158
+ jsonrpc: "2.0",
3159
+ error: {
3160
+ code: -32603,
3161
+ message: "Internal error",
3162
+ data: error.message
3163
+ },
3164
+ id: req.body?.id || null
3165
+ });
3166
+ }
3167
+ }),
3168
+ // REST endpoint - simplified HTTP+JSON interface
3169
+ rest: ((req, res) => {
3170
+ res.status(501).json({
3171
+ error: "REST transport not implemented in SDK v0.3.0",
3172
+ message: "Please use the JSON-RPC endpoint at /a2a/jsonrpc"
3173
+ });
3174
+ })
3175
+ };
3176
+ }
3177
+ /**
3178
+ * Updates the agent card with actual runtime information (host/port).
3179
+ */
3180
+ updateAgentCard(actualPort, actualHost = "localhost") {
3181
+ this.agentCard = AgentCardBuilder.updateWithRuntime(this.agentCard, actualPort, actualHost);
3182
+ this.requestHandler = new DefaultRequestHandler(
3183
+ this.agentCard,
3184
+ new InMemoryTaskStore(),
3185
+ this.moltiumExecutor
3186
+ );
3187
+ logger9.info("A2A agent card updated with runtime info", {
3188
+ host: actualHost,
3189
+ port: actualPort,
3190
+ url: this.agentCard.url
3191
+ });
3192
+ }
3193
+ /**
3194
+ * Gets the current agent card.
3195
+ */
3196
+ getAgentCard() {
3197
+ return this.agentCard;
3198
+ }
3199
+ /**
3200
+ * Logs A2A endpoint information.
3201
+ */
3202
+ logEndpoints(host, port) {
3203
+ const protocol = host === "localhost" || host === "127.0.0.1" ? "http" : "https";
3204
+ const baseUrl = `${protocol}://${host}:${port}`;
3205
+ logger9.info("A2A endpoints available:");
3206
+ logger9.info(` Agent Card: ${baseUrl}/.well-known/agent-card.json`);
3207
+ logger9.info(` JSON-RPC: ${baseUrl}/a2a/jsonrpc`);
3208
+ logger9.info(` HTTP+JSON: ${baseUrl}/a2a/rest`);
3209
+ }
3210
+ };
3211
+ function createA2AIntegration(agent, options = {}) {
3212
+ const a2aConfig = {
3213
+ enabled: true,
3214
+ baseUrl: options.a2aConfig?.baseUrl || "http://localhost:3000",
3215
+ pushNotifications: options.a2aConfig?.pushNotifications ?? false,
3216
+ streaming: options.a2aConfig?.streaming ?? true,
3217
+ stateTransitionHistory: options.a2aConfig?.stateTransitionHistory ?? true
3218
+ };
3219
+ return new A2AIntegration(agent, { a2aConfig, ...options });
3220
+ }
3221
+
2563
3222
  // src/server/app.ts
2564
- var logger7 = createLogger("Server");
2565
- function createApp(agent) {
3223
+ var logger10 = createLogger("Server");
3224
+ var AGENT_CARD_PATH = ".well-known/agent-card.json";
3225
+ function createApp(agent, options = {}) {
2566
3226
  const app = express();
2567
3227
  app.use(express.json());
2568
3228
  app.use(requestLogger);
2569
3229
  app.use(authMiddleware);
2570
3230
  app.use(createRoutes(agent));
3231
+ if (options.enableA2A !== false) {
3232
+ const port = options.port || parseInt(process.env.PORT || "3000", 10);
3233
+ const host = options.host || "0.0.0.0";
3234
+ const protocol = host === "localhost" || host === "127.0.0.1" || host === "0.0.0.0" ? "http" : "https";
3235
+ const baseUrl = options.a2aConfig?.baseUrl || `${protocol}://${host}:${port}`;
3236
+ const a2aIntegration = createA2AIntegration(agent, {
3237
+ a2aConfig: {
3238
+ enabled: true,
3239
+ baseUrl,
3240
+ pushNotifications: options.a2aConfig?.pushNotifications ?? false,
3241
+ streaming: options.a2aConfig?.streaming ?? true,
3242
+ stateTransitionHistory: options.a2aConfig?.stateTransitionHistory ?? true
3243
+ }
3244
+ });
3245
+ const handlers = a2aIntegration.getHandlers();
3246
+ app.use(`/${AGENT_CARD_PATH}`, handlers.agentCard);
3247
+ app.use("/a2a/jsonrpc", handlers.jsonRpc);
3248
+ app.use("/a2a/rest", handlers.rest);
3249
+ logger10.info("A2A protocol endpoints enabled");
3250
+ }
2571
3251
  app.use(errorHandler);
2572
3252
  return app;
2573
3253
  }
2574
3254
  async function startServer(agent, options = {}) {
2575
3255
  const port = options.port || parseInt(process.env.PORT || "3000", 10);
2576
3256
  const host = options.host || "0.0.0.0";
2577
- const app = createApp(agent);
3257
+ const app = createApp(agent, options);
2578
3258
  await agent.start();
2579
3259
  app.listen(port, host, () => {
2580
- logger7.info(`Agent "${agent.name}" running at http://${host}:${port}`);
3260
+ logger10.info(`Agent "${agent.name}" running at http://${host}:${port}`);
3261
+ if (options.enableA2A !== false) {
3262
+ const protocol = host === "localhost" || host === "127.0.0.1" ? "http" : "https";
3263
+ const baseUrl = `${protocol}://${host}:${port}`;
3264
+ logger10.info("A2A Protocol Endpoints:");
3265
+ logger10.info(` Agent Card: ${baseUrl}/.well-known/agent-card.json`);
3266
+ logger10.info(` JSON-RPC: ${baseUrl}/a2a/jsonrpc`);
3267
+ logger10.info(` HTTP+JSON: ${baseUrl}/a2a/rest`);
3268
+ }
2581
3269
  });
2582
3270
  const shutdown = async () => {
2583
- logger7.info("Received shutdown signal");
3271
+ logger10.info("Received shutdown signal");
2584
3272
  await agent.stop();
2585
3273
  process.exit(0);
2586
3274
  };
@@ -2588,9 +3276,11 @@ async function startServer(agent, options = {}) {
2588
3276
  process.on("SIGTERM", shutdown);
2589
3277
  }
2590
3278
  export {
3279
+ A2AIntegration,
2591
3280
  ActionHandler,
2592
3281
  ActionRegistry,
2593
3282
  Agent,
3283
+ AgentCardBuilder,
2594
3284
  AnthropicProvider,
2595
3285
  ConfigLoader,
2596
3286
  LLMProvider,
@@ -2598,6 +3288,7 @@ export {
2598
3288
  MarkdownParser,
2599
3289
  Memory,
2600
3290
  MoltbookAdapter,
3291
+ MoltiumExecutor,
2601
3292
  OpenAIProvider,
2602
3293
  Scheduler,
2603
3294
  ShortTermMemory,
@@ -2607,6 +3298,7 @@ export {
2607
3298
  buildSkillPrompt,
2608
3299
  buildSystemPrompt,
2609
3300
  builtInActions,
3301
+ createA2AIntegration,
2610
3302
  createApp,
2611
3303
  createLogger,
2612
3304
  createMarkdownAction,