@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.js CHANGED
@@ -30,9 +30,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ A2AIntegration: () => A2AIntegration,
33
34
  ActionHandler: () => ActionHandler,
34
35
  ActionRegistry: () => ActionRegistry,
35
36
  Agent: () => Agent,
37
+ AgentCardBuilder: () => AgentCardBuilder,
36
38
  AnthropicProvider: () => AnthropicProvider,
37
39
  ConfigLoader: () => ConfigLoader,
38
40
  LLMProvider: () => LLMProvider,
@@ -40,6 +42,7 @@ __export(index_exports, {
40
42
  MarkdownParser: () => MarkdownParser,
41
43
  Memory: () => Memory,
42
44
  MoltbookAdapter: () => MoltbookAdapter,
45
+ MoltiumExecutor: () => MoltiumExecutor,
43
46
  OpenAIProvider: () => OpenAIProvider,
44
47
  Scheduler: () => Scheduler,
45
48
  ShortTermMemory: () => ShortTermMemory,
@@ -49,6 +52,7 @@ __export(index_exports, {
49
52
  buildSkillPrompt: () => buildSkillPrompt,
50
53
  buildSystemPrompt: () => buildSystemPrompt,
51
54
  builtInActions: () => builtInActions,
55
+ createA2AIntegration: () => createA2AIntegration,
52
56
  createApp: () => createApp,
53
57
  createLogger: () => createLogger,
54
58
  createMarkdownAction: () => createMarkdownAction,
@@ -1379,6 +1383,174 @@ var TwitterAdapter = class extends SocialAdapter {
1379
1383
  }
1380
1384
  };
1381
1385
 
1386
+ // src/a2a/client.ts
1387
+ var import_client = require("@a2a-js/sdk/client");
1388
+ var import_uuid = require("uuid");
1389
+ var A2AClient = class {
1390
+ sdkClient;
1391
+ config;
1392
+ constructor(config) {
1393
+ this.config = {
1394
+ agentUrl: config.agentUrl,
1395
+ agentCardPath: config.agentCardPath || ".well-known/agent-card.json",
1396
+ timeout: config.timeout || 3e4
1397
+ };
1398
+ const agentUrl = this.config.agentUrl;
1399
+ const agentCardPath = this.config.agentCardPath;
1400
+ this.sdkClient = new import_client.A2AClient(agentUrl, agentCardPath);
1401
+ }
1402
+ /**
1403
+ * Send a text message to the agent and get a response
1404
+ *
1405
+ * @param options Message options including text content
1406
+ * @returns Promise resolving to the agent's response
1407
+ *
1408
+ * @example
1409
+ * ```typescript
1410
+ * const response = await client.sendMessage({
1411
+ * text: 'What are your thoughts on AI?',
1412
+ * contextId: 'conversation-123'
1413
+ * });
1414
+ *
1415
+ * if (response.success) {
1416
+ * console.log('Agent replied:', response.reply);
1417
+ * }
1418
+ * ```
1419
+ */
1420
+ async sendMessage(options) {
1421
+ try {
1422
+ const response = await this.sdkClient.sendMessage({
1423
+ message: {
1424
+ kind: "message",
1425
+ messageId: (0, import_uuid.v4)(),
1426
+ role: "user",
1427
+ contextId: options.contextId,
1428
+ metadata: options.metadata,
1429
+ parts: [
1430
+ {
1431
+ kind: "text",
1432
+ text: options.text
1433
+ }
1434
+ ]
1435
+ }
1436
+ });
1437
+ const reply = this.extractReply(response);
1438
+ return {
1439
+ success: true,
1440
+ reply,
1441
+ agentUrl: this.config.agentUrl,
1442
+ raw: response
1443
+ };
1444
+ } catch (error) {
1445
+ return {
1446
+ success: false,
1447
+ error: error.message || "Unknown error occurred",
1448
+ agentUrl: this.config.agentUrl
1449
+ };
1450
+ }
1451
+ }
1452
+ /**
1453
+ * Extract text reply from A2A protocol response
1454
+ * Handles both Message and Task response types
1455
+ */
1456
+ extractReply(response) {
1457
+ if (!("result" in response) || !response.result) {
1458
+ return JSON.stringify(response);
1459
+ }
1460
+ const result = response.result;
1461
+ if ("kind" in result && result.kind === "message" && "parts" in result) {
1462
+ const textParts = result.parts.filter((part) => part.kind === "text").map((part) => part.text);
1463
+ return textParts.join("\n");
1464
+ }
1465
+ return typeof result === "string" ? result : JSON.stringify(result);
1466
+ }
1467
+ /**
1468
+ * Get the agent card information
1469
+ *
1470
+ * @returns Promise resolving to the agent card
1471
+ */
1472
+ async getAgentCard() {
1473
+ return this.sdkClient.getAgentCard();
1474
+ }
1475
+ /**
1476
+ * Get the base URL of the agent
1477
+ */
1478
+ getAgentUrl() {
1479
+ return this.config.agentUrl;
1480
+ }
1481
+ };
1482
+
1483
+ // src/a2a/actions.ts
1484
+ function createA2ACommunicationAction(config = {}) {
1485
+ const {
1486
+ defaultAgentUrl,
1487
+ actionName = "talk_to_agent",
1488
+ description,
1489
+ verbose = false
1490
+ } = config;
1491
+ 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})` : ""}`;
1492
+ return {
1493
+ name: actionName,
1494
+ description: defaultDescription,
1495
+ async execute(context) {
1496
+ const { parameters } = context;
1497
+ const message = parameters.message;
1498
+ const agentUrl = parameters.agentUrl || defaultAgentUrl;
1499
+ if (!message) {
1500
+ return {
1501
+ success: false,
1502
+ error: 'Parameter "message" is required'
1503
+ };
1504
+ }
1505
+ if (!agentUrl) {
1506
+ return {
1507
+ success: false,
1508
+ error: 'Parameter "agentUrl" is required or defaultAgentUrl must be configured'
1509
+ };
1510
+ }
1511
+ if (verbose) {
1512
+ console.log(`[A2A] Sending message to ${agentUrl}:`, message);
1513
+ }
1514
+ try {
1515
+ const client = new A2AClient({ agentUrl });
1516
+ const response = await client.sendMessage({ text: message });
1517
+ if (verbose) {
1518
+ console.log(`[A2A] Response from ${agentUrl}:`, response.reply);
1519
+ }
1520
+ if (!response.success) {
1521
+ return {
1522
+ success: false,
1523
+ error: response.error || "Failed to communicate with agent"
1524
+ };
1525
+ }
1526
+ return {
1527
+ success: true,
1528
+ data: {
1529
+ reply: response.reply,
1530
+ agentUrl: response.agentUrl
1531
+ }
1532
+ };
1533
+ } catch (error) {
1534
+ if (verbose) {
1535
+ console.error(`[A2A] Error:`, error);
1536
+ }
1537
+ return {
1538
+ success: false,
1539
+ error: error.message || "Unknown error occurred"
1540
+ };
1541
+ }
1542
+ }
1543
+ };
1544
+ }
1545
+ function createMultipleA2AActions(configs) {
1546
+ return Object.entries(configs).map(
1547
+ ([name, config]) => createA2ACommunicationAction({
1548
+ ...config,
1549
+ actionName: name
1550
+ })
1551
+ );
1552
+ }
1553
+
1382
1554
  // src/agent/Agent.ts
1383
1555
  var logger4 = createLogger("Agent");
1384
1556
  function parsePostFrequency(freq) {
@@ -1632,6 +1804,37 @@ var Agent = class {
1632
1804
  }
1633
1805
  logger4.info(`Registered ${moltbookActions.length} Moltbook actions`);
1634
1806
  }
1807
+ const a2a = this.config.a2a;
1808
+ if (a2a && a2a.enabled !== false) {
1809
+ if (a2a.peers && Object.keys(a2a.peers).length > 0) {
1810
+ const peerActions = createMultipleA2AActions(
1811
+ Object.entries(a2a.peers).reduce((acc, [actionName, url]) => {
1812
+ acc[actionName] = {
1813
+ defaultAgentUrl: url,
1814
+ verbose: a2a.verbose,
1815
+ description: `Communicate with peer agent at ${url}`
1816
+ };
1817
+ return acc;
1818
+ }, {})
1819
+ );
1820
+ for (const action of peerActions) {
1821
+ if (!this.actionRegistry.has(action.name)) {
1822
+ this.actionRegistry.register(action);
1823
+ }
1824
+ }
1825
+ logger4.info(`Registered ${peerActions.length} A2A peer actions`);
1826
+ } else {
1827
+ const genericAction = createA2ACommunicationAction({
1828
+ defaultAgentUrl: a2a.defaultPeerUrl,
1829
+ actionName: a2a.genericActionName || "talk_to_agent",
1830
+ verbose: a2a.verbose
1831
+ });
1832
+ if (!this.actionRegistry.has(genericAction.name)) {
1833
+ this.actionRegistry.register(genericAction);
1834
+ }
1835
+ logger4.info(`Registered generic A2A action: ${genericAction.name}`);
1836
+ }
1837
+ }
1635
1838
  if (this.config.customActions) {
1636
1839
  for (const action of this.config.customActions) {
1637
1840
  this.actionRegistry.register(action);
@@ -2621,27 +2824,516 @@ function authMiddleware(req, res, next) {
2621
2824
  next();
2622
2825
  }
2623
2826
 
2827
+ // src/a2a/AgentCardBuilder.ts
2828
+ var logger7 = createLogger("AgentCardBuilder");
2829
+ var AgentCardBuilder = class {
2830
+ /**
2831
+ * Creates an A2A AgentCard from Moltium configuration.
2832
+ * @param config The Moltium agent configuration
2833
+ * @param a2aConfig A2A-specific configuration (URLs, capabilities)
2834
+ * @returns A2A-compliant AgentCard
2835
+ */
2836
+ static build(config, a2aConfig) {
2837
+ const baseUrl = a2aConfig.baseUrl;
2838
+ const skills = this.buildSkills(config);
2839
+ const capabilities = {
2840
+ streaming: a2aConfig.streaming ?? true,
2841
+ pushNotifications: a2aConfig.pushNotifications ?? false,
2842
+ stateTransitionHistory: a2aConfig.stateTransitionHistory ?? true
2843
+ };
2844
+ const defaultInputModes = ["text"];
2845
+ const defaultOutputModes = ["text"];
2846
+ const agentCard = {
2847
+ name: config.name,
2848
+ description: config.personality.bio || `${config.name} - An autonomous AI agent`,
2849
+ protocolVersion: "0.3.0",
2850
+ version: "0.1.0",
2851
+ url: `${baseUrl}/a2a/jsonrpc`,
2852
+ skills,
2853
+ capabilities,
2854
+ defaultInputModes,
2855
+ defaultOutputModes,
2856
+ additionalInterfaces: [
2857
+ { url: `${baseUrl}/a2a/jsonrpc`, transport: "JSONRPC" },
2858
+ { url: `${baseUrl}/a2a/rest`, transport: "HTTP+JSON" }
2859
+ ]
2860
+ };
2861
+ logger7.debug("Built A2A AgentCard", {
2862
+ name: agentCard.name,
2863
+ skillCount: skills.length,
2864
+ baseUrl
2865
+ });
2866
+ return agentCard;
2867
+ }
2868
+ /**
2869
+ * Converts Moltium actions to A2A skills.
2870
+ */
2871
+ static buildSkills(config) {
2872
+ const skills = [];
2873
+ skills.push({
2874
+ id: "chat",
2875
+ name: "Chat",
2876
+ description: `Interact with ${config.name}. ${config.personality.bio || ""}`,
2877
+ tags: ["chat", "conversation"]
2878
+ });
2879
+ const hasPosting = config.actions.some(
2880
+ (a) => a.includes("post") || a.includes("update")
2881
+ );
2882
+ if (hasPosting) {
2883
+ skills.push({
2884
+ id: "social_posting",
2885
+ name: "Social Posting",
2886
+ description: "Post updates and content to social platforms",
2887
+ tags: ["social", "posting"]
2888
+ });
2889
+ }
2890
+ const hasEngagement = config.actions.some(
2891
+ (a) => a.includes("comment") || a.includes("reply") || a.includes("respond")
2892
+ );
2893
+ if (hasEngagement) {
2894
+ skills.push({
2895
+ id: "social_engagement",
2896
+ name: "Social Engagement",
2897
+ description: "Engage with others through comments and replies",
2898
+ tags: ["social", "engagement"]
2899
+ });
2900
+ }
2901
+ const hasSearch = config.actions.some(
2902
+ (a) => a.includes("search") || a.includes("check_feed") || a.includes("browse")
2903
+ );
2904
+ if (hasSearch) {
2905
+ skills.push({
2906
+ id: "content_discovery",
2907
+ name: "Content Discovery",
2908
+ description: "Search and discover relevant content",
2909
+ tags: ["search", "discovery"]
2910
+ });
2911
+ }
2912
+ const hasAnalysis = config.actions.some(
2913
+ (a) => a.includes("analyze") || a.includes("think") || a.includes("research")
2914
+ );
2915
+ if (hasAnalysis) {
2916
+ skills.push({
2917
+ id: "analysis",
2918
+ name: "Analysis & Research",
2919
+ description: "Analyze problems and conduct research",
2920
+ tags: ["analysis", "research", "thinking"]
2921
+ });
2922
+ }
2923
+ return skills;
2924
+ }
2925
+ /**
2926
+ * Updates an agent card with runtime information.
2927
+ */
2928
+ static updateWithRuntime(agentCard, actualPort, actualHost = "localhost") {
2929
+ const protocol = actualHost === "localhost" || actualHost === "127.0.0.1" ? "http" : "https";
2930
+ const baseUrl = `${protocol}://${actualHost}:${actualPort}`;
2931
+ return {
2932
+ ...agentCard,
2933
+ url: `${baseUrl}/a2a/jsonrpc`,
2934
+ additionalInterfaces: [
2935
+ { url: `${baseUrl}/a2a/jsonrpc`, transport: "JSONRPC" },
2936
+ { url: `${baseUrl}/a2a/rest`, transport: "HTTP+JSON" }
2937
+ ]
2938
+ };
2939
+ }
2940
+ };
2941
+
2942
+ // src/a2a/MoltiumExecutor.ts
2943
+ var import_uuid2 = require("uuid");
2944
+ var logger8 = createLogger("MoltiumExecutor");
2945
+ var MoltiumExecutor = class {
2946
+ agent;
2947
+ cancelledTasks = /* @__PURE__ */ new Set();
2948
+ constructor(agent) {
2949
+ this.agent = agent;
2950
+ }
2951
+ /**
2952
+ * Executes an A2A request using the Moltium agent.
2953
+ * Converts A2A messages to Moltium actions and publishes results back via the event bus.
2954
+ */
2955
+ async execute(requestContext, eventBus) {
2956
+ const { taskId, contextId, userMessage, task } = requestContext;
2957
+ try {
2958
+ logger8.info(`[A2A] Executing request for task ${taskId}`);
2959
+ if (!task) {
2960
+ const initialTask = {
2961
+ kind: "task",
2962
+ id: taskId,
2963
+ contextId,
2964
+ status: {
2965
+ state: "submitted",
2966
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2967
+ },
2968
+ history: [userMessage]
2969
+ };
2970
+ eventBus.publish(initialTask);
2971
+ }
2972
+ if (this.cancelledTasks.has(taskId)) {
2973
+ this.publishCancellation(taskId, contextId, eventBus);
2974
+ return;
2975
+ }
2976
+ this.publishStatusUpdate(taskId, contextId, "working", eventBus, false);
2977
+ const userContent = this.extractMessageContent(userMessage);
2978
+ const isActionRequest = this.isActionRequest(userContent);
2979
+ let result;
2980
+ if (isActionRequest) {
2981
+ result = await this.executeAction(userContent, taskId);
2982
+ } else {
2983
+ result = await this.executeChat(userContent, taskId);
2984
+ }
2985
+ if (this.cancelledTasks.has(taskId)) {
2986
+ this.publishCancellation(taskId, contextId, eventBus);
2987
+ return;
2988
+ }
2989
+ if (result.success) {
2990
+ await this.publishResult(taskId, contextId, result, eventBus);
2991
+ } else {
2992
+ await this.publishError(taskId, contextId, result.error || "Unknown error", eventBus);
2993
+ }
2994
+ this.publishStatusUpdate(taskId, contextId, "completed", eventBus, true);
2995
+ eventBus.finished();
2996
+ logger8.info(`[A2A] Task ${taskId} completed successfully`);
2997
+ } catch (error) {
2998
+ logger8.error(`[A2A] Task ${taskId} failed`, {
2999
+ error: error instanceof Error ? error.message : String(error)
3000
+ });
3001
+ const errorMessage = error instanceof Error ? error.message : String(error);
3002
+ await this.publishError(taskId, contextId, errorMessage, eventBus);
3003
+ this.publishStatusUpdate(taskId, contextId, "failed", eventBus, true);
3004
+ eventBus.finished();
3005
+ } finally {
3006
+ this.cancelledTasks.delete(taskId);
3007
+ }
3008
+ }
3009
+ /**
3010
+ * Handles task cancellation requests.
3011
+ */
3012
+ async cancelTask(taskId, eventBus) {
3013
+ logger8.info(`[A2A] Cancellation requested for task ${taskId}`);
3014
+ this.cancelledTasks.add(taskId);
3015
+ }
3016
+ /**
3017
+ * Extracts text content from an A2A message.
3018
+ */
3019
+ extractMessageContent(message) {
3020
+ const textParts = message.parts.filter((part) => part.kind === "text");
3021
+ return textParts.map((part) => part.text).join("\n");
3022
+ }
3023
+ /**
3024
+ * Determines if the user message is requesting a specific action.
3025
+ */
3026
+ isActionRequest(content) {
3027
+ const actionKeywords = [
3028
+ "post",
3029
+ "search",
3030
+ "check feed",
3031
+ "browse",
3032
+ "comment",
3033
+ "upvote",
3034
+ "follow",
3035
+ "send dm"
3036
+ ];
3037
+ const lowerContent = content.toLowerCase();
3038
+ return actionKeywords.some((keyword) => lowerContent.includes(keyword));
3039
+ }
3040
+ /**
3041
+ * Executes a chat interaction using the agent's LLM.
3042
+ */
3043
+ async executeChat(userContent, taskId) {
3044
+ try {
3045
+ const llm = this.agent.getLLM();
3046
+ const systemPrompt = this.agent.getSystemPrompt();
3047
+ const response = await llm.generateText(userContent, {
3048
+ systemPrompt,
3049
+ temperature: this.agent.config.llm.temperature
3050
+ });
3051
+ return {
3052
+ success: true,
3053
+ data: { response, type: "chat" }
3054
+ };
3055
+ } catch (error) {
3056
+ return {
3057
+ success: false,
3058
+ error: `Chat execution failed: ${error instanceof Error ? error.message : String(error)}`
3059
+ };
3060
+ }
3061
+ }
3062
+ /**
3063
+ * Executes an action based on the user's request.
3064
+ */
3065
+ async executeAction(userContent, taskId) {
3066
+ try {
3067
+ const decision = await this.agent.think();
3068
+ const result = await this.agent.act(decision.action, decision.parameters);
3069
+ return {
3070
+ success: result.success,
3071
+ data: {
3072
+ action: decision.action,
3073
+ reasoning: decision.reasoning,
3074
+ result: result.data,
3075
+ type: "action"
3076
+ },
3077
+ error: result.error
3078
+ };
3079
+ } catch (error) {
3080
+ return {
3081
+ success: false,
3082
+ error: `Action execution failed: ${error instanceof Error ? error.message : String(error)}`
3083
+ };
3084
+ }
3085
+ }
3086
+ /**
3087
+ * Publishes a successful result as an A2A artifact.
3088
+ */
3089
+ async publishResult(taskId, contextId, result, eventBus) {
3090
+ const data = result.data;
3091
+ if (data?.type === "chat") {
3092
+ const artifactUpdate = {
3093
+ kind: "artifact-update",
3094
+ taskId,
3095
+ contextId,
3096
+ artifact: {
3097
+ artifactId: `response-${(0, import_uuid2.v4)()}`,
3098
+ name: "response.txt",
3099
+ parts: [{ kind: "text", text: data.response }]
3100
+ }
3101
+ };
3102
+ eventBus.publish(artifactUpdate);
3103
+ } else if (data?.type === "action") {
3104
+ const resultText = JSON.stringify(
3105
+ {
3106
+ action: data.action,
3107
+ reasoning: data.reasoning,
3108
+ result: data.result
3109
+ },
3110
+ null,
3111
+ 2
3112
+ );
3113
+ const artifactUpdate = {
3114
+ kind: "artifact-update",
3115
+ taskId,
3116
+ contextId,
3117
+ artifact: {
3118
+ artifactId: `action-result-${(0, import_uuid2.v4)()}`,
3119
+ name: "action_result.json",
3120
+ parts: [{ kind: "text", text: resultText }]
3121
+ }
3122
+ };
3123
+ eventBus.publish(artifactUpdate);
3124
+ } else {
3125
+ const resultText = typeof result.data === "string" ? result.data : JSON.stringify(result.data, null, 2);
3126
+ const artifactUpdate = {
3127
+ kind: "artifact-update",
3128
+ taskId,
3129
+ contextId,
3130
+ artifact: {
3131
+ artifactId: `result-${(0, import_uuid2.v4)()}`,
3132
+ name: "result.txt",
3133
+ parts: [{ kind: "text", text: resultText }]
3134
+ }
3135
+ };
3136
+ eventBus.publish(artifactUpdate);
3137
+ }
3138
+ }
3139
+ /**
3140
+ * Publishes an error as an A2A artifact.
3141
+ */
3142
+ async publishError(taskId, contextId, error, eventBus) {
3143
+ const artifactUpdate = {
3144
+ kind: "artifact-update",
3145
+ taskId,
3146
+ contextId,
3147
+ artifact: {
3148
+ artifactId: `error-${(0, import_uuid2.v4)()}`,
3149
+ name: "error.txt",
3150
+ parts: [{ kind: "text", text: `Error: ${error}` }]
3151
+ }
3152
+ };
3153
+ eventBus.publish(artifactUpdate);
3154
+ }
3155
+ /**
3156
+ * Publishes a status update event.
3157
+ */
3158
+ publishStatusUpdate(taskId, contextId, state, eventBus, final) {
3159
+ const statusUpdate = {
3160
+ kind: "status-update",
3161
+ taskId,
3162
+ contextId,
3163
+ status: {
3164
+ state,
3165
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
3166
+ },
3167
+ final
3168
+ };
3169
+ eventBus.publish(statusUpdate);
3170
+ }
3171
+ /**
3172
+ * Publishes a cancellation status.
3173
+ */
3174
+ publishCancellation(taskId, contextId, eventBus) {
3175
+ logger8.info(`[A2A] Publishing cancellation for task ${taskId}`);
3176
+ this.publishStatusUpdate(taskId, contextId, "canceled", eventBus, true);
3177
+ eventBus.finished();
3178
+ this.cancelledTasks.delete(taskId);
3179
+ }
3180
+ };
3181
+
3182
+ // src/a2a/integration.ts
3183
+ var import_server = require("@a2a-js/sdk/server");
3184
+ var logger9 = createLogger("A2AIntegration");
3185
+ var A2AIntegration = class {
3186
+ agent;
3187
+ agentCard;
3188
+ requestHandler;
3189
+ moltiumExecutor;
3190
+ constructor(agent, options) {
3191
+ this.agent = agent;
3192
+ this.agentCard = AgentCardBuilder.build(agent.config, options.a2aConfig);
3193
+ this.moltiumExecutor = new MoltiumExecutor(agent);
3194
+ this.requestHandler = new import_server.DefaultRequestHandler(
3195
+ this.agentCard,
3196
+ new import_server.InMemoryTaskStore(),
3197
+ this.moltiumExecutor
3198
+ );
3199
+ logger9.info("A2A integration initialized", {
3200
+ agentName: agent.name,
3201
+ baseUrl: options.a2aConfig.baseUrl
3202
+ });
3203
+ }
3204
+ /**
3205
+ * Creates Express middleware handlers for A2A endpoints.
3206
+ * Returns an object with individual handlers that can be mounted on specific routes.
3207
+ */
3208
+ getHandlers() {
3209
+ return {
3210
+ // Agent Card endpoint - serves the static agent card JSON
3211
+ agentCard: ((req, res) => {
3212
+ res.json(this.agentCard);
3213
+ }),
3214
+ // JSON-RPC endpoint - handles A2A protocol requests
3215
+ jsonRpc: (async (req, res) => {
3216
+ try {
3217
+ const jsonRpcHandler = new import_server.JsonRpcTransportHandler(this.requestHandler);
3218
+ const response = await jsonRpcHandler.handle(req.body);
3219
+ res.json(response);
3220
+ } catch (error) {
3221
+ logger9.error("JSON-RPC error:", error);
3222
+ res.status(500).json({
3223
+ jsonrpc: "2.0",
3224
+ error: {
3225
+ code: -32603,
3226
+ message: "Internal error",
3227
+ data: error.message
3228
+ },
3229
+ id: req.body?.id || null
3230
+ });
3231
+ }
3232
+ }),
3233
+ // REST endpoint - simplified HTTP+JSON interface
3234
+ rest: ((req, res) => {
3235
+ res.status(501).json({
3236
+ error: "REST transport not implemented in SDK v0.3.0",
3237
+ message: "Please use the JSON-RPC endpoint at /a2a/jsonrpc"
3238
+ });
3239
+ })
3240
+ };
3241
+ }
3242
+ /**
3243
+ * Updates the agent card with actual runtime information (host/port).
3244
+ */
3245
+ updateAgentCard(actualPort, actualHost = "localhost") {
3246
+ this.agentCard = AgentCardBuilder.updateWithRuntime(this.agentCard, actualPort, actualHost);
3247
+ this.requestHandler = new import_server.DefaultRequestHandler(
3248
+ this.agentCard,
3249
+ new import_server.InMemoryTaskStore(),
3250
+ this.moltiumExecutor
3251
+ );
3252
+ logger9.info("A2A agent card updated with runtime info", {
3253
+ host: actualHost,
3254
+ port: actualPort,
3255
+ url: this.agentCard.url
3256
+ });
3257
+ }
3258
+ /**
3259
+ * Gets the current agent card.
3260
+ */
3261
+ getAgentCard() {
3262
+ return this.agentCard;
3263
+ }
3264
+ /**
3265
+ * Logs A2A endpoint information.
3266
+ */
3267
+ logEndpoints(host, port) {
3268
+ const protocol = host === "localhost" || host === "127.0.0.1" ? "http" : "https";
3269
+ const baseUrl = `${protocol}://${host}:${port}`;
3270
+ logger9.info("A2A endpoints available:");
3271
+ logger9.info(` Agent Card: ${baseUrl}/.well-known/agent-card.json`);
3272
+ logger9.info(` JSON-RPC: ${baseUrl}/a2a/jsonrpc`);
3273
+ logger9.info(` HTTP+JSON: ${baseUrl}/a2a/rest`);
3274
+ }
3275
+ };
3276
+ function createA2AIntegration(agent, options = {}) {
3277
+ const a2aConfig = {
3278
+ enabled: true,
3279
+ baseUrl: options.a2aConfig?.baseUrl || "http://localhost:3000",
3280
+ pushNotifications: options.a2aConfig?.pushNotifications ?? false,
3281
+ streaming: options.a2aConfig?.streaming ?? true,
3282
+ stateTransitionHistory: options.a2aConfig?.stateTransitionHistory ?? true
3283
+ };
3284
+ return new A2AIntegration(agent, { a2aConfig, ...options });
3285
+ }
3286
+
2624
3287
  // src/server/app.ts
2625
- var logger7 = createLogger("Server");
2626
- function createApp(agent) {
3288
+ var logger10 = createLogger("Server");
3289
+ var AGENT_CARD_PATH = ".well-known/agent-card.json";
3290
+ function createApp(agent, options = {}) {
2627
3291
  const app = (0, import_express2.default)();
2628
3292
  app.use(import_express2.default.json());
2629
3293
  app.use(requestLogger);
2630
3294
  app.use(authMiddleware);
2631
3295
  app.use(createRoutes(agent));
3296
+ if (options.enableA2A !== false) {
3297
+ const port = options.port || parseInt(process.env.PORT || "3000", 10);
3298
+ const host = options.host || "0.0.0.0";
3299
+ const protocol = host === "localhost" || host === "127.0.0.1" || host === "0.0.0.0" ? "http" : "https";
3300
+ const baseUrl = options.a2aConfig?.baseUrl || `${protocol}://${host}:${port}`;
3301
+ const a2aIntegration = createA2AIntegration(agent, {
3302
+ a2aConfig: {
3303
+ enabled: true,
3304
+ baseUrl,
3305
+ pushNotifications: options.a2aConfig?.pushNotifications ?? false,
3306
+ streaming: options.a2aConfig?.streaming ?? true,
3307
+ stateTransitionHistory: options.a2aConfig?.stateTransitionHistory ?? true
3308
+ }
3309
+ });
3310
+ const handlers = a2aIntegration.getHandlers();
3311
+ app.use(`/${AGENT_CARD_PATH}`, handlers.agentCard);
3312
+ app.use("/a2a/jsonrpc", handlers.jsonRpc);
3313
+ app.use("/a2a/rest", handlers.rest);
3314
+ logger10.info("A2A protocol endpoints enabled");
3315
+ }
2632
3316
  app.use(errorHandler);
2633
3317
  return app;
2634
3318
  }
2635
3319
  async function startServer(agent, options = {}) {
2636
3320
  const port = options.port || parseInt(process.env.PORT || "3000", 10);
2637
3321
  const host = options.host || "0.0.0.0";
2638
- const app = createApp(agent);
3322
+ const app = createApp(agent, options);
2639
3323
  await agent.start();
2640
3324
  app.listen(port, host, () => {
2641
- logger7.info(`Agent "${agent.name}" running at http://${host}:${port}`);
3325
+ logger10.info(`Agent "${agent.name}" running at http://${host}:${port}`);
3326
+ if (options.enableA2A !== false) {
3327
+ const protocol = host === "localhost" || host === "127.0.0.1" ? "http" : "https";
3328
+ const baseUrl = `${protocol}://${host}:${port}`;
3329
+ logger10.info("A2A Protocol Endpoints:");
3330
+ logger10.info(` Agent Card: ${baseUrl}/.well-known/agent-card.json`);
3331
+ logger10.info(` JSON-RPC: ${baseUrl}/a2a/jsonrpc`);
3332
+ logger10.info(` HTTP+JSON: ${baseUrl}/a2a/rest`);
3333
+ }
2642
3334
  });
2643
3335
  const shutdown = async () => {
2644
- logger7.info("Received shutdown signal");
3336
+ logger10.info("Received shutdown signal");
2645
3337
  await agent.stop();
2646
3338
  process.exit(0);
2647
3339
  };
@@ -2650,9 +3342,11 @@ async function startServer(agent, options = {}) {
2650
3342
  }
2651
3343
  // Annotate the CommonJS export names for ESM import in node:
2652
3344
  0 && (module.exports = {
3345
+ A2AIntegration,
2653
3346
  ActionHandler,
2654
3347
  ActionRegistry,
2655
3348
  Agent,
3349
+ AgentCardBuilder,
2656
3350
  AnthropicProvider,
2657
3351
  ConfigLoader,
2658
3352
  LLMProvider,
@@ -2660,6 +3354,7 @@ async function startServer(agent, options = {}) {
2660
3354
  MarkdownParser,
2661
3355
  Memory,
2662
3356
  MoltbookAdapter,
3357
+ MoltiumExecutor,
2663
3358
  OpenAIProvider,
2664
3359
  Scheduler,
2665
3360
  ShortTermMemory,
@@ -2669,6 +3364,7 @@ async function startServer(agent, options = {}) {
2669
3364
  buildSkillPrompt,
2670
3365
  buildSystemPrompt,
2671
3366
  builtInActions,
3367
+ createA2AIntegration,
2672
3368
  createApp,
2673
3369
  createLogger,
2674
3370
  createMarkdownAction,