@moltium/core 0.1.28 → 0.1.30
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 +415 -129
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +192 -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,10 +687,12 @@ var moltbookActions = [
|
|
|
497
687
|
];
|
|
498
688
|
|
|
499
689
|
// src/actions/built-in/world.ts
|
|
690
|
+
init_logger();
|
|
691
|
+
var logger4 = createLogger("WorldActions");
|
|
500
692
|
function createJoinWorldAction(config) {
|
|
501
693
|
return {
|
|
502
694
|
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.`,
|
|
695
|
+
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
696
|
async execute(context) {
|
|
505
697
|
const { parameters, agent } = context;
|
|
506
698
|
const worldUrl = parameters.worldUrl || config?.defaultWorldUrl;
|
|
@@ -510,11 +702,45 @@ function createJoinWorldAction(config) {
|
|
|
510
702
|
const agentPort = process.env.PORT || "3000";
|
|
511
703
|
const agentHost = process.env.HOST || "localhost";
|
|
512
704
|
const agentUrl = `http://${agentHost}:${agentPort}`;
|
|
705
|
+
const walletAddress = parameters.walletAddress || agent?.config?.world?.walletAddress;
|
|
513
706
|
try {
|
|
514
707
|
const { default: axios2 } = await import("axios");
|
|
708
|
+
let paymentTxHash;
|
|
709
|
+
try {
|
|
710
|
+
const infoRes = await axios2.get(`${worldUrl}/world/join-info`, { timeout: 5e3 });
|
|
711
|
+
const joinInfo = infoRes.data;
|
|
712
|
+
if (joinInfo.requiresPayment && joinInfo.entryFee && joinInfo.entryFee !== "0") {
|
|
713
|
+
const privateKey = agent?.config?.world?.privateKey;
|
|
714
|
+
if (!privateKey) {
|
|
715
|
+
return {
|
|
716
|
+
success: false,
|
|
717
|
+
error: "World requires entry fee but agent has no wallet private key configured. Set AGENT_WALLET_PRIVATE_KEY in your .env file."
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
logger4.info(`World requires entry fee: ${joinInfo.entryFee} wei`);
|
|
721
|
+
const { AgentWallet: AgentWallet2 } = await Promise.resolve().then(() => (init_AgentWallet(), AgentWallet_exports));
|
|
722
|
+
const wallet = new AgentWallet2(privateKey, joinInfo.rpcUrl);
|
|
723
|
+
const balance = await wallet.getBalance();
|
|
724
|
+
if (BigInt(balance) < BigInt(joinInfo.entryFee)) {
|
|
725
|
+
const { formatEther } = await import("ethers");
|
|
726
|
+
return {
|
|
727
|
+
success: false,
|
|
728
|
+
error: `Insufficient balance to pay entry fee. Need ${formatEther(joinInfo.entryFee)} MON, have ${formatEther(balance)} MON`
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
logger4.info(`Paying entry fee to ${joinInfo.paymentAddress}...`);
|
|
732
|
+
paymentTxHash = await wallet.sendPayment(joinInfo.paymentAddress, joinInfo.entryFee);
|
|
733
|
+
logger4.info(`Entry fee paid. TX: ${paymentTxHash}`);
|
|
734
|
+
}
|
|
735
|
+
} catch (infoError) {
|
|
736
|
+
if (infoError?.response?.status !== 404) {
|
|
737
|
+
logger4.debug(`Could not query join-info: ${infoError.message}`);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
515
740
|
const response = await axios2.post(`${worldUrl}/world/join`, {
|
|
516
741
|
agentUrl,
|
|
517
|
-
walletAddress
|
|
742
|
+
walletAddress,
|
|
743
|
+
paymentTxHash
|
|
518
744
|
}, { timeout: 1e4 });
|
|
519
745
|
return {
|
|
520
746
|
success: true,
|
|
@@ -663,17 +889,39 @@ ${config.llm.systemPrompt}`);
|
|
|
663
889
|
}
|
|
664
890
|
function buildDecisionPrompt(context, availableActions) {
|
|
665
891
|
const actionList = availableActions.map((a) => `- ${a.name}: ${a.description}`).join("\n");
|
|
892
|
+
const actionNames = availableActions.map((a) => a.name);
|
|
893
|
+
const hasWorldActions = actionNames.some(
|
|
894
|
+
(n) => ["send_world_message", "query_world", "join_world", "leave_world"].includes(n)
|
|
895
|
+
);
|
|
896
|
+
const hasSocialActions = actionNames.some(
|
|
897
|
+
(n) => ["post_social_update", "respond_to_mention"].includes(n)
|
|
898
|
+
);
|
|
666
899
|
const recent = context.recentActions || [];
|
|
667
900
|
const recentNames = recent.map((r) => r.action);
|
|
668
901
|
const lastAction = recentNames.length > 0 ? recentNames[recentNames.length - 1] : "none";
|
|
669
902
|
let varietyHint = "";
|
|
670
903
|
if (recentNames.length > 0) {
|
|
904
|
+
const suggestions = [];
|
|
905
|
+
if (hasWorldActions) {
|
|
906
|
+
suggestions.push("querying the world for agents", "sending messages to other agents", "responding to conversations");
|
|
907
|
+
}
|
|
908
|
+
if (hasSocialActions) {
|
|
909
|
+
suggestions.push("posting content", "responding to mentions");
|
|
910
|
+
}
|
|
911
|
+
const suggestStr = suggestions.length > 0 ? `
|
|
912
|
+
Vary between: ${suggestions.join(", ")}.` : "";
|
|
671
913
|
varietyHint = `
|
|
672
914
|
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
|
-
|
|
915
|
+
IMPORTANT: Do NOT repeat "${lastAction}" again. Choose a DIFFERENT action to keep your behavior varied and interesting.` + suggestStr;
|
|
916
|
+
}
|
|
917
|
+
let preamble = "You are an autonomous AI agent.";
|
|
918
|
+
if (hasWorldActions) {
|
|
919
|
+
preamble += " You are connected to a world with other agents.";
|
|
920
|
+
preamble += " Use send_world_message to communicate with other agents (provide toAgentUrl and message parameters).";
|
|
921
|
+
preamble += " Use query_world to discover agents and world state.";
|
|
922
|
+
preamble += ' IMPORTANT: Only use actions from the "Available actions" list below. Do NOT invent action names.';
|
|
675
923
|
}
|
|
676
|
-
return
|
|
924
|
+
return `${preamble}
|
|
677
925
|
Decide what action to take next based on the current context and your personality.
|
|
678
926
|
|
|
679
927
|
Available actions:
|
|
@@ -684,7 +932,7 @@ ${JSON.stringify(context, null, 2)}
|
|
|
684
932
|
${varietyHint}
|
|
685
933
|
|
|
686
934
|
Think about what would be most natural and valuable right now.
|
|
687
|
-
|
|
935
|
+
Choose ONLY from the available actions listed above.
|
|
688
936
|
|
|
689
937
|
Respond with a JSON object:
|
|
690
938
|
{
|
|
@@ -711,7 +959,8 @@ Execute these instructions step by step and return the result as a JSON object:
|
|
|
711
959
|
}
|
|
712
960
|
|
|
713
961
|
// src/actions/interpreter.ts
|
|
714
|
-
|
|
962
|
+
init_logger();
|
|
963
|
+
var logger5 = createLogger("MarkdownInterpreter");
|
|
715
964
|
var LLMInterpretationError = class extends Error {
|
|
716
965
|
constructor(message) {
|
|
717
966
|
super(message);
|
|
@@ -723,7 +972,7 @@ function createMarkdownAction(name, description, llmProvider) {
|
|
|
723
972
|
name,
|
|
724
973
|
description,
|
|
725
974
|
execute: async (context) => {
|
|
726
|
-
|
|
975
|
+
logger5.info(`Interpreting markdown skill: ${name}`);
|
|
727
976
|
const prompt = buildSkillPrompt(name, description, context.parameters);
|
|
728
977
|
try {
|
|
729
978
|
const response = await llmProvider.generateText(prompt, {
|
|
@@ -744,7 +993,7 @@ function createMarkdownAction(name, description, llmProvider) {
|
|
|
744
993
|
} catch (error) {
|
|
745
994
|
if (error instanceof LLMInterpretationError) throw error;
|
|
746
995
|
const message = error instanceof Error ? error.message : String(error);
|
|
747
|
-
|
|
996
|
+
logger5.error(`Markdown skill interpretation failed: ${name}`, { error: message });
|
|
748
997
|
throw new LLMInterpretationError(
|
|
749
998
|
`Failed to interpret skill "${name}": ${message}`
|
|
750
999
|
);
|
|
@@ -1524,6 +1773,9 @@ var TwitterAdapter = class extends SocialAdapter {
|
|
|
1524
1773
|
}
|
|
1525
1774
|
};
|
|
1526
1775
|
|
|
1776
|
+
// src/agent/Agent.ts
|
|
1777
|
+
init_logger();
|
|
1778
|
+
|
|
1527
1779
|
// src/a2a/client.ts
|
|
1528
1780
|
var import_client = require("@a2a-js/sdk/client");
|
|
1529
1781
|
var import_uuid = require("uuid");
|
|
@@ -1697,7 +1949,7 @@ function createMultipleA2AActions(configs) {
|
|
|
1697
1949
|
}
|
|
1698
1950
|
|
|
1699
1951
|
// src/agent/Agent.ts
|
|
1700
|
-
var
|
|
1952
|
+
var logger6 = createLogger("Agent");
|
|
1701
1953
|
function parsePostFrequency(freq) {
|
|
1702
1954
|
const lower = freq.toLowerCase().trim();
|
|
1703
1955
|
if (lower === "realtime") return 5 * 60 * 1e3;
|
|
@@ -1793,7 +2045,17 @@ var Agent = class {
|
|
|
1793
2045
|
// ── Lifecycle ──
|
|
1794
2046
|
async init() {
|
|
1795
2047
|
this.state = "initializing";
|
|
1796
|
-
|
|
2048
|
+
logger6.info(`Initializing agent: ${this.config.name}`);
|
|
2049
|
+
if (this.config.world?.privateKey && !this.config.world.walletAddress) {
|
|
2050
|
+
try {
|
|
2051
|
+
const { AgentWallet: AgentWallet2 } = await Promise.resolve().then(() => (init_AgentWallet(), AgentWallet_exports));
|
|
2052
|
+
const wallet = new AgentWallet2(this.config.world.privateKey);
|
|
2053
|
+
this.config.world.walletAddress = await wallet.getAddressAsync();
|
|
2054
|
+
logger6.info(`Wallet address derived: ${this.config.world.walletAddress}`);
|
|
2055
|
+
} catch (error) {
|
|
2056
|
+
logger6.warn(`Failed to derive wallet address: ${error.message}`);
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
1797
2059
|
this.initLLM();
|
|
1798
2060
|
this.registerActions();
|
|
1799
2061
|
await this.initSocialAdapters();
|
|
@@ -1802,7 +2064,7 @@ var Agent = class {
|
|
|
1802
2064
|
await this.hooks.onInit(this);
|
|
1803
2065
|
}
|
|
1804
2066
|
await this.postStartupMessages();
|
|
1805
|
-
|
|
2067
|
+
logger6.info(`Agent initialized: ${this.config.name}`);
|
|
1806
2068
|
}
|
|
1807
2069
|
async start() {
|
|
1808
2070
|
if (this.state !== "initializing" && this.state !== "idle") {
|
|
@@ -1812,7 +2074,7 @@ var Agent = class {
|
|
|
1812
2074
|
await this.init();
|
|
1813
2075
|
}
|
|
1814
2076
|
this.state = "running";
|
|
1815
|
-
|
|
2077
|
+
logger6.info(`Agent started: ${this.config.name}`);
|
|
1816
2078
|
if (this.hooks.onStart) {
|
|
1817
2079
|
await this.hooks.onStart(this);
|
|
1818
2080
|
}
|
|
@@ -1826,7 +2088,7 @@ var Agent = class {
|
|
|
1826
2088
|
}
|
|
1827
2089
|
async stop() {
|
|
1828
2090
|
this.state = "stopping";
|
|
1829
|
-
|
|
2091
|
+
logger6.info(`Stopping agent: ${this.config.name}`);
|
|
1830
2092
|
if (this.tickTimer) {
|
|
1831
2093
|
clearInterval(this.tickTimer);
|
|
1832
2094
|
this.tickTimer = void 0;
|
|
@@ -1839,7 +2101,7 @@ var Agent = class {
|
|
|
1839
2101
|
await this.hooks.onShutdown(this);
|
|
1840
2102
|
}
|
|
1841
2103
|
this.state = "stopped";
|
|
1842
|
-
|
|
2104
|
+
logger6.info(`Agent stopped: ${this.config.name}`);
|
|
1843
2105
|
}
|
|
1844
2106
|
// ── Decision Loop ──
|
|
1845
2107
|
async think() {
|
|
@@ -1859,7 +2121,7 @@ var Agent = class {
|
|
|
1859
2121
|
},
|
|
1860
2122
|
{ systemPrompt: this.systemPrompt, temperature: this.config.llm.temperature }
|
|
1861
2123
|
);
|
|
1862
|
-
|
|
2124
|
+
logger6.debug(`Decision: ${decision.action} \u2014 ${decision.reasoning}`);
|
|
1863
2125
|
return decision;
|
|
1864
2126
|
}
|
|
1865
2127
|
async act(actionName, parameters = {}) {
|
|
@@ -1882,17 +2144,17 @@ var Agent = class {
|
|
|
1882
2144
|
await this.hooks.onTick(this);
|
|
1883
2145
|
}
|
|
1884
2146
|
if (this.isSleeping()) {
|
|
1885
|
-
|
|
2147
|
+
logger6.info(`Tick #${this.tickCount}: Sleeping \u2014 skipped`);
|
|
1886
2148
|
return;
|
|
1887
2149
|
}
|
|
1888
|
-
|
|
2150
|
+
logger6.info(`Tick #${this.tickCount}: Thinking...`);
|
|
1889
2151
|
const decision = await this.think();
|
|
1890
|
-
|
|
2152
|
+
logger6.info(`Tick #${this.tickCount}: Decision \u2192 ${decision.action} | Reasoning: ${decision.reasoning}`);
|
|
1891
2153
|
if (decision.parameters && Object.keys(decision.parameters).length > 0) {
|
|
1892
|
-
|
|
2154
|
+
logger6.info(`Tick #${this.tickCount}: Parameters \u2192 ${JSON.stringify(decision.parameters)}`);
|
|
1893
2155
|
}
|
|
1894
2156
|
const result = await this.act(decision.action, decision.parameters);
|
|
1895
|
-
|
|
2157
|
+
logger6.info(`Tick #${this.tickCount}: Result \u2192 success=${result.success}${result.data ? ` data=${JSON.stringify(result.data).slice(0, 200)}` : ""}`);
|
|
1896
2158
|
this.recentActions.push({
|
|
1897
2159
|
action: decision.action,
|
|
1898
2160
|
reasoning: decision.reasoning,
|
|
@@ -1910,7 +2172,7 @@ var Agent = class {
|
|
|
1910
2172
|
await this.fireWebhook("onAction", decision, result);
|
|
1911
2173
|
}
|
|
1912
2174
|
} catch (error) {
|
|
1913
|
-
|
|
2175
|
+
logger6.error(`Tick #${this.tickCount} error: ${error instanceof Error ? error.message : error}`);
|
|
1914
2176
|
if (this.hooks.onError && error instanceof Error) {
|
|
1915
2177
|
await this.hooks.onError(error, this);
|
|
1916
2178
|
}
|
|
@@ -1950,7 +2212,7 @@ var Agent = class {
|
|
|
1950
2212
|
this.actionRegistry.register(action);
|
|
1951
2213
|
}
|
|
1952
2214
|
}
|
|
1953
|
-
|
|
2215
|
+
logger6.info(`Registered ${moltbookActions.length} Moltbook actions`);
|
|
1954
2216
|
}
|
|
1955
2217
|
const a2a = this.config.a2a;
|
|
1956
2218
|
if (a2a && a2a.enabled !== false) {
|
|
@@ -1970,7 +2232,7 @@ var Agent = class {
|
|
|
1970
2232
|
this.actionRegistry.register(action);
|
|
1971
2233
|
}
|
|
1972
2234
|
}
|
|
1973
|
-
|
|
2235
|
+
logger6.info(`Registered ${peerActions.length} A2A peer actions`);
|
|
1974
2236
|
} else {
|
|
1975
2237
|
const genericAction = createA2ACommunicationAction({
|
|
1976
2238
|
defaultAgentUrl: a2a.defaultPeerUrl,
|
|
@@ -1980,7 +2242,7 @@ var Agent = class {
|
|
|
1980
2242
|
if (!this.actionRegistry.has(genericAction.name)) {
|
|
1981
2243
|
this.actionRegistry.register(genericAction);
|
|
1982
2244
|
}
|
|
1983
|
-
|
|
2245
|
+
logger6.info(`Registered generic A2A action: ${genericAction.name}`);
|
|
1984
2246
|
}
|
|
1985
2247
|
}
|
|
1986
2248
|
const world = this.config.world;
|
|
@@ -1997,7 +2259,7 @@ var Agent = class {
|
|
|
1997
2259
|
this.actionRegistry.register(action);
|
|
1998
2260
|
}
|
|
1999
2261
|
}
|
|
2000
|
-
|
|
2262
|
+
logger6.info(`Registered 4 world actions (world: ${worldUrl})`);
|
|
2001
2263
|
}
|
|
2002
2264
|
if (this.config.customActions) {
|
|
2003
2265
|
for (const action of this.config.customActions) {
|
|
@@ -2010,7 +2272,7 @@ var Agent = class {
|
|
|
2010
2272
|
await this.initMoltbook(social);
|
|
2011
2273
|
await this.initTwitter(social);
|
|
2012
2274
|
if (Object.keys(this.socialAdapters).length === 0) {
|
|
2013
|
-
|
|
2275
|
+
logger6.warn("Social: No adapters connected. Set MOLTBOOK_API_KEY or Twitter env vars in your .env to enable.");
|
|
2014
2276
|
}
|
|
2015
2277
|
}
|
|
2016
2278
|
async initMoltbook(social) {
|
|
@@ -2021,13 +2283,13 @@ var Agent = class {
|
|
|
2021
2283
|
const explicitlyDisabled = configMoltbook && configMoltbook.enabled === false && !envKey;
|
|
2022
2284
|
const shouldConnect = !isPlaceholder && !explicitlyDisabled;
|
|
2023
2285
|
if (explicitlyDisabled) {
|
|
2024
|
-
|
|
2286
|
+
logger6.info("Moltbook: Disabled in config and no MOLTBOOK_API_KEY in env \u2014 skipping");
|
|
2025
2287
|
return;
|
|
2026
2288
|
}
|
|
2027
2289
|
if (isPlaceholder) {
|
|
2028
2290
|
if (configMoltbook?.enabled || envKey) {
|
|
2029
|
-
|
|
2030
|
-
|
|
2291
|
+
logger6.warn("Moltbook: MOLTBOOK_API_KEY is missing or still a placeholder.");
|
|
2292
|
+
logger6.warn(" Fix: Set a valid MOLTBOOK_API_KEY in your .env file.");
|
|
2031
2293
|
}
|
|
2032
2294
|
return;
|
|
2033
2295
|
}
|
|
@@ -2045,16 +2307,16 @@ var Agent = class {
|
|
|
2045
2307
|
...configMoltbook?.apiKey ? {} : { apiKey },
|
|
2046
2308
|
...configMoltbook?.baseUrl ? {} : { baseUrl }
|
|
2047
2309
|
};
|
|
2048
|
-
|
|
2049
|
-
|
|
2310
|
+
logger6.info(`Moltbook: API key detected from ${source}`);
|
|
2311
|
+
logger6.info(`Moltbook: Connecting to ${baseUrl} ...`);
|
|
2050
2312
|
const adapter = new MoltbookAdapter(effectiveConfig);
|
|
2051
2313
|
try {
|
|
2052
2314
|
await adapter.connect();
|
|
2053
2315
|
this.socialAdapters["moltbook"] = adapter;
|
|
2054
2316
|
social.moltbook = effectiveConfig;
|
|
2055
|
-
|
|
2317
|
+
logger6.info(`Moltbook: Connected successfully (submolt: ${defaultSubmolt})`);
|
|
2056
2318
|
} catch (error) {
|
|
2057
|
-
|
|
2319
|
+
logger6.error(`Moltbook: Connection FAILED \u2014 ${error.message || error}`);
|
|
2058
2320
|
this.logPlatformError("Moltbook", error);
|
|
2059
2321
|
}
|
|
2060
2322
|
}
|
|
@@ -2073,23 +2335,23 @@ var Agent = class {
|
|
|
2073
2335
|
const hasAllCreds = hasKey && apiSecret && accessToken && accessSecret;
|
|
2074
2336
|
const explicitlyDisabled = configTwitter && configTwitter.enabled === false && !envApiKey;
|
|
2075
2337
|
if (explicitlyDisabled) {
|
|
2076
|
-
|
|
2338
|
+
logger6.info("Twitter: Disabled in config and no TWITTER_API_KEY in env \u2014 skipping");
|
|
2077
2339
|
return;
|
|
2078
2340
|
}
|
|
2079
2341
|
if (!hasKey) {
|
|
2080
2342
|
if (configTwitter?.enabled || envApiKey) {
|
|
2081
|
-
|
|
2082
|
-
|
|
2343
|
+
logger6.warn("Twitter: Credentials are missing or still placeholders.");
|
|
2344
|
+
logger6.warn(" Fix: Set valid Twitter keys in your .env file.");
|
|
2083
2345
|
}
|
|
2084
2346
|
return;
|
|
2085
2347
|
}
|
|
2086
2348
|
if (!hasAllCreds) {
|
|
2087
|
-
|
|
2349
|
+
logger6.warn("Twitter: Some credentials are missing. Need: TWITTER_API_KEY, TWITTER_API_SECRET, TWITTER_ACCESS_TOKEN, TWITTER_ACCESS_SECRET");
|
|
2088
2350
|
return;
|
|
2089
2351
|
}
|
|
2090
2352
|
const source = creds?.apiKey ? "config" : "environment";
|
|
2091
|
-
|
|
2092
|
-
|
|
2353
|
+
logger6.info(`Twitter: Credentials detected from ${source}`);
|
|
2354
|
+
logger6.info("Twitter: Connecting...");
|
|
2093
2355
|
const effectiveConfig = {
|
|
2094
2356
|
enabled: true,
|
|
2095
2357
|
...configTwitter,
|
|
@@ -2100,16 +2362,16 @@ var Agent = class {
|
|
|
2100
2362
|
await adapter.connect();
|
|
2101
2363
|
this.socialAdapters["twitter"] = adapter;
|
|
2102
2364
|
social.twitter = effectiveConfig;
|
|
2103
|
-
|
|
2365
|
+
logger6.info("Twitter: Connected successfully");
|
|
2104
2366
|
} catch (error) {
|
|
2105
|
-
|
|
2367
|
+
logger6.error(`Twitter: Connection FAILED \u2014 ${error.message || error}`);
|
|
2106
2368
|
this.logPlatformError("Twitter", error);
|
|
2107
2369
|
}
|
|
2108
2370
|
}
|
|
2109
2371
|
async postStartupMessages() {
|
|
2110
2372
|
const adapters = Object.entries(this.socialAdapters);
|
|
2111
2373
|
if (adapters.length === 0) {
|
|
2112
|
-
|
|
2374
|
+
logger6.info("Startup post: No connected social adapters \u2014 skipping");
|
|
2113
2375
|
return;
|
|
2114
2376
|
}
|
|
2115
2377
|
let content;
|
|
@@ -2124,18 +2386,18 @@ Write only the post content, nothing else. Keep it concise and natural.`;
|
|
|
2124
2386
|
temperature: this.config.llm.temperature ?? 0.8,
|
|
2125
2387
|
maxTokens: 280
|
|
2126
2388
|
})).trim();
|
|
2127
|
-
|
|
2389
|
+
logger6.info(`Startup post: LLM generated content (${content.length} chars)`);
|
|
2128
2390
|
} catch (error) {
|
|
2129
|
-
|
|
2391
|
+
logger6.warn(`Startup post: LLM generation failed (${error.message}), using fallback`);
|
|
2130
2392
|
content = `${this.config.name} is now online and ready.`;
|
|
2131
2393
|
}
|
|
2132
2394
|
for (const [platform, adapter] of adapters) {
|
|
2133
|
-
|
|
2395
|
+
logger6.info(`Startup post: Posting to ${platform}...`);
|
|
2134
2396
|
try {
|
|
2135
2397
|
const result = await adapter.post(content);
|
|
2136
|
-
|
|
2398
|
+
logger6.info(`Startup post: ${platform} SUCCESS \u2014 id=${result.id}${result.url ? ` url=${result.url}` : ""}`);
|
|
2137
2399
|
} catch (error) {
|
|
2138
|
-
|
|
2400
|
+
logger6.error(`Startup post: ${platform} FAILED \u2014 ${error.message || error}`);
|
|
2139
2401
|
this.logPlatformError(platform, error);
|
|
2140
2402
|
}
|
|
2141
2403
|
}
|
|
@@ -2158,7 +2420,7 @@ Write only the post content, nothing else. Keep it concise and natural.`;
|
|
|
2158
2420
|
await this.scheduledPost("moltbook");
|
|
2159
2421
|
}
|
|
2160
2422
|
});
|
|
2161
|
-
|
|
2423
|
+
logger6.info(`Scheduler: Moltbook posting every ${formatInterval(intervalMs)}`);
|
|
2162
2424
|
}
|
|
2163
2425
|
}
|
|
2164
2426
|
}
|
|
@@ -2174,7 +2436,7 @@ Write only the post content, nothing else. Keep it concise and natural.`;
|
|
|
2174
2436
|
await this.scheduledPost("twitter");
|
|
2175
2437
|
}
|
|
2176
2438
|
});
|
|
2177
|
-
|
|
2439
|
+
logger6.info(`Scheduler: Twitter posting every ${formatInterval(intervalMs)}`);
|
|
2178
2440
|
}
|
|
2179
2441
|
}
|
|
2180
2442
|
}
|
|
@@ -2190,7 +2452,7 @@ Write only the post content, nothing else. Keep it concise and natural.`;
|
|
|
2190
2452
|
await this.executeScheduledTask(task);
|
|
2191
2453
|
}
|
|
2192
2454
|
});
|
|
2193
|
-
|
|
2455
|
+
logger6.info(`Scheduler: "${task.name}" every ${formatInterval(task.intervalMs)}`);
|
|
2194
2456
|
}
|
|
2195
2457
|
}
|
|
2196
2458
|
async scheduledPost(platform) {
|
|
@@ -2206,15 +2468,15 @@ Write only the post content, nothing else. Keep it concise and natural.`;
|
|
|
2206
2468
|
maxTokens: 280
|
|
2207
2469
|
});
|
|
2208
2470
|
const result = await adapter.post(content.trim());
|
|
2209
|
-
|
|
2471
|
+
logger6.info(`Scheduled post: ${platform} SUCCESS \u2014 id=${result.id}`);
|
|
2210
2472
|
} catch (error) {
|
|
2211
|
-
|
|
2473
|
+
logger6.error(`Scheduled post: ${platform} FAILED \u2014 ${error.message || error}`);
|
|
2212
2474
|
this.logPlatformError(platform, error);
|
|
2213
2475
|
}
|
|
2214
2476
|
}
|
|
2215
2477
|
async executeScheduledTask(task) {
|
|
2216
2478
|
try {
|
|
2217
|
-
|
|
2479
|
+
logger6.info(`Scheduled task: Running "${task.name}"`);
|
|
2218
2480
|
const prompt = `You are ${this.config.name}, an autonomous agent. Execute the following scheduled task.
|
|
2219
2481
|
|
|
2220
2482
|
Task: ${task.name}
|
|
@@ -2239,74 +2501,74 @@ Decide what action to take. Respond with JSON:
|
|
|
2239
2501
|
{ systemPrompt: this.systemPrompt, temperature: this.config.llm.temperature }
|
|
2240
2502
|
);
|
|
2241
2503
|
const result = await this.act(decision.action, decision.parameters);
|
|
2242
|
-
|
|
2504
|
+
logger6.info(`Scheduled task: "${task.name}" completed \u2014 action=${decision.action}, success=${result.success}`);
|
|
2243
2505
|
} catch (error) {
|
|
2244
|
-
|
|
2506
|
+
logger6.error(`Scheduled task: "${task.name}" FAILED \u2014 ${error.message || error}`);
|
|
2245
2507
|
}
|
|
2246
2508
|
}
|
|
2247
2509
|
logPlatformError(platform, error) {
|
|
2248
2510
|
if (!error.response) {
|
|
2249
2511
|
if (error.code === "ENOTFOUND") {
|
|
2250
|
-
|
|
2512
|
+
logger6.error(` ${platform}: DNS lookup failed \u2014 check the base URL.`);
|
|
2251
2513
|
} else if (error.code === "ECONNREFUSED") {
|
|
2252
|
-
|
|
2514
|
+
logger6.error(` ${platform}: Connection refused \u2014 is the server running?`);
|
|
2253
2515
|
} else if (error.code === "ETIMEDOUT" || error.code === "ECONNABORTED") {
|
|
2254
|
-
|
|
2516
|
+
logger6.error(` ${platform}: Request timed out.`);
|
|
2255
2517
|
} else {
|
|
2256
|
-
|
|
2518
|
+
logger6.error(` ${platform}: Network error (${error.code || "unknown"})`);
|
|
2257
2519
|
}
|
|
2258
2520
|
return;
|
|
2259
2521
|
}
|
|
2260
2522
|
const status = error.response.status;
|
|
2261
2523
|
const data = error.response.data;
|
|
2262
|
-
|
|
2524
|
+
logger6.error(` ${platform}: HTTP ${status}`);
|
|
2263
2525
|
if (data) {
|
|
2264
|
-
if (data.error)
|
|
2265
|
-
if (data.hint)
|
|
2266
|
-
if (!data.error && !data.hint)
|
|
2526
|
+
if (data.error) logger6.error(` ${platform}: API error: ${data.error}`);
|
|
2527
|
+
if (data.hint) logger6.error(` ${platform}: API hint: ${data.hint}`);
|
|
2528
|
+
if (!data.error && !data.hint) logger6.error(` ${platform}: Response: ${JSON.stringify(data)}`);
|
|
2267
2529
|
}
|
|
2268
2530
|
if (status === 401) {
|
|
2269
|
-
|
|
2531
|
+
logger6.error(` ${platform}: Your API key was rejected. Verify it is correct and the agent is claimed.`);
|
|
2270
2532
|
} else if (status === 403) {
|
|
2271
|
-
|
|
2533
|
+
logger6.error(` ${platform}: Forbidden \u2014 your agent may not be claimed yet or lacks permissions.`);
|
|
2272
2534
|
} else if (status === 429) {
|
|
2273
2535
|
const retryMin = data?.retry_after_minutes;
|
|
2274
2536
|
const retrySec = data?.retry_after_seconds;
|
|
2275
2537
|
if (retryMin) {
|
|
2276
|
-
|
|
2538
|
+
logger6.error(` ${platform}: Rate limited \u2014 try again in ${retryMin} minute(s).`);
|
|
2277
2539
|
} else if (retrySec) {
|
|
2278
|
-
|
|
2540
|
+
logger6.error(` ${platform}: Rate limited \u2014 try again in ${retrySec} second(s).`);
|
|
2279
2541
|
} else {
|
|
2280
|
-
|
|
2542
|
+
logger6.error(` ${platform}: Rate limited \u2014 wait before retrying.`);
|
|
2281
2543
|
}
|
|
2282
2544
|
} else if (status === 404) {
|
|
2283
|
-
|
|
2545
|
+
logger6.error(` ${platform}: Endpoint not found \u2014 check the base URL.`);
|
|
2284
2546
|
} else if (status >= 500) {
|
|
2285
|
-
|
|
2547
|
+
logger6.error(` ${platform}: Server error \u2014 the platform may be temporarily down.`);
|
|
2286
2548
|
}
|
|
2287
2549
|
}
|
|
2288
2550
|
async autoJoinWorld() {
|
|
2289
2551
|
const worldUrl = this.config.world.url;
|
|
2290
|
-
|
|
2552
|
+
logger6.info(`Auto-joining world: ${worldUrl}`);
|
|
2291
2553
|
try {
|
|
2292
2554
|
const result = await this.act("join_world", {
|
|
2293
2555
|
worldUrl,
|
|
2294
2556
|
walletAddress: this.config.world.walletAddress
|
|
2295
2557
|
});
|
|
2296
2558
|
if (result.success) {
|
|
2297
|
-
|
|
2559
|
+
logger6.info(`Successfully joined world: ${worldUrl}`);
|
|
2298
2560
|
} else {
|
|
2299
|
-
|
|
2561
|
+
logger6.warn(`Failed to join world: ${result.error}`);
|
|
2300
2562
|
}
|
|
2301
2563
|
} catch (error) {
|
|
2302
|
-
|
|
2564
|
+
logger6.warn(`Auto-join world failed: ${error?.message || error}`);
|
|
2303
2565
|
}
|
|
2304
2566
|
}
|
|
2305
2567
|
startAutonomousLoop() {
|
|
2306
2568
|
const actionsPerHour = typeof this.config.behaviors.actionsPerHour === "function" ? this.config.behaviors.actionsPerHour({}) : this.config.behaviors.actionsPerHour || 5;
|
|
2307
2569
|
const intervalMs = Math.floor(36e5 / actionsPerHour);
|
|
2308
2570
|
this.tickTimer = setInterval(() => this.tick(), intervalMs);
|
|
2309
|
-
|
|
2571
|
+
logger6.info(`Autonomous loop started: ~${actionsPerHour} actions/hour (every ${intervalMs}ms)`);
|
|
2310
2572
|
}
|
|
2311
2573
|
isSleeping() {
|
|
2312
2574
|
const schedule = this.config.behaviors.sleepSchedule;
|
|
@@ -2341,7 +2603,7 @@ Decide what action to take. Respond with JSON:
|
|
|
2341
2603
|
await axios2.post(hook, { event, data: args });
|
|
2342
2604
|
}
|
|
2343
2605
|
} catch (error) {
|
|
2344
|
-
|
|
2606
|
+
logger6.error(`Webhook ${event} failed: ${error}`);
|
|
2345
2607
|
}
|
|
2346
2608
|
}
|
|
2347
2609
|
};
|
|
@@ -2481,10 +2743,18 @@ var MarkdownParser = class {
|
|
|
2481
2743
|
const fields = this.parseKeyValueLines(section.content);
|
|
2482
2744
|
const url = fields["url"];
|
|
2483
2745
|
if (!url) return void 0;
|
|
2746
|
+
let privateKey;
|
|
2747
|
+
const pkField = fields["wallet_private_key"];
|
|
2748
|
+
if (pkField === "env") {
|
|
2749
|
+
privateKey = process.env.AGENT_WALLET_PRIVATE_KEY;
|
|
2750
|
+
} else if (pkField && pkField.startsWith("0x")) {
|
|
2751
|
+
privateKey = pkField;
|
|
2752
|
+
}
|
|
2484
2753
|
return {
|
|
2485
2754
|
url,
|
|
2486
2755
|
autoJoin: fields["auto_join"] !== "false",
|
|
2487
|
-
...fields["wallet_address"] ? { walletAddress: fields["wallet_address"] } : {}
|
|
2756
|
+
...fields["wallet_address"] ? { walletAddress: fields["wallet_address"] } : {},
|
|
2757
|
+
...privateKey ? { privateKey } : {}
|
|
2488
2758
|
};
|
|
2489
2759
|
}
|
|
2490
2760
|
parseSleepSchedule(value) {
|
|
@@ -2659,7 +2929,8 @@ var ConfigLoader = class {
|
|
|
2659
2929
|
};
|
|
2660
2930
|
|
|
2661
2931
|
// src/memory/longterm.ts
|
|
2662
|
-
|
|
2932
|
+
init_logger();
|
|
2933
|
+
var logger7 = createLogger("LongTermMemory");
|
|
2663
2934
|
var LongTermMemory = class extends Memory {
|
|
2664
2935
|
redisConfig;
|
|
2665
2936
|
postgresConfig;
|
|
@@ -2835,9 +3106,9 @@ var LongTermMemory = class extends Memory {
|
|
|
2835
3106
|
try {
|
|
2836
3107
|
const { default: Redis } = await import("ioredis");
|
|
2837
3108
|
this.redis = new Redis(this.redisConfig.url);
|
|
2838
|
-
|
|
3109
|
+
logger7.info("Redis connection established");
|
|
2839
3110
|
} catch (error) {
|
|
2840
|
-
|
|
3111
|
+
logger7.error(`Failed to connect to Redis: ${error}`);
|
|
2841
3112
|
throw error;
|
|
2842
3113
|
}
|
|
2843
3114
|
}
|
|
@@ -2850,9 +3121,9 @@ var LongTermMemory = class extends Memory {
|
|
|
2850
3121
|
connectionString: this.postgresConfig.url
|
|
2851
3122
|
});
|
|
2852
3123
|
await this.pg.query("SELECT 1");
|
|
2853
|
-
|
|
3124
|
+
logger7.info("Postgres connection established");
|
|
2854
3125
|
} catch (error) {
|
|
2855
|
-
|
|
3126
|
+
logger7.error(`Failed to connect to Postgres: ${error}`);
|
|
2856
3127
|
throw error;
|
|
2857
3128
|
}
|
|
2858
3129
|
}
|
|
@@ -2994,13 +3265,14 @@ function createRoutes(agent) {
|
|
|
2994
3265
|
}
|
|
2995
3266
|
|
|
2996
3267
|
// src/server/middleware.ts
|
|
2997
|
-
|
|
3268
|
+
init_logger();
|
|
3269
|
+
var logger8 = createLogger("Server");
|
|
2998
3270
|
function requestLogger(req, _res, next) {
|
|
2999
|
-
|
|
3271
|
+
logger8.debug(`${req.method} ${req.path}`);
|
|
3000
3272
|
next();
|
|
3001
3273
|
}
|
|
3002
3274
|
function errorHandler(err, _req, res, _next) {
|
|
3003
|
-
|
|
3275
|
+
logger8.error(`Server error: ${err.message}`);
|
|
3004
3276
|
res.status(500).json({ error: err.message });
|
|
3005
3277
|
}
|
|
3006
3278
|
function authMiddleware(req, res, next) {
|
|
@@ -3017,8 +3289,12 @@ function authMiddleware(req, res, next) {
|
|
|
3017
3289
|
next();
|
|
3018
3290
|
}
|
|
3019
3291
|
|
|
3292
|
+
// src/server/app.ts
|
|
3293
|
+
init_logger();
|
|
3294
|
+
|
|
3020
3295
|
// src/a2a/AgentCardBuilder.ts
|
|
3021
|
-
|
|
3296
|
+
init_logger();
|
|
3297
|
+
var logger9 = createLogger("AgentCardBuilder");
|
|
3022
3298
|
var AgentCardBuilder = class {
|
|
3023
3299
|
/**
|
|
3024
3300
|
* Creates an A2A AgentCard from Moltium configuration.
|
|
@@ -3040,7 +3316,7 @@ var AgentCardBuilder = class {
|
|
|
3040
3316
|
name: config.name,
|
|
3041
3317
|
description: config.personality.bio || `${config.name} - An autonomous AI agent`,
|
|
3042
3318
|
protocolVersion: "0.3.0",
|
|
3043
|
-
version: "0.1.
|
|
3319
|
+
version: "0.1.30",
|
|
3044
3320
|
url: `${baseUrl}/a2a/jsonrpc`,
|
|
3045
3321
|
skills,
|
|
3046
3322
|
capabilities,
|
|
@@ -3051,7 +3327,7 @@ var AgentCardBuilder = class {
|
|
|
3051
3327
|
{ url: `${baseUrl}/a2a/rest`, transport: "HTTP+JSON" }
|
|
3052
3328
|
]
|
|
3053
3329
|
};
|
|
3054
|
-
|
|
3330
|
+
logger9.debug("Built A2A AgentCard", {
|
|
3055
3331
|
name: agentCard.name,
|
|
3056
3332
|
skillCount: skills.length,
|
|
3057
3333
|
baseUrl
|
|
@@ -3133,8 +3409,9 @@ var AgentCardBuilder = class {
|
|
|
3133
3409
|
};
|
|
3134
3410
|
|
|
3135
3411
|
// src/a2a/MoltiumExecutor.ts
|
|
3412
|
+
init_logger();
|
|
3136
3413
|
var import_uuid2 = require("uuid");
|
|
3137
|
-
var
|
|
3414
|
+
var logger10 = createLogger("MoltiumExecutor");
|
|
3138
3415
|
var MoltiumExecutor = class {
|
|
3139
3416
|
agent;
|
|
3140
3417
|
cancelledTasks = /* @__PURE__ */ new Set();
|
|
@@ -3148,7 +3425,7 @@ var MoltiumExecutor = class {
|
|
|
3148
3425
|
async execute(requestContext, eventBus) {
|
|
3149
3426
|
const { taskId, contextId, userMessage, task } = requestContext;
|
|
3150
3427
|
try {
|
|
3151
|
-
|
|
3428
|
+
logger10.info(`[A2A] Executing request for task ${taskId}`);
|
|
3152
3429
|
if (!task) {
|
|
3153
3430
|
const initialTask = {
|
|
3154
3431
|
kind: "task",
|
|
@@ -3186,9 +3463,9 @@ var MoltiumExecutor = class {
|
|
|
3186
3463
|
}
|
|
3187
3464
|
this.publishStatusUpdate(taskId, contextId, "completed", eventBus, true);
|
|
3188
3465
|
eventBus.finished();
|
|
3189
|
-
|
|
3466
|
+
logger10.info(`[A2A] Task ${taskId} completed successfully`);
|
|
3190
3467
|
} catch (error) {
|
|
3191
|
-
|
|
3468
|
+
logger10.error(`[A2A] Task ${taskId} failed`, {
|
|
3192
3469
|
error: error instanceof Error ? error.message : String(error)
|
|
3193
3470
|
});
|
|
3194
3471
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -3203,7 +3480,7 @@ var MoltiumExecutor = class {
|
|
|
3203
3480
|
* Handles task cancellation requests.
|
|
3204
3481
|
*/
|
|
3205
3482
|
async cancelTask(taskId, eventBus) {
|
|
3206
|
-
|
|
3483
|
+
logger10.info(`[A2A] Cancellation requested for task ${taskId}`);
|
|
3207
3484
|
this.cancelledTasks.add(taskId);
|
|
3208
3485
|
}
|
|
3209
3486
|
/**
|
|
@@ -3365,7 +3642,7 @@ var MoltiumExecutor = class {
|
|
|
3365
3642
|
* Publishes a cancellation status.
|
|
3366
3643
|
*/
|
|
3367
3644
|
publishCancellation(taskId, contextId, eventBus) {
|
|
3368
|
-
|
|
3645
|
+
logger10.info(`[A2A] Publishing cancellation for task ${taskId}`);
|
|
3369
3646
|
this.publishStatusUpdate(taskId, contextId, "canceled", eventBus, true);
|
|
3370
3647
|
eventBus.finished();
|
|
3371
3648
|
this.cancelledTasks.delete(taskId);
|
|
@@ -3374,7 +3651,8 @@ var MoltiumExecutor = class {
|
|
|
3374
3651
|
|
|
3375
3652
|
// src/a2a/integration.ts
|
|
3376
3653
|
var import_server = require("@a2a-js/sdk/server");
|
|
3377
|
-
|
|
3654
|
+
init_logger();
|
|
3655
|
+
var logger11 = createLogger("A2AIntegration");
|
|
3378
3656
|
var A2AIntegration = class {
|
|
3379
3657
|
agent;
|
|
3380
3658
|
agentCard;
|
|
@@ -3389,7 +3667,7 @@ var A2AIntegration = class {
|
|
|
3389
3667
|
new import_server.InMemoryTaskStore(),
|
|
3390
3668
|
this.moltiumExecutor
|
|
3391
3669
|
);
|
|
3392
|
-
|
|
3670
|
+
logger11.info("A2A integration initialized", {
|
|
3393
3671
|
agentName: agent.name,
|
|
3394
3672
|
baseUrl: options.a2aConfig.baseUrl
|
|
3395
3673
|
});
|
|
@@ -3411,7 +3689,7 @@ var A2AIntegration = class {
|
|
|
3411
3689
|
const response = await jsonRpcHandler.handle(req.body);
|
|
3412
3690
|
res.json(response);
|
|
3413
3691
|
} catch (error) {
|
|
3414
|
-
|
|
3692
|
+
logger11.error("JSON-RPC error:", error);
|
|
3415
3693
|
res.status(500).json({
|
|
3416
3694
|
jsonrpc: "2.0",
|
|
3417
3695
|
error: {
|
|
@@ -3442,7 +3720,7 @@ var A2AIntegration = class {
|
|
|
3442
3720
|
new import_server.InMemoryTaskStore(),
|
|
3443
3721
|
this.moltiumExecutor
|
|
3444
3722
|
);
|
|
3445
|
-
|
|
3723
|
+
logger11.info("A2A agent card updated with runtime info", {
|
|
3446
3724
|
host: actualHost,
|
|
3447
3725
|
port: actualPort,
|
|
3448
3726
|
url: this.agentCard.url
|
|
@@ -3460,10 +3738,10 @@ var A2AIntegration = class {
|
|
|
3460
3738
|
logEndpoints(host, port) {
|
|
3461
3739
|
const protocol = host === "localhost" || host === "127.0.0.1" ? "http" : "https";
|
|
3462
3740
|
const baseUrl = `${protocol}://${host}:${port}`;
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3741
|
+
logger11.info("A2A endpoints available:");
|
|
3742
|
+
logger11.info(` Agent Card: ${baseUrl}/.well-known/agent.json`);
|
|
3743
|
+
logger11.info(` JSON-RPC: ${baseUrl}/a2a/jsonrpc`);
|
|
3744
|
+
logger11.info(` HTTP+JSON: ${baseUrl}/a2a/rest`);
|
|
3467
3745
|
}
|
|
3468
3746
|
};
|
|
3469
3747
|
function createA2AIntegration(agent, options = {}) {
|
|
@@ -3478,7 +3756,7 @@ function createA2AIntegration(agent, options = {}) {
|
|
|
3478
3756
|
}
|
|
3479
3757
|
|
|
3480
3758
|
// src/server/app.ts
|
|
3481
|
-
var
|
|
3759
|
+
var logger12 = createLogger("Server");
|
|
3482
3760
|
var AGENT_CARD_PATH = ".well-known/agent.json";
|
|
3483
3761
|
function createApp(agent, options = {}) {
|
|
3484
3762
|
const app = (0, import_express2.default)();
|
|
@@ -3504,9 +3782,10 @@ function createApp(agent, options = {}) {
|
|
|
3504
3782
|
});
|
|
3505
3783
|
const handlers = a2aIntegration.getHandlers();
|
|
3506
3784
|
app.use(`/${AGENT_CARD_PATH}`, handlers.agentCard);
|
|
3785
|
+
app.use("/.well-known/agent-card.json", handlers.agentCard);
|
|
3507
3786
|
app.use("/a2a/jsonrpc", handlers.jsonRpc);
|
|
3508
3787
|
app.use("/a2a/rest", handlers.rest);
|
|
3509
|
-
|
|
3788
|
+
logger12.info("A2A protocol endpoints enabled");
|
|
3510
3789
|
}
|
|
3511
3790
|
app.use(errorHandler);
|
|
3512
3791
|
return app;
|
|
@@ -3517,28 +3796,34 @@ async function startServer(agent, options = {}) {
|
|
|
3517
3796
|
const app = createApp(agent, options);
|
|
3518
3797
|
await new Promise((resolve2) => {
|
|
3519
3798
|
app.listen(port, host, () => {
|
|
3520
|
-
|
|
3799
|
+
logger12.info(`Agent "${agent.name}" running at http://${host}:${port}`);
|
|
3521
3800
|
if (options.enableA2A !== false) {
|
|
3522
3801
|
const logHost = host === "0.0.0.0" ? "localhost" : host;
|
|
3523
3802
|
const protocol = logHost === "localhost" || logHost === "127.0.0.1" ? "http" : "https";
|
|
3524
3803
|
const baseUrl = `${protocol}://${logHost}:${port}`;
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3804
|
+
logger12.info("A2A Protocol Endpoints:");
|
|
3805
|
+
logger12.info(` Agent Card: ${baseUrl}/.well-known/agent.json`);
|
|
3806
|
+
logger12.info(` JSON-RPC: ${baseUrl}/a2a/jsonrpc`);
|
|
3807
|
+
logger12.info(` HTTP+JSON: ${baseUrl}/a2a/rest`);
|
|
3529
3808
|
}
|
|
3530
3809
|
resolve2();
|
|
3531
3810
|
});
|
|
3532
3811
|
});
|
|
3533
3812
|
await agent.start();
|
|
3534
3813
|
const shutdown = async () => {
|
|
3535
|
-
|
|
3814
|
+
logger12.info("Received shutdown signal");
|
|
3536
3815
|
await agent.stop();
|
|
3537
3816
|
process.exit(0);
|
|
3538
3817
|
};
|
|
3539
3818
|
process.on("SIGINT", shutdown);
|
|
3540
3819
|
process.on("SIGTERM", shutdown);
|
|
3541
3820
|
}
|
|
3821
|
+
|
|
3822
|
+
// src/wallet/index.ts
|
|
3823
|
+
init_AgentWallet();
|
|
3824
|
+
|
|
3825
|
+
// src/index.ts
|
|
3826
|
+
init_logger();
|
|
3542
3827
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3543
3828
|
0 && (module.exports = {
|
|
3544
3829
|
A2AClient,
|
|
@@ -3547,6 +3832,7 @@ async function startServer(agent, options = {}) {
|
|
|
3547
3832
|
ActionRegistry,
|
|
3548
3833
|
Agent,
|
|
3549
3834
|
AgentCardBuilder,
|
|
3835
|
+
AgentWallet,
|
|
3550
3836
|
AnthropicProvider,
|
|
3551
3837
|
ConfigLoader,
|
|
3552
3838
|
LLMProvider,
|