@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/README.md +231 -0
- package/dist/index.d.cts +330 -3
- package/dist/index.d.ts +330 -3
- package/dist/index.js +903 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +891 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -2
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
|
|
2565
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|