@moltium/core 0.1.29 → 0.1.31
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/AgentWallet-WSXDC5NX.mjs +7 -0
- package/dist/AgentWallet-WSXDC5NX.mjs.map +1 -0
- package/dist/chunk-K2UFQ7YF.mjs +197 -0
- package/dist/chunk-K2UFQ7YF.mjs.map +1 -0
- package/dist/index.d.cts +67 -3
- package/dist/index.d.ts +67 -3
- package/dist/index.js +424 -129
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +201 -128
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -1
package/dist/index.js
CHANGED
|
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
8
11
|
var __export = (target, all) => {
|
|
9
12
|
for (var name in all)
|
|
10
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -27,6 +30,208 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
30
|
));
|
|
28
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
32
|
|
|
33
|
+
// src/logger.ts
|
|
34
|
+
function createLogger(label) {
|
|
35
|
+
return import_winston.default.createLogger({
|
|
36
|
+
level: logLevel,
|
|
37
|
+
format: import_winston.default.format.combine(
|
|
38
|
+
import_winston.default.format.timestamp({ format: "HH:mm:ss" }),
|
|
39
|
+
import_winston.default.format.label({ label }),
|
|
40
|
+
import_winston.default.format.printf(({ timestamp, level, label: label2, message, ...meta }) => {
|
|
41
|
+
const lvlColor = levelColors[level] || colors.white;
|
|
42
|
+
const lvl = `${lvlColor}${level.toUpperCase().padEnd(5)}${colors.reset}`;
|
|
43
|
+
const mod = `${colors.magenta}[${label2}]${colors.reset}`;
|
|
44
|
+
const ts = `${colors.dim}${timestamp}${colors.reset}`;
|
|
45
|
+
const metaStr = Object.keys(meta).length > 0 ? ` ${colors.dim}${JSON.stringify(meta)}${colors.reset}` : "";
|
|
46
|
+
return `${ts} ${lvl} ${mod} ${message}${metaStr}`;
|
|
47
|
+
})
|
|
48
|
+
),
|
|
49
|
+
transports: [new import_winston.default.transports.Console()]
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
var import_winston, logLevel, colors, levelColors;
|
|
53
|
+
var init_logger = __esm({
|
|
54
|
+
"src/logger.ts"() {
|
|
55
|
+
"use strict";
|
|
56
|
+
import_winston = __toESM(require("winston"), 1);
|
|
57
|
+
logLevel = process.env.LOG_LEVEL || "info";
|
|
58
|
+
colors = {
|
|
59
|
+
reset: "\x1B[0m",
|
|
60
|
+
dim: "\x1B[2m",
|
|
61
|
+
bold: "\x1B[1m",
|
|
62
|
+
cyan: "\x1B[36m",
|
|
63
|
+
yellow: "\x1B[33m",
|
|
64
|
+
green: "\x1B[32m",
|
|
65
|
+
red: "\x1B[31m",
|
|
66
|
+
magenta: "\x1B[35m",
|
|
67
|
+
blue: "\x1B[34m",
|
|
68
|
+
white: "\x1B[37m",
|
|
69
|
+
gray: "\x1B[90m"
|
|
70
|
+
};
|
|
71
|
+
levelColors = {
|
|
72
|
+
error: colors.red,
|
|
73
|
+
warn: colors.yellow,
|
|
74
|
+
info: colors.green,
|
|
75
|
+
debug: colors.gray
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// src/wallet/AgentWallet.ts
|
|
81
|
+
var AgentWallet_exports = {};
|
|
82
|
+
__export(AgentWallet_exports, {
|
|
83
|
+
AgentWallet: () => AgentWallet
|
|
84
|
+
});
|
|
85
|
+
var logger3, AgentWallet;
|
|
86
|
+
var init_AgentWallet = __esm({
|
|
87
|
+
"src/wallet/AgentWallet.ts"() {
|
|
88
|
+
"use strict";
|
|
89
|
+
init_logger();
|
|
90
|
+
logger3 = createLogger("AgentWallet");
|
|
91
|
+
AgentWallet = class {
|
|
92
|
+
constructor(privateKey, rpcUrl) {
|
|
93
|
+
this.privateKey = privateKey;
|
|
94
|
+
if (!privateKey.startsWith("0x")) {
|
|
95
|
+
this.privateKey = `0x${privateKey}`;
|
|
96
|
+
}
|
|
97
|
+
if (rpcUrl) {
|
|
98
|
+
this.connect(rpcUrl);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
ethers;
|
|
102
|
+
wallet;
|
|
103
|
+
// ethers.Wallet
|
|
104
|
+
provider;
|
|
105
|
+
// ethers.JsonRpcProvider
|
|
106
|
+
_address = null;
|
|
107
|
+
/**
|
|
108
|
+
* Lazy-load ethers.js (optional peer dependency)
|
|
109
|
+
*/
|
|
110
|
+
async loadEthers() {
|
|
111
|
+
if (this.ethers) return this.ethers;
|
|
112
|
+
try {
|
|
113
|
+
this.ethers = await import("ethers");
|
|
114
|
+
return this.ethers;
|
|
115
|
+
} catch {
|
|
116
|
+
throw new Error(
|
|
117
|
+
"ethers.js is required for wallet operations. Install it: npm install ethers"
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Ensure wallet is initialized
|
|
123
|
+
*/
|
|
124
|
+
async ensureWallet() {
|
|
125
|
+
if (this.wallet) return;
|
|
126
|
+
const ethers = await this.loadEthers();
|
|
127
|
+
if (this.provider) {
|
|
128
|
+
this.wallet = new ethers.Wallet(this.privateKey, this.provider);
|
|
129
|
+
} else {
|
|
130
|
+
this.wallet = new ethers.Wallet(this.privateKey);
|
|
131
|
+
}
|
|
132
|
+
this._address = this.wallet.address;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Connect to a blockchain RPC endpoint
|
|
136
|
+
*/
|
|
137
|
+
connect(rpcUrl) {
|
|
138
|
+
this._rpcUrl = rpcUrl;
|
|
139
|
+
this.wallet = null;
|
|
140
|
+
this.provider = null;
|
|
141
|
+
}
|
|
142
|
+
_rpcUrl;
|
|
143
|
+
/**
|
|
144
|
+
* Ensure provider is connected
|
|
145
|
+
*/
|
|
146
|
+
async ensureProvider() {
|
|
147
|
+
if (this.provider) return;
|
|
148
|
+
if (!this._rpcUrl) {
|
|
149
|
+
throw new Error("No RPC URL configured. Call connect(rpcUrl) first.");
|
|
150
|
+
}
|
|
151
|
+
const ethers = await this.loadEthers();
|
|
152
|
+
this.provider = new ethers.JsonRpcProvider(this._rpcUrl);
|
|
153
|
+
this.wallet = new ethers.Wallet(this.privateKey, this.provider);
|
|
154
|
+
this._address = this.wallet.address;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get the wallet address derived from the private key.
|
|
158
|
+
* This is synchronous if ethers is already loaded, otherwise async.
|
|
159
|
+
*/
|
|
160
|
+
getAddress() {
|
|
161
|
+
if (this._address) return this._address;
|
|
162
|
+
try {
|
|
163
|
+
const ethers = require("ethers");
|
|
164
|
+
const addr = ethers.computeAddress(this.privateKey);
|
|
165
|
+
this._address = addr;
|
|
166
|
+
return addr;
|
|
167
|
+
} catch {
|
|
168
|
+
throw new Error(
|
|
169
|
+
"ethers.js is required for wallet operations. Install it: npm install ethers"
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Get wallet address (async version — always works)
|
|
175
|
+
*/
|
|
176
|
+
async getAddressAsync() {
|
|
177
|
+
if (this._address) return this._address;
|
|
178
|
+
const ethers = await this.loadEthers();
|
|
179
|
+
const addr = ethers.computeAddress(this.privateKey);
|
|
180
|
+
this._address = addr;
|
|
181
|
+
return addr;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Send native tokens (MON/ETH) to an address
|
|
185
|
+
* @param to Recipient address
|
|
186
|
+
* @param amountWei Amount in wei (string)
|
|
187
|
+
* @returns Transaction hash
|
|
188
|
+
*/
|
|
189
|
+
async sendPayment(to, amountWei) {
|
|
190
|
+
await this.ensureProvider();
|
|
191
|
+
logger3.info(`Sending payment: ${amountWei} wei to ${to}`);
|
|
192
|
+
const tx = await this.wallet.sendTransaction({
|
|
193
|
+
to,
|
|
194
|
+
value: BigInt(amountWei)
|
|
195
|
+
});
|
|
196
|
+
logger3.info(`Payment sent, waiting for confirmation...`, { txHash: tx.hash });
|
|
197
|
+
const receipt = await tx.wait();
|
|
198
|
+
if (receipt.status !== 1) {
|
|
199
|
+
throw new Error(`Payment transaction failed: ${tx.hash}`);
|
|
200
|
+
}
|
|
201
|
+
logger3.info(`Payment confirmed`, { txHash: tx.hash });
|
|
202
|
+
return tx.hash;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Sign a message with the wallet's private key
|
|
206
|
+
* @param message Message to sign
|
|
207
|
+
* @returns Signature hex string
|
|
208
|
+
*/
|
|
209
|
+
async signMessage(message) {
|
|
210
|
+
await this.ensureWallet();
|
|
211
|
+
return this.wallet.signMessage(message);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Get wallet balance in wei
|
|
215
|
+
* @returns Balance as string (wei)
|
|
216
|
+
*/
|
|
217
|
+
async getBalance() {
|
|
218
|
+
await this.ensureProvider();
|
|
219
|
+
const balance = await this.provider.getBalance(this.wallet.address);
|
|
220
|
+
return balance.toString();
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Get formatted balance (in ETH/MON)
|
|
224
|
+
*/
|
|
225
|
+
async getFormattedBalance() {
|
|
226
|
+
await this.ensureProvider();
|
|
227
|
+
const ethers = await this.loadEthers();
|
|
228
|
+
const balance = await this.provider.getBalance(this.wallet.address);
|
|
229
|
+
return ethers.formatEther(balance);
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
30
235
|
// src/index.ts
|
|
31
236
|
var index_exports = {};
|
|
32
237
|
__export(index_exports, {
|
|
@@ -36,6 +241,7 @@ __export(index_exports, {
|
|
|
36
241
|
ActionRegistry: () => ActionRegistry,
|
|
37
242
|
Agent: () => Agent,
|
|
38
243
|
AgentCardBuilder: () => AgentCardBuilder,
|
|
244
|
+
AgentWallet: () => AgentWallet,
|
|
39
245
|
AnthropicProvider: () => AnthropicProvider,
|
|
40
246
|
ConfigLoader: () => ConfigLoader,
|
|
41
247
|
LLMProvider: () => LLMProvider,
|
|
@@ -70,25 +276,8 @@ __export(index_exports, {
|
|
|
70
276
|
});
|
|
71
277
|
module.exports = __toCommonJS(index_exports);
|
|
72
278
|
|
|
73
|
-
// src/logger.ts
|
|
74
|
-
var import_winston = __toESM(require("winston"), 1);
|
|
75
|
-
var logLevel = process.env.LOG_LEVEL || "info";
|
|
76
|
-
function createLogger(label) {
|
|
77
|
-
return import_winston.default.createLogger({
|
|
78
|
-
level: logLevel,
|
|
79
|
-
format: import_winston.default.format.combine(
|
|
80
|
-
import_winston.default.format.timestamp(),
|
|
81
|
-
import_winston.default.format.label({ label }),
|
|
82
|
-
import_winston.default.format.printf(({ timestamp, level, label: label2, message, ...meta }) => {
|
|
83
|
-
const metaStr = Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : "";
|
|
84
|
-
return `${timestamp} [${label2}] ${level}: ${message}${metaStr}`;
|
|
85
|
-
})
|
|
86
|
-
),
|
|
87
|
-
transports: [new import_winston.default.transports.Console()]
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
279
|
// src/agent/scheduler.ts
|
|
280
|
+
init_logger();
|
|
92
281
|
var logger = createLogger("Scheduler");
|
|
93
282
|
var Scheduler = class {
|
|
94
283
|
jobs = [];
|
|
@@ -168,6 +357,7 @@ var ActionRegistry = class {
|
|
|
168
357
|
};
|
|
169
358
|
|
|
170
359
|
// src/actions/ActionHandler.ts
|
|
360
|
+
init_logger();
|
|
171
361
|
var logger2 = createLogger("ActionHandler");
|
|
172
362
|
var ActionExecutionError = class extends Error {
|
|
173
363
|
constructor(message, actionName, recoverable = true) {
|
|
@@ -497,25 +687,70 @@ var moltbookActions = [
|
|
|
497
687
|
];
|
|
498
688
|
|
|
499
689
|
// src/actions/built-in/world.ts
|
|
690
|
+
init_logger();
|
|
691
|
+
var logger4 = createLogger("WorldActions");
|
|
692
|
+
var joinedWorlds = /* @__PURE__ */ new Set();
|
|
500
693
|
function createJoinWorldAction(config) {
|
|
501
694
|
return {
|
|
502
695
|
name: "join_world",
|
|
503
|
-
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.`,
|
|
696
|
+
description: `Join a world by URL. The world will fetch this agent's A2A Agent Card and evaluate admission. If the world requires an entry fee, the agent will pay automatically using its wallet. 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.`,
|
|
504
697
|
async execute(context) {
|
|
505
698
|
const { parameters, agent } = context;
|
|
506
699
|
const worldUrl = parameters.worldUrl || config?.defaultWorldUrl;
|
|
507
700
|
if (!worldUrl) {
|
|
508
701
|
return { success: false, error: 'Parameter "worldUrl" is required' };
|
|
509
702
|
}
|
|
703
|
+
if (joinedWorlds.has(worldUrl)) {
|
|
704
|
+
return {
|
|
705
|
+
success: true,
|
|
706
|
+
data: { message: "Already joined this world", worldUrl }
|
|
707
|
+
};
|
|
708
|
+
}
|
|
510
709
|
const agentPort = process.env.PORT || "3000";
|
|
511
710
|
const agentHost = process.env.HOST || "localhost";
|
|
512
711
|
const agentUrl = `http://${agentHost}:${agentPort}`;
|
|
712
|
+
const walletAddress = parameters.walletAddress || agent?.config?.world?.walletAddress;
|
|
513
713
|
try {
|
|
514
714
|
const { default: axios2 } = await import("axios");
|
|
715
|
+
let paymentTxHash;
|
|
716
|
+
let joinInfo = null;
|
|
717
|
+
try {
|
|
718
|
+
const infoRes = await axios2.get(`${worldUrl}/world/join-info`, { timeout: 5e3 });
|
|
719
|
+
joinInfo = infoRes.data;
|
|
720
|
+
} catch (infoError) {
|
|
721
|
+
if (infoError?.response?.status !== 404) {
|
|
722
|
+
logger4.debug(`Could not query join-info: ${infoError.message}`);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
if (joinInfo?.requiresPayment && joinInfo.entryFee && joinInfo.entryFee !== "0") {
|
|
726
|
+
const privateKey = agent?.config?.world?.privateKey;
|
|
727
|
+
if (!privateKey) {
|
|
728
|
+
return {
|
|
729
|
+
success: false,
|
|
730
|
+
error: "World requires entry fee but agent has no wallet private key configured. Set AGENT_WALLET_PRIVATE_KEY in your .env file."
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
logger4.info(`World requires entry fee: ${joinInfo.entryFee} wei`);
|
|
734
|
+
const { AgentWallet: AgentWallet2 } = await Promise.resolve().then(() => (init_AgentWallet(), AgentWallet_exports));
|
|
735
|
+
const wallet = new AgentWallet2(privateKey, joinInfo.rpcUrl);
|
|
736
|
+
const balance = await wallet.getBalance();
|
|
737
|
+
if (BigInt(balance) < BigInt(joinInfo.entryFee)) {
|
|
738
|
+
const { formatEther } = await import("ethers");
|
|
739
|
+
return {
|
|
740
|
+
success: false,
|
|
741
|
+
error: `Insufficient balance to pay entry fee. Need ${formatEther(joinInfo.entryFee)} MON, have ${formatEther(balance)} MON`
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
logger4.info(`Paying entry fee to ${joinInfo.paymentAddress}...`);
|
|
745
|
+
paymentTxHash = await wallet.sendPayment(joinInfo.paymentAddress, joinInfo.entryFee);
|
|
746
|
+
logger4.info(`Entry fee paid. TX: ${paymentTxHash}`);
|
|
747
|
+
}
|
|
515
748
|
const response = await axios2.post(`${worldUrl}/world/join`, {
|
|
516
749
|
agentUrl,
|
|
517
|
-
walletAddress
|
|
750
|
+
walletAddress,
|
|
751
|
+
paymentTxHash
|
|
518
752
|
}, { timeout: 1e4 });
|
|
753
|
+
joinedWorlds.add(worldUrl);
|
|
519
754
|
return {
|
|
520
755
|
success: true,
|
|
521
756
|
data: response.data
|
|
@@ -546,6 +781,7 @@ function createLeaveWorldAction(config) {
|
|
|
546
781
|
`${worldUrl}/world/agents/${encodeURIComponent(agentUrl)}`,
|
|
547
782
|
{ timeout: 1e4 }
|
|
548
783
|
);
|
|
784
|
+
joinedWorlds.delete(worldUrl);
|
|
549
785
|
return {
|
|
550
786
|
success: true,
|
|
551
787
|
data: response.data
|
|
@@ -663,17 +899,39 @@ ${config.llm.systemPrompt}`);
|
|
|
663
899
|
}
|
|
664
900
|
function buildDecisionPrompt(context, availableActions) {
|
|
665
901
|
const actionList = availableActions.map((a) => `- ${a.name}: ${a.description}`).join("\n");
|
|
902
|
+
const actionNames = availableActions.map((a) => a.name);
|
|
903
|
+
const hasWorldActions = actionNames.some(
|
|
904
|
+
(n) => ["send_world_message", "query_world", "join_world", "leave_world"].includes(n)
|
|
905
|
+
);
|
|
906
|
+
const hasSocialActions = actionNames.some(
|
|
907
|
+
(n) => ["post_social_update", "respond_to_mention"].includes(n)
|
|
908
|
+
);
|
|
666
909
|
const recent = context.recentActions || [];
|
|
667
910
|
const recentNames = recent.map((r) => r.action);
|
|
668
911
|
const lastAction = recentNames.length > 0 ? recentNames[recentNames.length - 1] : "none";
|
|
669
912
|
let varietyHint = "";
|
|
670
913
|
if (recentNames.length > 0) {
|
|
914
|
+
const suggestions = [];
|
|
915
|
+
if (hasWorldActions) {
|
|
916
|
+
suggestions.push("querying the world for agents", "sending messages to other agents", "responding to conversations");
|
|
917
|
+
}
|
|
918
|
+
if (hasSocialActions) {
|
|
919
|
+
suggestions.push("posting content", "responding to mentions");
|
|
920
|
+
}
|
|
921
|
+
const suggestStr = suggestions.length > 0 ? `
|
|
922
|
+
Vary between: ${suggestions.join(", ")}.` : "";
|
|
671
923
|
varietyHint = `
|
|
672
924
|
Your recent actions (most recent last): ${recentNames.join(" \u2192 ")}
|
|
673
|
-
IMPORTANT: Do NOT repeat "${lastAction}" again. Choose a DIFFERENT action to keep your behavior varied and interesting
|
|
674
|
-
Vary between: posting content, checking your feed, replying to others, checking DMs, browsing communities, searching for topics, and following interesting agents.`;
|
|
925
|
+
IMPORTANT: Do NOT repeat "${lastAction}" again. Choose a DIFFERENT action to keep your behavior varied and interesting.` + suggestStr;
|
|
675
926
|
}
|
|
676
|
-
|
|
927
|
+
let preamble = "You are an autonomous AI agent.";
|
|
928
|
+
if (hasWorldActions) {
|
|
929
|
+
preamble += " You are connected to a world with other agents.";
|
|
930
|
+
preamble += " Use send_world_message to communicate with other agents (provide toAgentUrl and message parameters).";
|
|
931
|
+
preamble += " Use query_world to discover agents and world state.";
|
|
932
|
+
preamble += ' IMPORTANT: Only use actions from the "Available actions" list below. Do NOT invent action names.';
|
|
933
|
+
}
|
|
934
|
+
return `${preamble}
|
|
677
935
|
Decide what action to take next based on the current context and your personality.
|
|
678
936
|
|
|
679
937
|
Available actions:
|
|
@@ -684,7 +942,7 @@ ${JSON.stringify(context, null, 2)}
|
|
|
684
942
|
${varietyHint}
|
|
685
943
|
|
|
686
944
|
Think about what would be most natural and valuable right now.
|
|
687
|
-
|
|
945
|
+
Choose ONLY from the available actions listed above.
|
|
688
946
|
|
|
689
947
|
Respond with a JSON object:
|
|
690
948
|
{
|
|
@@ -711,7 +969,8 @@ Execute these instructions step by step and return the result as a JSON object:
|
|
|
711
969
|
}
|
|
712
970
|
|
|
713
971
|
// src/actions/interpreter.ts
|
|
714
|
-
|
|
972
|
+
init_logger();
|
|
973
|
+
var logger5 = createLogger("MarkdownInterpreter");
|
|
715
974
|
var LLMInterpretationError = class extends Error {
|
|
716
975
|
constructor(message) {
|
|
717
976
|
super(message);
|
|
@@ -723,7 +982,7 @@ function createMarkdownAction(name, description, llmProvider) {
|
|
|
723
982
|
name,
|
|
724
983
|
description,
|
|
725
984
|
execute: async (context) => {
|
|
726
|
-
|
|
985
|
+
logger5.info(`Interpreting markdown skill: ${name}`);
|
|
727
986
|
const prompt = buildSkillPrompt(name, description, context.parameters);
|
|
728
987
|
try {
|
|
729
988
|
const response = await llmProvider.generateText(prompt, {
|
|
@@ -744,7 +1003,7 @@ function createMarkdownAction(name, description, llmProvider) {
|
|
|
744
1003
|
} catch (error) {
|
|
745
1004
|
if (error instanceof LLMInterpretationError) throw error;
|
|
746
1005
|
const message = error instanceof Error ? error.message : String(error);
|
|
747
|
-
|
|
1006
|
+
logger5.error(`Markdown skill interpretation failed: ${name}`, { error: message });
|
|
748
1007
|
throw new LLMInterpretationError(
|
|
749
1008
|
`Failed to interpret skill "${name}": ${message}`
|
|
750
1009
|
);
|
|
@@ -1524,6 +1783,9 @@ var TwitterAdapter = class extends SocialAdapter {
|
|
|
1524
1783
|
}
|
|
1525
1784
|
};
|
|
1526
1785
|
|
|
1786
|
+
// src/agent/Agent.ts
|
|
1787
|
+
init_logger();
|
|
1788
|
+
|
|
1527
1789
|
// src/a2a/client.ts
|
|
1528
1790
|
var import_client = require("@a2a-js/sdk/client");
|
|
1529
1791
|
var import_uuid = require("uuid");
|
|
@@ -1697,7 +1959,7 @@ function createMultipleA2AActions(configs) {
|
|
|
1697
1959
|
}
|
|
1698
1960
|
|
|
1699
1961
|
// src/agent/Agent.ts
|
|
1700
|
-
var
|
|
1962
|
+
var logger6 = createLogger("Agent");
|
|
1701
1963
|
function parsePostFrequency(freq) {
|
|
1702
1964
|
const lower = freq.toLowerCase().trim();
|
|
1703
1965
|
if (lower === "realtime") return 5 * 60 * 1e3;
|
|
@@ -1793,7 +2055,17 @@ var Agent = class {
|
|
|
1793
2055
|
// ── Lifecycle ──
|
|
1794
2056
|
async init() {
|
|
1795
2057
|
this.state = "initializing";
|
|
1796
|
-
|
|
2058
|
+
logger6.info(`Initializing agent: ${this.config.name}`);
|
|
2059
|
+
if (this.config.world?.privateKey && !this.config.world.walletAddress) {
|
|
2060
|
+
try {
|
|
2061
|
+
const { AgentWallet: AgentWallet2 } = await Promise.resolve().then(() => (init_AgentWallet(), AgentWallet_exports));
|
|
2062
|
+
const wallet = new AgentWallet2(this.config.world.privateKey);
|
|
2063
|
+
this.config.world.walletAddress = await wallet.getAddressAsync();
|
|
2064
|
+
logger6.info(`Wallet address derived: ${this.config.world.walletAddress}`);
|
|
2065
|
+
} catch (error) {
|
|
2066
|
+
logger6.warn(`Failed to derive wallet address: ${error.message}`);
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
1797
2069
|
this.initLLM();
|
|
1798
2070
|
this.registerActions();
|
|
1799
2071
|
await this.initSocialAdapters();
|
|
@@ -1802,7 +2074,7 @@ var Agent = class {
|
|
|
1802
2074
|
await this.hooks.onInit(this);
|
|
1803
2075
|
}
|
|
1804
2076
|
await this.postStartupMessages();
|
|
1805
|
-
|
|
2077
|
+
logger6.info(`Agent initialized: ${this.config.name}`);
|
|
1806
2078
|
}
|
|
1807
2079
|
async start() {
|
|
1808
2080
|
if (this.state !== "initializing" && this.state !== "idle") {
|
|
@@ -1812,7 +2084,7 @@ var Agent = class {
|
|
|
1812
2084
|
await this.init();
|
|
1813
2085
|
}
|
|
1814
2086
|
this.state = "running";
|
|
1815
|
-
|
|
2087
|
+
logger6.info(`Agent started: ${this.config.name}`);
|
|
1816
2088
|
if (this.hooks.onStart) {
|
|
1817
2089
|
await this.hooks.onStart(this);
|
|
1818
2090
|
}
|
|
@@ -1826,7 +2098,7 @@ var Agent = class {
|
|
|
1826
2098
|
}
|
|
1827
2099
|
async stop() {
|
|
1828
2100
|
this.state = "stopping";
|
|
1829
|
-
|
|
2101
|
+
logger6.info(`Stopping agent: ${this.config.name}`);
|
|
1830
2102
|
if (this.tickTimer) {
|
|
1831
2103
|
clearInterval(this.tickTimer);
|
|
1832
2104
|
this.tickTimer = void 0;
|
|
@@ -1839,7 +2111,7 @@ var Agent = class {
|
|
|
1839
2111
|
await this.hooks.onShutdown(this);
|
|
1840
2112
|
}
|
|
1841
2113
|
this.state = "stopped";
|
|
1842
|
-
|
|
2114
|
+
logger6.info(`Agent stopped: ${this.config.name}`);
|
|
1843
2115
|
}
|
|
1844
2116
|
// ── Decision Loop ──
|
|
1845
2117
|
async think() {
|
|
@@ -1859,7 +2131,7 @@ var Agent = class {
|
|
|
1859
2131
|
},
|
|
1860
2132
|
{ systemPrompt: this.systemPrompt, temperature: this.config.llm.temperature }
|
|
1861
2133
|
);
|
|
1862
|
-
|
|
2134
|
+
logger6.debug(`Decision: ${decision.action} \u2014 ${decision.reasoning}`);
|
|
1863
2135
|
return decision;
|
|
1864
2136
|
}
|
|
1865
2137
|
async act(actionName, parameters = {}) {
|
|
@@ -1882,17 +2154,17 @@ var Agent = class {
|
|
|
1882
2154
|
await this.hooks.onTick(this);
|
|
1883
2155
|
}
|
|
1884
2156
|
if (this.isSleeping()) {
|
|
1885
|
-
|
|
2157
|
+
logger6.info(`Tick #${this.tickCount}: Sleeping \u2014 skipped`);
|
|
1886
2158
|
return;
|
|
1887
2159
|
}
|
|
1888
|
-
|
|
2160
|
+
logger6.info(`Tick #${this.tickCount}: Thinking...`);
|
|
1889
2161
|
const decision = await this.think();
|
|
1890
|
-
|
|
2162
|
+
logger6.info(`Tick #${this.tickCount}: Decision \u2192 ${decision.action} | Reasoning: ${decision.reasoning}`);
|
|
1891
2163
|
if (decision.parameters && Object.keys(decision.parameters).length > 0) {
|
|
1892
|
-
|
|
2164
|
+
logger6.info(`Tick #${this.tickCount}: Parameters \u2192 ${JSON.stringify(decision.parameters)}`);
|
|
1893
2165
|
}
|
|
1894
2166
|
const result = await this.act(decision.action, decision.parameters);
|
|
1895
|
-
|
|
2167
|
+
logger6.info(`Tick #${this.tickCount}: Result \u2192 success=${result.success}${result.data ? ` data=${JSON.stringify(result.data).slice(0, 200)}` : ""}`);
|
|
1896
2168
|
this.recentActions.push({
|
|
1897
2169
|
action: decision.action,
|
|
1898
2170
|
reasoning: decision.reasoning,
|
|
@@ -1910,7 +2182,7 @@ var Agent = class {
|
|
|
1910
2182
|
await this.fireWebhook("onAction", decision, result);
|
|
1911
2183
|
}
|
|
1912
2184
|
} catch (error) {
|
|
1913
|
-
|
|
2185
|
+
logger6.error(`Tick #${this.tickCount} error: ${error instanceof Error ? error.message : error}`);
|
|
1914
2186
|
if (this.hooks.onError && error instanceof Error) {
|
|
1915
2187
|
await this.hooks.onError(error, this);
|
|
1916
2188
|
}
|
|
@@ -1950,7 +2222,7 @@ var Agent = class {
|
|
|
1950
2222
|
this.actionRegistry.register(action);
|
|
1951
2223
|
}
|
|
1952
2224
|
}
|
|
1953
|
-
|
|
2225
|
+
logger6.info(`Registered ${moltbookActions.length} Moltbook actions`);
|
|
1954
2226
|
}
|
|
1955
2227
|
const a2a = this.config.a2a;
|
|
1956
2228
|
if (a2a && a2a.enabled !== false) {
|
|
@@ -1970,7 +2242,7 @@ var Agent = class {
|
|
|
1970
2242
|
this.actionRegistry.register(action);
|
|
1971
2243
|
}
|
|
1972
2244
|
}
|
|
1973
|
-
|
|
2245
|
+
logger6.info(`Registered ${peerActions.length} A2A peer actions`);
|
|
1974
2246
|
} else {
|
|
1975
2247
|
const genericAction = createA2ACommunicationAction({
|
|
1976
2248
|
defaultAgentUrl: a2a.defaultPeerUrl,
|
|
@@ -1980,7 +2252,7 @@ var Agent = class {
|
|
|
1980
2252
|
if (!this.actionRegistry.has(genericAction.name)) {
|
|
1981
2253
|
this.actionRegistry.register(genericAction);
|
|
1982
2254
|
}
|
|
1983
|
-
|
|
2255
|
+
logger6.info(`Registered generic A2A action: ${genericAction.name}`);
|
|
1984
2256
|
}
|
|
1985
2257
|
}
|
|
1986
2258
|
const world = this.config.world;
|
|
@@ -1997,7 +2269,7 @@ var Agent = class {
|
|
|
1997
2269
|
this.actionRegistry.register(action);
|
|
1998
2270
|
}
|
|
1999
2271
|
}
|
|
2000
|
-
|
|
2272
|
+
logger6.info(`Registered 4 world actions (world: ${worldUrl})`);
|
|
2001
2273
|
}
|
|
2002
2274
|
if (this.config.customActions) {
|
|
2003
2275
|
for (const action of this.config.customActions) {
|
|
@@ -2010,7 +2282,7 @@ var Agent = class {
|
|
|
2010
2282
|
await this.initMoltbook(social);
|
|
2011
2283
|
await this.initTwitter(social);
|
|
2012
2284
|
if (Object.keys(this.socialAdapters).length === 0) {
|
|
2013
|
-
|
|
2285
|
+
logger6.warn("Social: No adapters connected. Set MOLTBOOK_API_KEY or Twitter env vars in your .env to enable.");
|
|
2014
2286
|
}
|
|
2015
2287
|
}
|
|
2016
2288
|
async initMoltbook(social) {
|
|
@@ -2021,13 +2293,13 @@ var Agent = class {
|
|
|
2021
2293
|
const explicitlyDisabled = configMoltbook && configMoltbook.enabled === false && !envKey;
|
|
2022
2294
|
const shouldConnect = !isPlaceholder && !explicitlyDisabled;
|
|
2023
2295
|
if (explicitlyDisabled) {
|
|
2024
|
-
|
|
2296
|
+
logger6.info("Moltbook: Disabled in config and no MOLTBOOK_API_KEY in env \u2014 skipping");
|
|
2025
2297
|
return;
|
|
2026
2298
|
}
|
|
2027
2299
|
if (isPlaceholder) {
|
|
2028
2300
|
if (configMoltbook?.enabled || envKey) {
|
|
2029
|
-
|
|
2030
|
-
|
|
2301
|
+
logger6.warn("Moltbook: MOLTBOOK_API_KEY is missing or still a placeholder.");
|
|
2302
|
+
logger6.warn(" Fix: Set a valid MOLTBOOK_API_KEY in your .env file.");
|
|
2031
2303
|
}
|
|
2032
2304
|
return;
|
|
2033
2305
|
}
|
|
@@ -2045,16 +2317,16 @@ var Agent = class {
|
|
|
2045
2317
|
...configMoltbook?.apiKey ? {} : { apiKey },
|
|
2046
2318
|
...configMoltbook?.baseUrl ? {} : { baseUrl }
|
|
2047
2319
|
};
|
|
2048
|
-
|
|
2049
|
-
|
|
2320
|
+
logger6.info(`Moltbook: API key detected from ${source}`);
|
|
2321
|
+
logger6.info(`Moltbook: Connecting to ${baseUrl} ...`);
|
|
2050
2322
|
const adapter = new MoltbookAdapter(effectiveConfig);
|
|
2051
2323
|
try {
|
|
2052
2324
|
await adapter.connect();
|
|
2053
2325
|
this.socialAdapters["moltbook"] = adapter;
|
|
2054
2326
|
social.moltbook = effectiveConfig;
|
|
2055
|
-
|
|
2327
|
+
logger6.info(`Moltbook: Connected successfully (submolt: ${defaultSubmolt})`);
|
|
2056
2328
|
} catch (error) {
|
|
2057
|
-
|
|
2329
|
+
logger6.error(`Moltbook: Connection FAILED \u2014 ${error.message || error}`);
|
|
2058
2330
|
this.logPlatformError("Moltbook", error);
|
|
2059
2331
|
}
|
|
2060
2332
|
}
|
|
@@ -2073,23 +2345,23 @@ var Agent = class {
|
|
|
2073
2345
|
const hasAllCreds = hasKey && apiSecret && accessToken && accessSecret;
|
|
2074
2346
|
const explicitlyDisabled = configTwitter && configTwitter.enabled === false && !envApiKey;
|
|
2075
2347
|
if (explicitlyDisabled) {
|
|
2076
|
-
|
|
2348
|
+
logger6.info("Twitter: Disabled in config and no TWITTER_API_KEY in env \u2014 skipping");
|
|
2077
2349
|
return;
|
|
2078
2350
|
}
|
|
2079
2351
|
if (!hasKey) {
|
|
2080
2352
|
if (configTwitter?.enabled || envApiKey) {
|
|
2081
|
-
|
|
2082
|
-
|
|
2353
|
+
logger6.warn("Twitter: Credentials are missing or still placeholders.");
|
|
2354
|
+
logger6.warn(" Fix: Set valid Twitter keys in your .env file.");
|
|
2083
2355
|
}
|
|
2084
2356
|
return;
|
|
2085
2357
|
}
|
|
2086
2358
|
if (!hasAllCreds) {
|
|
2087
|
-
|
|
2359
|
+
logger6.warn("Twitter: Some credentials are missing. Need: TWITTER_API_KEY, TWITTER_API_SECRET, TWITTER_ACCESS_TOKEN, TWITTER_ACCESS_SECRET");
|
|
2088
2360
|
return;
|
|
2089
2361
|
}
|
|
2090
2362
|
const source = creds?.apiKey ? "config" : "environment";
|
|
2091
|
-
|
|
2092
|
-
|
|
2363
|
+
logger6.info(`Twitter: Credentials detected from ${source}`);
|
|
2364
|
+
logger6.info("Twitter: Connecting...");
|
|
2093
2365
|
const effectiveConfig = {
|
|
2094
2366
|
enabled: true,
|
|
2095
2367
|
...configTwitter,
|
|
@@ -2100,16 +2372,16 @@ var Agent = class {
|
|
|
2100
2372
|
await adapter.connect();
|
|
2101
2373
|
this.socialAdapters["twitter"] = adapter;
|
|
2102
2374
|
social.twitter = effectiveConfig;
|
|
2103
|
-
|
|
2375
|
+
logger6.info("Twitter: Connected successfully");
|
|
2104
2376
|
} catch (error) {
|
|
2105
|
-
|
|
2377
|
+
logger6.error(`Twitter: Connection FAILED \u2014 ${error.message || error}`);
|
|
2106
2378
|
this.logPlatformError("Twitter", error);
|
|
2107
2379
|
}
|
|
2108
2380
|
}
|
|
2109
2381
|
async postStartupMessages() {
|
|
2110
2382
|
const adapters = Object.entries(this.socialAdapters);
|
|
2111
2383
|
if (adapters.length === 0) {
|
|
2112
|
-
|
|
2384
|
+
logger6.info("Startup post: No connected social adapters \u2014 skipping");
|
|
2113
2385
|
return;
|
|
2114
2386
|
}
|
|
2115
2387
|
let content;
|
|
@@ -2124,18 +2396,18 @@ Write only the post content, nothing else. Keep it concise and natural.`;
|
|
|
2124
2396
|
temperature: this.config.llm.temperature ?? 0.8,
|
|
2125
2397
|
maxTokens: 280
|
|
2126
2398
|
})).trim();
|
|
2127
|
-
|
|
2399
|
+
logger6.info(`Startup post: LLM generated content (${content.length} chars)`);
|
|
2128
2400
|
} catch (error) {
|
|
2129
|
-
|
|
2401
|
+
logger6.warn(`Startup post: LLM generation failed (${error.message}), using fallback`);
|
|
2130
2402
|
content = `${this.config.name} is now online and ready.`;
|
|
2131
2403
|
}
|
|
2132
2404
|
for (const [platform, adapter] of adapters) {
|
|
2133
|
-
|
|
2405
|
+
logger6.info(`Startup post: Posting to ${platform}...`);
|
|
2134
2406
|
try {
|
|
2135
2407
|
const result = await adapter.post(content);
|
|
2136
|
-
|
|
2408
|
+
logger6.info(`Startup post: ${platform} SUCCESS \u2014 id=${result.id}${result.url ? ` url=${result.url}` : ""}`);
|
|
2137
2409
|
} catch (error) {
|
|
2138
|
-
|
|
2410
|
+
logger6.error(`Startup post: ${platform} FAILED \u2014 ${error.message || error}`);
|
|
2139
2411
|
this.logPlatformError(platform, error);
|
|
2140
2412
|
}
|
|
2141
2413
|
}
|
|
@@ -2158,7 +2430,7 @@ Write only the post content, nothing else. Keep it concise and natural.`;
|
|
|
2158
2430
|
await this.scheduledPost("moltbook");
|
|
2159
2431
|
}
|
|
2160
2432
|
});
|
|
2161
|
-
|
|
2433
|
+
logger6.info(`Scheduler: Moltbook posting every ${formatInterval(intervalMs)}`);
|
|
2162
2434
|
}
|
|
2163
2435
|
}
|
|
2164
2436
|
}
|
|
@@ -2174,7 +2446,7 @@ Write only the post content, nothing else. Keep it concise and natural.`;
|
|
|
2174
2446
|
await this.scheduledPost("twitter");
|
|
2175
2447
|
}
|
|
2176
2448
|
});
|
|
2177
|
-
|
|
2449
|
+
logger6.info(`Scheduler: Twitter posting every ${formatInterval(intervalMs)}`);
|
|
2178
2450
|
}
|
|
2179
2451
|
}
|
|
2180
2452
|
}
|
|
@@ -2190,7 +2462,7 @@ Write only the post content, nothing else. Keep it concise and natural.`;
|
|
|
2190
2462
|
await this.executeScheduledTask(task);
|
|
2191
2463
|
}
|
|
2192
2464
|
});
|
|
2193
|
-
|
|
2465
|
+
logger6.info(`Scheduler: "${task.name}" every ${formatInterval(task.intervalMs)}`);
|
|
2194
2466
|
}
|
|
2195
2467
|
}
|
|
2196
2468
|
async scheduledPost(platform) {
|
|
@@ -2206,15 +2478,15 @@ Write only the post content, nothing else. Keep it concise and natural.`;
|
|
|
2206
2478
|
maxTokens: 280
|
|
2207
2479
|
});
|
|
2208
2480
|
const result = await adapter.post(content.trim());
|
|
2209
|
-
|
|
2481
|
+
logger6.info(`Scheduled post: ${platform} SUCCESS \u2014 id=${result.id}`);
|
|
2210
2482
|
} catch (error) {
|
|
2211
|
-
|
|
2483
|
+
logger6.error(`Scheduled post: ${platform} FAILED \u2014 ${error.message || error}`);
|
|
2212
2484
|
this.logPlatformError(platform, error);
|
|
2213
2485
|
}
|
|
2214
2486
|
}
|
|
2215
2487
|
async executeScheduledTask(task) {
|
|
2216
2488
|
try {
|
|
2217
|
-
|
|
2489
|
+
logger6.info(`Scheduled task: Running "${task.name}"`);
|
|
2218
2490
|
const prompt = `You are ${this.config.name}, an autonomous agent. Execute the following scheduled task.
|
|
2219
2491
|
|
|
2220
2492
|
Task: ${task.name}
|
|
@@ -2239,74 +2511,74 @@ Decide what action to take. Respond with JSON:
|
|
|
2239
2511
|
{ systemPrompt: this.systemPrompt, temperature: this.config.llm.temperature }
|
|
2240
2512
|
);
|
|
2241
2513
|
const result = await this.act(decision.action, decision.parameters);
|
|
2242
|
-
|
|
2514
|
+
logger6.info(`Scheduled task: "${task.name}" completed \u2014 action=${decision.action}, success=${result.success}`);
|
|
2243
2515
|
} catch (error) {
|
|
2244
|
-
|
|
2516
|
+
logger6.error(`Scheduled task: "${task.name}" FAILED \u2014 ${error.message || error}`);
|
|
2245
2517
|
}
|
|
2246
2518
|
}
|
|
2247
2519
|
logPlatformError(platform, error) {
|
|
2248
2520
|
if (!error.response) {
|
|
2249
2521
|
if (error.code === "ENOTFOUND") {
|
|
2250
|
-
|
|
2522
|
+
logger6.error(` ${platform}: DNS lookup failed \u2014 check the base URL.`);
|
|
2251
2523
|
} else if (error.code === "ECONNREFUSED") {
|
|
2252
|
-
|
|
2524
|
+
logger6.error(` ${platform}: Connection refused \u2014 is the server running?`);
|
|
2253
2525
|
} else if (error.code === "ETIMEDOUT" || error.code === "ECONNABORTED") {
|
|
2254
|
-
|
|
2526
|
+
logger6.error(` ${platform}: Request timed out.`);
|
|
2255
2527
|
} else {
|
|
2256
|
-
|
|
2528
|
+
logger6.error(` ${platform}: Network error (${error.code || "unknown"})`);
|
|
2257
2529
|
}
|
|
2258
2530
|
return;
|
|
2259
2531
|
}
|
|
2260
2532
|
const status = error.response.status;
|
|
2261
2533
|
const data = error.response.data;
|
|
2262
|
-
|
|
2534
|
+
logger6.error(` ${platform}: HTTP ${status}`);
|
|
2263
2535
|
if (data) {
|
|
2264
|
-
if (data.error)
|
|
2265
|
-
if (data.hint)
|
|
2266
|
-
if (!data.error && !data.hint)
|
|
2536
|
+
if (data.error) logger6.error(` ${platform}: API error: ${data.error}`);
|
|
2537
|
+
if (data.hint) logger6.error(` ${platform}: API hint: ${data.hint}`);
|
|
2538
|
+
if (!data.error && !data.hint) logger6.error(` ${platform}: Response: ${JSON.stringify(data)}`);
|
|
2267
2539
|
}
|
|
2268
2540
|
if (status === 401) {
|
|
2269
|
-
|
|
2541
|
+
logger6.error(` ${platform}: Your API key was rejected. Verify it is correct and the agent is claimed.`);
|
|
2270
2542
|
} else if (status === 403) {
|
|
2271
|
-
|
|
2543
|
+
logger6.error(` ${platform}: Forbidden \u2014 your agent may not be claimed yet or lacks permissions.`);
|
|
2272
2544
|
} else if (status === 429) {
|
|
2273
2545
|
const retryMin = data?.retry_after_minutes;
|
|
2274
2546
|
const retrySec = data?.retry_after_seconds;
|
|
2275
2547
|
if (retryMin) {
|
|
2276
|
-
|
|
2548
|
+
logger6.error(` ${platform}: Rate limited \u2014 try again in ${retryMin} minute(s).`);
|
|
2277
2549
|
} else if (retrySec) {
|
|
2278
|
-
|
|
2550
|
+
logger6.error(` ${platform}: Rate limited \u2014 try again in ${retrySec} second(s).`);
|
|
2279
2551
|
} else {
|
|
2280
|
-
|
|
2552
|
+
logger6.error(` ${platform}: Rate limited \u2014 wait before retrying.`);
|
|
2281
2553
|
}
|
|
2282
2554
|
} else if (status === 404) {
|
|
2283
|
-
|
|
2555
|
+
logger6.error(` ${platform}: Endpoint not found \u2014 check the base URL.`);
|
|
2284
2556
|
} else if (status >= 500) {
|
|
2285
|
-
|
|
2557
|
+
logger6.error(` ${platform}: Server error \u2014 the platform may be temporarily down.`);
|
|
2286
2558
|
}
|
|
2287
2559
|
}
|
|
2288
2560
|
async autoJoinWorld() {
|
|
2289
2561
|
const worldUrl = this.config.world.url;
|
|
2290
|
-
|
|
2562
|
+
logger6.info(`Auto-joining world: ${worldUrl}`);
|
|
2291
2563
|
try {
|
|
2292
2564
|
const result = await this.act("join_world", {
|
|
2293
2565
|
worldUrl,
|
|
2294
2566
|
walletAddress: this.config.world.walletAddress
|
|
2295
2567
|
});
|
|
2296
2568
|
if (result.success) {
|
|
2297
|
-
|
|
2569
|
+
logger6.info(`Successfully joined world: ${worldUrl}`);
|
|
2298
2570
|
} else {
|
|
2299
|
-
|
|
2571
|
+
logger6.warn(`Failed to join world: ${result.error}`);
|
|
2300
2572
|
}
|
|
2301
2573
|
} catch (error) {
|
|
2302
|
-
|
|
2574
|
+
logger6.warn(`Auto-join world failed: ${error?.message || error}`);
|
|
2303
2575
|
}
|
|
2304
2576
|
}
|
|
2305
2577
|
startAutonomousLoop() {
|
|
2306
2578
|
const actionsPerHour = typeof this.config.behaviors.actionsPerHour === "function" ? this.config.behaviors.actionsPerHour({}) : this.config.behaviors.actionsPerHour || 5;
|
|
2307
2579
|
const intervalMs = Math.floor(36e5 / actionsPerHour);
|
|
2308
2580
|
this.tickTimer = setInterval(() => this.tick(), intervalMs);
|
|
2309
|
-
|
|
2581
|
+
logger6.info(`Autonomous loop started: ~${actionsPerHour} actions/hour (every ${intervalMs}ms)`);
|
|
2310
2582
|
}
|
|
2311
2583
|
isSleeping() {
|
|
2312
2584
|
const schedule = this.config.behaviors.sleepSchedule;
|
|
@@ -2341,7 +2613,7 @@ Decide what action to take. Respond with JSON:
|
|
|
2341
2613
|
await axios2.post(hook, { event, data: args });
|
|
2342
2614
|
}
|
|
2343
2615
|
} catch (error) {
|
|
2344
|
-
|
|
2616
|
+
logger6.error(`Webhook ${event} failed: ${error}`);
|
|
2345
2617
|
}
|
|
2346
2618
|
}
|
|
2347
2619
|
};
|
|
@@ -2481,10 +2753,18 @@ var MarkdownParser = class {
|
|
|
2481
2753
|
const fields = this.parseKeyValueLines(section.content);
|
|
2482
2754
|
const url = fields["url"];
|
|
2483
2755
|
if (!url) return void 0;
|
|
2756
|
+
let privateKey;
|
|
2757
|
+
const pkField = fields["wallet_private_key"];
|
|
2758
|
+
if (pkField === "env") {
|
|
2759
|
+
privateKey = process.env.AGENT_WALLET_PRIVATE_KEY;
|
|
2760
|
+
} else if (pkField && pkField.startsWith("0x")) {
|
|
2761
|
+
privateKey = pkField;
|
|
2762
|
+
}
|
|
2484
2763
|
return {
|
|
2485
2764
|
url,
|
|
2486
2765
|
autoJoin: fields["auto_join"] !== "false",
|
|
2487
|
-
...fields["wallet_address"] ? { walletAddress: fields["wallet_address"] } : {}
|
|
2766
|
+
...fields["wallet_address"] ? { walletAddress: fields["wallet_address"] } : {},
|
|
2767
|
+
...privateKey ? { privateKey } : {}
|
|
2488
2768
|
};
|
|
2489
2769
|
}
|
|
2490
2770
|
parseSleepSchedule(value) {
|
|
@@ -2659,7 +2939,8 @@ var ConfigLoader = class {
|
|
|
2659
2939
|
};
|
|
2660
2940
|
|
|
2661
2941
|
// src/memory/longterm.ts
|
|
2662
|
-
|
|
2942
|
+
init_logger();
|
|
2943
|
+
var logger7 = createLogger("LongTermMemory");
|
|
2663
2944
|
var LongTermMemory = class extends Memory {
|
|
2664
2945
|
redisConfig;
|
|
2665
2946
|
postgresConfig;
|
|
@@ -2835,9 +3116,9 @@ var LongTermMemory = class extends Memory {
|
|
|
2835
3116
|
try {
|
|
2836
3117
|
const { default: Redis } = await import("ioredis");
|
|
2837
3118
|
this.redis = new Redis(this.redisConfig.url);
|
|
2838
|
-
|
|
3119
|
+
logger7.info("Redis connection established");
|
|
2839
3120
|
} catch (error) {
|
|
2840
|
-
|
|
3121
|
+
logger7.error(`Failed to connect to Redis: ${error}`);
|
|
2841
3122
|
throw error;
|
|
2842
3123
|
}
|
|
2843
3124
|
}
|
|
@@ -2850,9 +3131,9 @@ var LongTermMemory = class extends Memory {
|
|
|
2850
3131
|
connectionString: this.postgresConfig.url
|
|
2851
3132
|
});
|
|
2852
3133
|
await this.pg.query("SELECT 1");
|
|
2853
|
-
|
|
3134
|
+
logger7.info("Postgres connection established");
|
|
2854
3135
|
} catch (error) {
|
|
2855
|
-
|
|
3136
|
+
logger7.error(`Failed to connect to Postgres: ${error}`);
|
|
2856
3137
|
throw error;
|
|
2857
3138
|
}
|
|
2858
3139
|
}
|
|
@@ -2994,13 +3275,14 @@ function createRoutes(agent) {
|
|
|
2994
3275
|
}
|
|
2995
3276
|
|
|
2996
3277
|
// src/server/middleware.ts
|
|
2997
|
-
|
|
3278
|
+
init_logger();
|
|
3279
|
+
var logger8 = createLogger("Server");
|
|
2998
3280
|
function requestLogger(req, _res, next) {
|
|
2999
|
-
|
|
3281
|
+
logger8.debug(`${req.method} ${req.path}`);
|
|
3000
3282
|
next();
|
|
3001
3283
|
}
|
|
3002
3284
|
function errorHandler(err, _req, res, _next) {
|
|
3003
|
-
|
|
3285
|
+
logger8.error(`Server error: ${err.message}`);
|
|
3004
3286
|
res.status(500).json({ error: err.message });
|
|
3005
3287
|
}
|
|
3006
3288
|
function authMiddleware(req, res, next) {
|
|
@@ -3017,8 +3299,12 @@ function authMiddleware(req, res, next) {
|
|
|
3017
3299
|
next();
|
|
3018
3300
|
}
|
|
3019
3301
|
|
|
3302
|
+
// src/server/app.ts
|
|
3303
|
+
init_logger();
|
|
3304
|
+
|
|
3020
3305
|
// src/a2a/AgentCardBuilder.ts
|
|
3021
|
-
|
|
3306
|
+
init_logger();
|
|
3307
|
+
var logger9 = createLogger("AgentCardBuilder");
|
|
3022
3308
|
var AgentCardBuilder = class {
|
|
3023
3309
|
/**
|
|
3024
3310
|
* Creates an A2A AgentCard from Moltium configuration.
|
|
@@ -3040,7 +3326,7 @@ var AgentCardBuilder = class {
|
|
|
3040
3326
|
name: config.name,
|
|
3041
3327
|
description: config.personality.bio || `${config.name} - An autonomous AI agent`,
|
|
3042
3328
|
protocolVersion: "0.3.0",
|
|
3043
|
-
version: "0.1.
|
|
3329
|
+
version: "0.1.30",
|
|
3044
3330
|
url: `${baseUrl}/a2a/jsonrpc`,
|
|
3045
3331
|
skills,
|
|
3046
3332
|
capabilities,
|
|
@@ -3051,7 +3337,7 @@ var AgentCardBuilder = class {
|
|
|
3051
3337
|
{ url: `${baseUrl}/a2a/rest`, transport: "HTTP+JSON" }
|
|
3052
3338
|
]
|
|
3053
3339
|
};
|
|
3054
|
-
|
|
3340
|
+
logger9.debug("Built A2A AgentCard", {
|
|
3055
3341
|
name: agentCard.name,
|
|
3056
3342
|
skillCount: skills.length,
|
|
3057
3343
|
baseUrl
|
|
@@ -3133,8 +3419,9 @@ var AgentCardBuilder = class {
|
|
|
3133
3419
|
};
|
|
3134
3420
|
|
|
3135
3421
|
// src/a2a/MoltiumExecutor.ts
|
|
3422
|
+
init_logger();
|
|
3136
3423
|
var import_uuid2 = require("uuid");
|
|
3137
|
-
var
|
|
3424
|
+
var logger10 = createLogger("MoltiumExecutor");
|
|
3138
3425
|
var MoltiumExecutor = class {
|
|
3139
3426
|
agent;
|
|
3140
3427
|
cancelledTasks = /* @__PURE__ */ new Set();
|
|
@@ -3148,7 +3435,7 @@ var MoltiumExecutor = class {
|
|
|
3148
3435
|
async execute(requestContext, eventBus) {
|
|
3149
3436
|
const { taskId, contextId, userMessage, task } = requestContext;
|
|
3150
3437
|
try {
|
|
3151
|
-
|
|
3438
|
+
logger10.info(`[A2A] Executing request for task ${taskId}`);
|
|
3152
3439
|
if (!task) {
|
|
3153
3440
|
const initialTask = {
|
|
3154
3441
|
kind: "task",
|
|
@@ -3186,9 +3473,9 @@ var MoltiumExecutor = class {
|
|
|
3186
3473
|
}
|
|
3187
3474
|
this.publishStatusUpdate(taskId, contextId, "completed", eventBus, true);
|
|
3188
3475
|
eventBus.finished();
|
|
3189
|
-
|
|
3476
|
+
logger10.info(`[A2A] Task ${taskId} completed successfully`);
|
|
3190
3477
|
} catch (error) {
|
|
3191
|
-
|
|
3478
|
+
logger10.error(`[A2A] Task ${taskId} failed`, {
|
|
3192
3479
|
error: error instanceof Error ? error.message : String(error)
|
|
3193
3480
|
});
|
|
3194
3481
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -3203,7 +3490,7 @@ var MoltiumExecutor = class {
|
|
|
3203
3490
|
* Handles task cancellation requests.
|
|
3204
3491
|
*/
|
|
3205
3492
|
async cancelTask(taskId, eventBus) {
|
|
3206
|
-
|
|
3493
|
+
logger10.info(`[A2A] Cancellation requested for task ${taskId}`);
|
|
3207
3494
|
this.cancelledTasks.add(taskId);
|
|
3208
3495
|
}
|
|
3209
3496
|
/**
|
|
@@ -3365,7 +3652,7 @@ var MoltiumExecutor = class {
|
|
|
3365
3652
|
* Publishes a cancellation status.
|
|
3366
3653
|
*/
|
|
3367
3654
|
publishCancellation(taskId, contextId, eventBus) {
|
|
3368
|
-
|
|
3655
|
+
logger10.info(`[A2A] Publishing cancellation for task ${taskId}`);
|
|
3369
3656
|
this.publishStatusUpdate(taskId, contextId, "canceled", eventBus, true);
|
|
3370
3657
|
eventBus.finished();
|
|
3371
3658
|
this.cancelledTasks.delete(taskId);
|
|
@@ -3374,7 +3661,8 @@ var MoltiumExecutor = class {
|
|
|
3374
3661
|
|
|
3375
3662
|
// src/a2a/integration.ts
|
|
3376
3663
|
var import_server = require("@a2a-js/sdk/server");
|
|
3377
|
-
|
|
3664
|
+
init_logger();
|
|
3665
|
+
var logger11 = createLogger("A2AIntegration");
|
|
3378
3666
|
var A2AIntegration = class {
|
|
3379
3667
|
agent;
|
|
3380
3668
|
agentCard;
|
|
@@ -3389,7 +3677,7 @@ var A2AIntegration = class {
|
|
|
3389
3677
|
new import_server.InMemoryTaskStore(),
|
|
3390
3678
|
this.moltiumExecutor
|
|
3391
3679
|
);
|
|
3392
|
-
|
|
3680
|
+
logger11.info("A2A integration initialized", {
|
|
3393
3681
|
agentName: agent.name,
|
|
3394
3682
|
baseUrl: options.a2aConfig.baseUrl
|
|
3395
3683
|
});
|
|
@@ -3411,7 +3699,7 @@ var A2AIntegration = class {
|
|
|
3411
3699
|
const response = await jsonRpcHandler.handle(req.body);
|
|
3412
3700
|
res.json(response);
|
|
3413
3701
|
} catch (error) {
|
|
3414
|
-
|
|
3702
|
+
logger11.error("JSON-RPC error:", error);
|
|
3415
3703
|
res.status(500).json({
|
|
3416
3704
|
jsonrpc: "2.0",
|
|
3417
3705
|
error: {
|
|
@@ -3442,7 +3730,7 @@ var A2AIntegration = class {
|
|
|
3442
3730
|
new import_server.InMemoryTaskStore(),
|
|
3443
3731
|
this.moltiumExecutor
|
|
3444
3732
|
);
|
|
3445
|
-
|
|
3733
|
+
logger11.info("A2A agent card updated with runtime info", {
|
|
3446
3734
|
host: actualHost,
|
|
3447
3735
|
port: actualPort,
|
|
3448
3736
|
url: this.agentCard.url
|
|
@@ -3460,10 +3748,10 @@ var A2AIntegration = class {
|
|
|
3460
3748
|
logEndpoints(host, port) {
|
|
3461
3749
|
const protocol = host === "localhost" || host === "127.0.0.1" ? "http" : "https";
|
|
3462
3750
|
const baseUrl = `${protocol}://${host}:${port}`;
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3751
|
+
logger11.info("A2A endpoints available:");
|
|
3752
|
+
logger11.info(` Agent Card: ${baseUrl}/.well-known/agent.json`);
|
|
3753
|
+
logger11.info(` JSON-RPC: ${baseUrl}/a2a/jsonrpc`);
|
|
3754
|
+
logger11.info(` HTTP+JSON: ${baseUrl}/a2a/rest`);
|
|
3467
3755
|
}
|
|
3468
3756
|
};
|
|
3469
3757
|
function createA2AIntegration(agent, options = {}) {
|
|
@@ -3478,7 +3766,7 @@ function createA2AIntegration(agent, options = {}) {
|
|
|
3478
3766
|
}
|
|
3479
3767
|
|
|
3480
3768
|
// src/server/app.ts
|
|
3481
|
-
var
|
|
3769
|
+
var logger12 = createLogger("Server");
|
|
3482
3770
|
var AGENT_CARD_PATH = ".well-known/agent.json";
|
|
3483
3771
|
function createApp(agent, options = {}) {
|
|
3484
3772
|
const app = (0, import_express2.default)();
|
|
@@ -3507,7 +3795,7 @@ function createApp(agent, options = {}) {
|
|
|
3507
3795
|
app.use("/.well-known/agent-card.json", handlers.agentCard);
|
|
3508
3796
|
app.use("/a2a/jsonrpc", handlers.jsonRpc);
|
|
3509
3797
|
app.use("/a2a/rest", handlers.rest);
|
|
3510
|
-
|
|
3798
|
+
logger12.info("A2A protocol endpoints enabled");
|
|
3511
3799
|
}
|
|
3512
3800
|
app.use(errorHandler);
|
|
3513
3801
|
return app;
|
|
@@ -3518,28 +3806,34 @@ async function startServer(agent, options = {}) {
|
|
|
3518
3806
|
const app = createApp(agent, options);
|
|
3519
3807
|
await new Promise((resolve2) => {
|
|
3520
3808
|
app.listen(port, host, () => {
|
|
3521
|
-
|
|
3809
|
+
logger12.info(`Agent "${agent.name}" running at http://${host}:${port}`);
|
|
3522
3810
|
if (options.enableA2A !== false) {
|
|
3523
3811
|
const logHost = host === "0.0.0.0" ? "localhost" : host;
|
|
3524
3812
|
const protocol = logHost === "localhost" || logHost === "127.0.0.1" ? "http" : "https";
|
|
3525
3813
|
const baseUrl = `${protocol}://${logHost}:${port}`;
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3814
|
+
logger12.info("A2A Protocol Endpoints:");
|
|
3815
|
+
logger12.info(` Agent Card: ${baseUrl}/.well-known/agent.json`);
|
|
3816
|
+
logger12.info(` JSON-RPC: ${baseUrl}/a2a/jsonrpc`);
|
|
3817
|
+
logger12.info(` HTTP+JSON: ${baseUrl}/a2a/rest`);
|
|
3530
3818
|
}
|
|
3531
3819
|
resolve2();
|
|
3532
3820
|
});
|
|
3533
3821
|
});
|
|
3534
3822
|
await agent.start();
|
|
3535
3823
|
const shutdown = async () => {
|
|
3536
|
-
|
|
3824
|
+
logger12.info("Received shutdown signal");
|
|
3537
3825
|
await agent.stop();
|
|
3538
3826
|
process.exit(0);
|
|
3539
3827
|
};
|
|
3540
3828
|
process.on("SIGINT", shutdown);
|
|
3541
3829
|
process.on("SIGTERM", shutdown);
|
|
3542
3830
|
}
|
|
3831
|
+
|
|
3832
|
+
// src/wallet/index.ts
|
|
3833
|
+
init_AgentWallet();
|
|
3834
|
+
|
|
3835
|
+
// src/index.ts
|
|
3836
|
+
init_logger();
|
|
3543
3837
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3544
3838
|
0 && (module.exports = {
|
|
3545
3839
|
A2AClient,
|
|
@@ -3548,6 +3842,7 @@ async function startServer(agent, options = {}) {
|
|
|
3548
3842
|
ActionRegistry,
|
|
3549
3843
|
Agent,
|
|
3550
3844
|
AgentCardBuilder,
|
|
3845
|
+
AgentWallet,
|
|
3551
3846
|
AnthropicProvider,
|
|
3552
3847
|
ConfigLoader,
|
|
3553
3848
|
LLMProvider,
|