@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/index.mjs CHANGED
@@ -1,20 +1,7 @@
1
- // src/logger.ts
2
- import winston from "winston";
3
- var logLevel = process.env.LOG_LEVEL || "info";
4
- function createLogger(label) {
5
- return winston.createLogger({
6
- level: logLevel,
7
- format: winston.format.combine(
8
- winston.format.timestamp(),
9
- winston.format.label({ label }),
10
- winston.format.printf(({ timestamp, level, label: label2, message, ...meta }) => {
11
- const metaStr = Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : "";
12
- return `${timestamp} [${label2}] ${level}: ${message}${metaStr}`;
13
- })
14
- ),
15
- transports: [new winston.transports.Console()]
16
- });
17
- }
1
+ import {
2
+ AgentWallet,
3
+ createLogger
4
+ } from "./chunk-K2UFQ7YF.mjs";
18
5
 
19
6
  // src/agent/scheduler.ts
20
7
  var logger = createLogger("Scheduler");
@@ -425,10 +412,11 @@ var moltbookActions = [
425
412
  ];
426
413
 
427
414
  // src/actions/built-in/world.ts
415
+ var logger3 = createLogger("WorldActions");
428
416
  function createJoinWorldAction(config) {
429
417
  return {
430
418
  name: "join_world",
431
- description: `Join a world by URL. The world will fetch this agent's A2A Agent Card and evaluate admission. Parameters: worldUrl (string${config?.defaultWorldUrl ? ", optional" : ", required"}) - the world server URL${config?.defaultWorldUrl ? ` (defaults to ${config.defaultWorldUrl})` : ""}, walletAddress (string, optional) - wallet address for blockchain worlds.`,
419
+ 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.`,
432
420
  async execute(context) {
433
421
  const { parameters, agent } = context;
434
422
  const worldUrl = parameters.worldUrl || config?.defaultWorldUrl;
@@ -438,11 +426,45 @@ function createJoinWorldAction(config) {
438
426
  const agentPort = process.env.PORT || "3000";
439
427
  const agentHost = process.env.HOST || "localhost";
440
428
  const agentUrl = `http://${agentHost}:${agentPort}`;
429
+ const walletAddress = parameters.walletAddress || agent?.config?.world?.walletAddress;
441
430
  try {
442
431
  const { default: axios2 } = await import("axios");
432
+ let paymentTxHash;
433
+ try {
434
+ const infoRes = await axios2.get(`${worldUrl}/world/join-info`, { timeout: 5e3 });
435
+ const joinInfo = infoRes.data;
436
+ if (joinInfo.requiresPayment && joinInfo.entryFee && joinInfo.entryFee !== "0") {
437
+ const privateKey = agent?.config?.world?.privateKey;
438
+ if (!privateKey) {
439
+ return {
440
+ success: false,
441
+ error: "World requires entry fee but agent has no wallet private key configured. Set AGENT_WALLET_PRIVATE_KEY in your .env file."
442
+ };
443
+ }
444
+ logger3.info(`World requires entry fee: ${joinInfo.entryFee} wei`);
445
+ const { AgentWallet: AgentWallet2 } = await import("./AgentWallet-WSXDC5NX.mjs");
446
+ const wallet = new AgentWallet2(privateKey, joinInfo.rpcUrl);
447
+ const balance = await wallet.getBalance();
448
+ if (BigInt(balance) < BigInt(joinInfo.entryFee)) {
449
+ const { formatEther } = await import("ethers");
450
+ return {
451
+ success: false,
452
+ error: `Insufficient balance to pay entry fee. Need ${formatEther(joinInfo.entryFee)} MON, have ${formatEther(balance)} MON`
453
+ };
454
+ }
455
+ logger3.info(`Paying entry fee to ${joinInfo.paymentAddress}...`);
456
+ paymentTxHash = await wallet.sendPayment(joinInfo.paymentAddress, joinInfo.entryFee);
457
+ logger3.info(`Entry fee paid. TX: ${paymentTxHash}`);
458
+ }
459
+ } catch (infoError) {
460
+ if (infoError?.response?.status !== 404) {
461
+ logger3.debug(`Could not query join-info: ${infoError.message}`);
462
+ }
463
+ }
443
464
  const response = await axios2.post(`${worldUrl}/world/join`, {
444
465
  agentUrl,
445
- walletAddress: parameters.walletAddress || agent?.config?.world?.walletAddress
466
+ walletAddress,
467
+ paymentTxHash
446
468
  }, { timeout: 1e4 });
447
469
  return {
448
470
  success: true,
@@ -591,17 +613,39 @@ ${config.llm.systemPrompt}`);
591
613
  }
592
614
  function buildDecisionPrompt(context, availableActions) {
593
615
  const actionList = availableActions.map((a) => `- ${a.name}: ${a.description}`).join("\n");
616
+ const actionNames = availableActions.map((a) => a.name);
617
+ const hasWorldActions = actionNames.some(
618
+ (n) => ["send_world_message", "query_world", "join_world", "leave_world"].includes(n)
619
+ );
620
+ const hasSocialActions = actionNames.some(
621
+ (n) => ["post_social_update", "respond_to_mention"].includes(n)
622
+ );
594
623
  const recent = context.recentActions || [];
595
624
  const recentNames = recent.map((r) => r.action);
596
625
  const lastAction = recentNames.length > 0 ? recentNames[recentNames.length - 1] : "none";
597
626
  let varietyHint = "";
598
627
  if (recentNames.length > 0) {
628
+ const suggestions = [];
629
+ if (hasWorldActions) {
630
+ suggestions.push("querying the world for agents", "sending messages to other agents", "responding to conversations");
631
+ }
632
+ if (hasSocialActions) {
633
+ suggestions.push("posting content", "responding to mentions");
634
+ }
635
+ const suggestStr = suggestions.length > 0 ? `
636
+ Vary between: ${suggestions.join(", ")}.` : "";
599
637
  varietyHint = `
600
638
  Your recent actions (most recent last): ${recentNames.join(" \u2192 ")}
601
- IMPORTANT: Do NOT repeat "${lastAction}" again. Choose a DIFFERENT action to keep your behavior varied and interesting.
602
- Vary between: posting content, checking your feed, replying to others, checking DMs, browsing communities, searching for topics, and following interesting agents.`;
639
+ IMPORTANT: Do NOT repeat "${lastAction}" again. Choose a DIFFERENT action to keep your behavior varied and interesting.` + suggestStr;
603
640
  }
604
- return `You are an autonomous AI agent on moltbook (a social network for AI agents).
641
+ let preamble = "You are an autonomous AI agent.";
642
+ if (hasWorldActions) {
643
+ preamble += " You are connected to a world with other agents.";
644
+ preamble += " Use send_world_message to communicate with other agents (provide toAgentUrl and message parameters).";
645
+ preamble += " Use query_world to discover agents and world state.";
646
+ preamble += ' IMPORTANT: Only use actions from the "Available actions" list below. Do NOT invent action names.';
647
+ }
648
+ return `${preamble}
605
649
  Decide what action to take next based on the current context and your personality.
606
650
 
607
651
  Available actions:
@@ -612,7 +656,7 @@ ${JSON.stringify(context, null, 2)}
612
656
  ${varietyHint}
613
657
 
614
658
  Think about what would be most natural and valuable right now.
615
- If the action generates content (post, comment, DM), include the actual content in parameters.
659
+ Choose ONLY from the available actions listed above.
616
660
 
617
661
  Respond with a JSON object:
618
662
  {
@@ -639,7 +683,7 @@ Execute these instructions step by step and return the result as a JSON object:
639
683
  }
640
684
 
641
685
  // src/actions/interpreter.ts
642
- var logger3 = createLogger("MarkdownInterpreter");
686
+ var logger4 = createLogger("MarkdownInterpreter");
643
687
  var LLMInterpretationError = class extends Error {
644
688
  constructor(message) {
645
689
  super(message);
@@ -651,7 +695,7 @@ function createMarkdownAction(name, description, llmProvider) {
651
695
  name,
652
696
  description,
653
697
  execute: async (context) => {
654
- logger3.info(`Interpreting markdown skill: ${name}`);
698
+ logger4.info(`Interpreting markdown skill: ${name}`);
655
699
  const prompt = buildSkillPrompt(name, description, context.parameters);
656
700
  try {
657
701
  const response = await llmProvider.generateText(prompt, {
@@ -672,7 +716,7 @@ function createMarkdownAction(name, description, llmProvider) {
672
716
  } catch (error) {
673
717
  if (error instanceof LLMInterpretationError) throw error;
674
718
  const message = error instanceof Error ? error.message : String(error);
675
- logger3.error(`Markdown skill interpretation failed: ${name}`, { error: message });
719
+ logger4.error(`Markdown skill interpretation failed: ${name}`, { error: message });
676
720
  throw new LLMInterpretationError(
677
721
  `Failed to interpret skill "${name}": ${message}`
678
722
  );
@@ -1625,7 +1669,7 @@ function createMultipleA2AActions(configs) {
1625
1669
  }
1626
1670
 
1627
1671
  // src/agent/Agent.ts
1628
- var logger4 = createLogger("Agent");
1672
+ var logger5 = createLogger("Agent");
1629
1673
  function parsePostFrequency(freq) {
1630
1674
  const lower = freq.toLowerCase().trim();
1631
1675
  if (lower === "realtime") return 5 * 60 * 1e3;
@@ -1721,7 +1765,17 @@ var Agent = class {
1721
1765
  // ── Lifecycle ──
1722
1766
  async init() {
1723
1767
  this.state = "initializing";
1724
- logger4.info(`Initializing agent: ${this.config.name}`);
1768
+ logger5.info(`Initializing agent: ${this.config.name}`);
1769
+ if (this.config.world?.privateKey && !this.config.world.walletAddress) {
1770
+ try {
1771
+ const { AgentWallet: AgentWallet2 } = await import("./AgentWallet-WSXDC5NX.mjs");
1772
+ const wallet = new AgentWallet2(this.config.world.privateKey);
1773
+ this.config.world.walletAddress = await wallet.getAddressAsync();
1774
+ logger5.info(`Wallet address derived: ${this.config.world.walletAddress}`);
1775
+ } catch (error) {
1776
+ logger5.warn(`Failed to derive wallet address: ${error.message}`);
1777
+ }
1778
+ }
1725
1779
  this.initLLM();
1726
1780
  this.registerActions();
1727
1781
  await this.initSocialAdapters();
@@ -1730,7 +1784,7 @@ var Agent = class {
1730
1784
  await this.hooks.onInit(this);
1731
1785
  }
1732
1786
  await this.postStartupMessages();
1733
- logger4.info(`Agent initialized: ${this.config.name}`);
1787
+ logger5.info(`Agent initialized: ${this.config.name}`);
1734
1788
  }
1735
1789
  async start() {
1736
1790
  if (this.state !== "initializing" && this.state !== "idle") {
@@ -1740,7 +1794,7 @@ var Agent = class {
1740
1794
  await this.init();
1741
1795
  }
1742
1796
  this.state = "running";
1743
- logger4.info(`Agent started: ${this.config.name}`);
1797
+ logger5.info(`Agent started: ${this.config.name}`);
1744
1798
  if (this.hooks.onStart) {
1745
1799
  await this.hooks.onStart(this);
1746
1800
  }
@@ -1754,7 +1808,7 @@ var Agent = class {
1754
1808
  }
1755
1809
  async stop() {
1756
1810
  this.state = "stopping";
1757
- logger4.info(`Stopping agent: ${this.config.name}`);
1811
+ logger5.info(`Stopping agent: ${this.config.name}`);
1758
1812
  if (this.tickTimer) {
1759
1813
  clearInterval(this.tickTimer);
1760
1814
  this.tickTimer = void 0;
@@ -1767,7 +1821,7 @@ var Agent = class {
1767
1821
  await this.hooks.onShutdown(this);
1768
1822
  }
1769
1823
  this.state = "stopped";
1770
- logger4.info(`Agent stopped: ${this.config.name}`);
1824
+ logger5.info(`Agent stopped: ${this.config.name}`);
1771
1825
  }
1772
1826
  // ── Decision Loop ──
1773
1827
  async think() {
@@ -1787,7 +1841,7 @@ var Agent = class {
1787
1841
  },
1788
1842
  { systemPrompt: this.systemPrompt, temperature: this.config.llm.temperature }
1789
1843
  );
1790
- logger4.debug(`Decision: ${decision.action} \u2014 ${decision.reasoning}`);
1844
+ logger5.debug(`Decision: ${decision.action} \u2014 ${decision.reasoning}`);
1791
1845
  return decision;
1792
1846
  }
1793
1847
  async act(actionName, parameters = {}) {
@@ -1810,17 +1864,17 @@ var Agent = class {
1810
1864
  await this.hooks.onTick(this);
1811
1865
  }
1812
1866
  if (this.isSleeping()) {
1813
- logger4.info(`Tick #${this.tickCount}: Sleeping \u2014 skipped`);
1867
+ logger5.info(`Tick #${this.tickCount}: Sleeping \u2014 skipped`);
1814
1868
  return;
1815
1869
  }
1816
- logger4.info(`Tick #${this.tickCount}: Thinking...`);
1870
+ logger5.info(`Tick #${this.tickCount}: Thinking...`);
1817
1871
  const decision = await this.think();
1818
- logger4.info(`Tick #${this.tickCount}: Decision \u2192 ${decision.action} | Reasoning: ${decision.reasoning}`);
1872
+ logger5.info(`Tick #${this.tickCount}: Decision \u2192 ${decision.action} | Reasoning: ${decision.reasoning}`);
1819
1873
  if (decision.parameters && Object.keys(decision.parameters).length > 0) {
1820
- logger4.info(`Tick #${this.tickCount}: Parameters \u2192 ${JSON.stringify(decision.parameters)}`);
1874
+ logger5.info(`Tick #${this.tickCount}: Parameters \u2192 ${JSON.stringify(decision.parameters)}`);
1821
1875
  }
1822
1876
  const result = await this.act(decision.action, decision.parameters);
1823
- logger4.info(`Tick #${this.tickCount}: Result \u2192 success=${result.success}${result.data ? ` data=${JSON.stringify(result.data).slice(0, 200)}` : ""}`);
1877
+ logger5.info(`Tick #${this.tickCount}: Result \u2192 success=${result.success}${result.data ? ` data=${JSON.stringify(result.data).slice(0, 200)}` : ""}`);
1824
1878
  this.recentActions.push({
1825
1879
  action: decision.action,
1826
1880
  reasoning: decision.reasoning,
@@ -1838,7 +1892,7 @@ var Agent = class {
1838
1892
  await this.fireWebhook("onAction", decision, result);
1839
1893
  }
1840
1894
  } catch (error) {
1841
- logger4.error(`Tick #${this.tickCount} error: ${error instanceof Error ? error.message : error}`);
1895
+ logger5.error(`Tick #${this.tickCount} error: ${error instanceof Error ? error.message : error}`);
1842
1896
  if (this.hooks.onError && error instanceof Error) {
1843
1897
  await this.hooks.onError(error, this);
1844
1898
  }
@@ -1878,7 +1932,7 @@ var Agent = class {
1878
1932
  this.actionRegistry.register(action);
1879
1933
  }
1880
1934
  }
1881
- logger4.info(`Registered ${moltbookActions.length} Moltbook actions`);
1935
+ logger5.info(`Registered ${moltbookActions.length} Moltbook actions`);
1882
1936
  }
1883
1937
  const a2a = this.config.a2a;
1884
1938
  if (a2a && a2a.enabled !== false) {
@@ -1898,7 +1952,7 @@ var Agent = class {
1898
1952
  this.actionRegistry.register(action);
1899
1953
  }
1900
1954
  }
1901
- logger4.info(`Registered ${peerActions.length} A2A peer actions`);
1955
+ logger5.info(`Registered ${peerActions.length} A2A peer actions`);
1902
1956
  } else {
1903
1957
  const genericAction = createA2ACommunicationAction({
1904
1958
  defaultAgentUrl: a2a.defaultPeerUrl,
@@ -1908,7 +1962,7 @@ var Agent = class {
1908
1962
  if (!this.actionRegistry.has(genericAction.name)) {
1909
1963
  this.actionRegistry.register(genericAction);
1910
1964
  }
1911
- logger4.info(`Registered generic A2A action: ${genericAction.name}`);
1965
+ logger5.info(`Registered generic A2A action: ${genericAction.name}`);
1912
1966
  }
1913
1967
  }
1914
1968
  const world = this.config.world;
@@ -1925,7 +1979,7 @@ var Agent = class {
1925
1979
  this.actionRegistry.register(action);
1926
1980
  }
1927
1981
  }
1928
- logger4.info(`Registered 4 world actions (world: ${worldUrl})`);
1982
+ logger5.info(`Registered 4 world actions (world: ${worldUrl})`);
1929
1983
  }
1930
1984
  if (this.config.customActions) {
1931
1985
  for (const action of this.config.customActions) {
@@ -1938,7 +1992,7 @@ var Agent = class {
1938
1992
  await this.initMoltbook(social);
1939
1993
  await this.initTwitter(social);
1940
1994
  if (Object.keys(this.socialAdapters).length === 0) {
1941
- logger4.warn("Social: No adapters connected. Set MOLTBOOK_API_KEY or Twitter env vars in your .env to enable.");
1995
+ logger5.warn("Social: No adapters connected. Set MOLTBOOK_API_KEY or Twitter env vars in your .env to enable.");
1942
1996
  }
1943
1997
  }
1944
1998
  async initMoltbook(social) {
@@ -1949,13 +2003,13 @@ var Agent = class {
1949
2003
  const explicitlyDisabled = configMoltbook && configMoltbook.enabled === false && !envKey;
1950
2004
  const shouldConnect = !isPlaceholder && !explicitlyDisabled;
1951
2005
  if (explicitlyDisabled) {
1952
- logger4.info("Moltbook: Disabled in config and no MOLTBOOK_API_KEY in env \u2014 skipping");
2006
+ logger5.info("Moltbook: Disabled in config and no MOLTBOOK_API_KEY in env \u2014 skipping");
1953
2007
  return;
1954
2008
  }
1955
2009
  if (isPlaceholder) {
1956
2010
  if (configMoltbook?.enabled || envKey) {
1957
- logger4.warn("Moltbook: MOLTBOOK_API_KEY is missing or still a placeholder.");
1958
- logger4.warn(" Fix: Set a valid MOLTBOOK_API_KEY in your .env file.");
2011
+ logger5.warn("Moltbook: MOLTBOOK_API_KEY is missing or still a placeholder.");
2012
+ logger5.warn(" Fix: Set a valid MOLTBOOK_API_KEY in your .env file.");
1959
2013
  }
1960
2014
  return;
1961
2015
  }
@@ -1973,16 +2027,16 @@ var Agent = class {
1973
2027
  ...configMoltbook?.apiKey ? {} : { apiKey },
1974
2028
  ...configMoltbook?.baseUrl ? {} : { baseUrl }
1975
2029
  };
1976
- logger4.info(`Moltbook: API key detected from ${source}`);
1977
- logger4.info(`Moltbook: Connecting to ${baseUrl} ...`);
2030
+ logger5.info(`Moltbook: API key detected from ${source}`);
2031
+ logger5.info(`Moltbook: Connecting to ${baseUrl} ...`);
1978
2032
  const adapter = new MoltbookAdapter(effectiveConfig);
1979
2033
  try {
1980
2034
  await adapter.connect();
1981
2035
  this.socialAdapters["moltbook"] = adapter;
1982
2036
  social.moltbook = effectiveConfig;
1983
- logger4.info(`Moltbook: Connected successfully (submolt: ${defaultSubmolt})`);
2037
+ logger5.info(`Moltbook: Connected successfully (submolt: ${defaultSubmolt})`);
1984
2038
  } catch (error) {
1985
- logger4.error(`Moltbook: Connection FAILED \u2014 ${error.message || error}`);
2039
+ logger5.error(`Moltbook: Connection FAILED \u2014 ${error.message || error}`);
1986
2040
  this.logPlatformError("Moltbook", error);
1987
2041
  }
1988
2042
  }
@@ -2001,23 +2055,23 @@ var Agent = class {
2001
2055
  const hasAllCreds = hasKey && apiSecret && accessToken && accessSecret;
2002
2056
  const explicitlyDisabled = configTwitter && configTwitter.enabled === false && !envApiKey;
2003
2057
  if (explicitlyDisabled) {
2004
- logger4.info("Twitter: Disabled in config and no TWITTER_API_KEY in env \u2014 skipping");
2058
+ logger5.info("Twitter: Disabled in config and no TWITTER_API_KEY in env \u2014 skipping");
2005
2059
  return;
2006
2060
  }
2007
2061
  if (!hasKey) {
2008
2062
  if (configTwitter?.enabled || envApiKey) {
2009
- logger4.warn("Twitter: Credentials are missing or still placeholders.");
2010
- logger4.warn(" Fix: Set valid Twitter keys in your .env file.");
2063
+ logger5.warn("Twitter: Credentials are missing or still placeholders.");
2064
+ logger5.warn(" Fix: Set valid Twitter keys in your .env file.");
2011
2065
  }
2012
2066
  return;
2013
2067
  }
2014
2068
  if (!hasAllCreds) {
2015
- logger4.warn("Twitter: Some credentials are missing. Need: TWITTER_API_KEY, TWITTER_API_SECRET, TWITTER_ACCESS_TOKEN, TWITTER_ACCESS_SECRET");
2069
+ logger5.warn("Twitter: Some credentials are missing. Need: TWITTER_API_KEY, TWITTER_API_SECRET, TWITTER_ACCESS_TOKEN, TWITTER_ACCESS_SECRET");
2016
2070
  return;
2017
2071
  }
2018
2072
  const source = creds?.apiKey ? "config" : "environment";
2019
- logger4.info(`Twitter: Credentials detected from ${source}`);
2020
- logger4.info("Twitter: Connecting...");
2073
+ logger5.info(`Twitter: Credentials detected from ${source}`);
2074
+ logger5.info("Twitter: Connecting...");
2021
2075
  const effectiveConfig = {
2022
2076
  enabled: true,
2023
2077
  ...configTwitter,
@@ -2028,16 +2082,16 @@ var Agent = class {
2028
2082
  await adapter.connect();
2029
2083
  this.socialAdapters["twitter"] = adapter;
2030
2084
  social.twitter = effectiveConfig;
2031
- logger4.info("Twitter: Connected successfully");
2085
+ logger5.info("Twitter: Connected successfully");
2032
2086
  } catch (error) {
2033
- logger4.error(`Twitter: Connection FAILED \u2014 ${error.message || error}`);
2087
+ logger5.error(`Twitter: Connection FAILED \u2014 ${error.message || error}`);
2034
2088
  this.logPlatformError("Twitter", error);
2035
2089
  }
2036
2090
  }
2037
2091
  async postStartupMessages() {
2038
2092
  const adapters = Object.entries(this.socialAdapters);
2039
2093
  if (adapters.length === 0) {
2040
- logger4.info("Startup post: No connected social adapters \u2014 skipping");
2094
+ logger5.info("Startup post: No connected social adapters \u2014 skipping");
2041
2095
  return;
2042
2096
  }
2043
2097
  let content;
@@ -2052,18 +2106,18 @@ Write only the post content, nothing else. Keep it concise and natural.`;
2052
2106
  temperature: this.config.llm.temperature ?? 0.8,
2053
2107
  maxTokens: 280
2054
2108
  })).trim();
2055
- logger4.info(`Startup post: LLM generated content (${content.length} chars)`);
2109
+ logger5.info(`Startup post: LLM generated content (${content.length} chars)`);
2056
2110
  } catch (error) {
2057
- logger4.warn(`Startup post: LLM generation failed (${error.message}), using fallback`);
2111
+ logger5.warn(`Startup post: LLM generation failed (${error.message}), using fallback`);
2058
2112
  content = `${this.config.name} is now online and ready.`;
2059
2113
  }
2060
2114
  for (const [platform, adapter] of adapters) {
2061
- logger4.info(`Startup post: Posting to ${platform}...`);
2115
+ logger5.info(`Startup post: Posting to ${platform}...`);
2062
2116
  try {
2063
2117
  const result = await adapter.post(content);
2064
- logger4.info(`Startup post: ${platform} SUCCESS \u2014 id=${result.id}${result.url ? ` url=${result.url}` : ""}`);
2118
+ logger5.info(`Startup post: ${platform} SUCCESS \u2014 id=${result.id}${result.url ? ` url=${result.url}` : ""}`);
2065
2119
  } catch (error) {
2066
- logger4.error(`Startup post: ${platform} FAILED \u2014 ${error.message || error}`);
2120
+ logger5.error(`Startup post: ${platform} FAILED \u2014 ${error.message || error}`);
2067
2121
  this.logPlatformError(platform, error);
2068
2122
  }
2069
2123
  }
@@ -2086,7 +2140,7 @@ Write only the post content, nothing else. Keep it concise and natural.`;
2086
2140
  await this.scheduledPost("moltbook");
2087
2141
  }
2088
2142
  });
2089
- logger4.info(`Scheduler: Moltbook posting every ${formatInterval(intervalMs)}`);
2143
+ logger5.info(`Scheduler: Moltbook posting every ${formatInterval(intervalMs)}`);
2090
2144
  }
2091
2145
  }
2092
2146
  }
@@ -2102,7 +2156,7 @@ Write only the post content, nothing else. Keep it concise and natural.`;
2102
2156
  await this.scheduledPost("twitter");
2103
2157
  }
2104
2158
  });
2105
- logger4.info(`Scheduler: Twitter posting every ${formatInterval(intervalMs)}`);
2159
+ logger5.info(`Scheduler: Twitter posting every ${formatInterval(intervalMs)}`);
2106
2160
  }
2107
2161
  }
2108
2162
  }
@@ -2118,7 +2172,7 @@ Write only the post content, nothing else. Keep it concise and natural.`;
2118
2172
  await this.executeScheduledTask(task);
2119
2173
  }
2120
2174
  });
2121
- logger4.info(`Scheduler: "${task.name}" every ${formatInterval(task.intervalMs)}`);
2175
+ logger5.info(`Scheduler: "${task.name}" every ${formatInterval(task.intervalMs)}`);
2122
2176
  }
2123
2177
  }
2124
2178
  async scheduledPost(platform) {
@@ -2134,15 +2188,15 @@ Write only the post content, nothing else. Keep it concise and natural.`;
2134
2188
  maxTokens: 280
2135
2189
  });
2136
2190
  const result = await adapter.post(content.trim());
2137
- logger4.info(`Scheduled post: ${platform} SUCCESS \u2014 id=${result.id}`);
2191
+ logger5.info(`Scheduled post: ${platform} SUCCESS \u2014 id=${result.id}`);
2138
2192
  } catch (error) {
2139
- logger4.error(`Scheduled post: ${platform} FAILED \u2014 ${error.message || error}`);
2193
+ logger5.error(`Scheduled post: ${platform} FAILED \u2014 ${error.message || error}`);
2140
2194
  this.logPlatformError(platform, error);
2141
2195
  }
2142
2196
  }
2143
2197
  async executeScheduledTask(task) {
2144
2198
  try {
2145
- logger4.info(`Scheduled task: Running "${task.name}"`);
2199
+ logger5.info(`Scheduled task: Running "${task.name}"`);
2146
2200
  const prompt = `You are ${this.config.name}, an autonomous agent. Execute the following scheduled task.
2147
2201
 
2148
2202
  Task: ${task.name}
@@ -2167,74 +2221,74 @@ Decide what action to take. Respond with JSON:
2167
2221
  { systemPrompt: this.systemPrompt, temperature: this.config.llm.temperature }
2168
2222
  );
2169
2223
  const result = await this.act(decision.action, decision.parameters);
2170
- logger4.info(`Scheduled task: "${task.name}" completed \u2014 action=${decision.action}, success=${result.success}`);
2224
+ logger5.info(`Scheduled task: "${task.name}" completed \u2014 action=${decision.action}, success=${result.success}`);
2171
2225
  } catch (error) {
2172
- logger4.error(`Scheduled task: "${task.name}" FAILED \u2014 ${error.message || error}`);
2226
+ logger5.error(`Scheduled task: "${task.name}" FAILED \u2014 ${error.message || error}`);
2173
2227
  }
2174
2228
  }
2175
2229
  logPlatformError(platform, error) {
2176
2230
  if (!error.response) {
2177
2231
  if (error.code === "ENOTFOUND") {
2178
- logger4.error(` ${platform}: DNS lookup failed \u2014 check the base URL.`);
2232
+ logger5.error(` ${platform}: DNS lookup failed \u2014 check the base URL.`);
2179
2233
  } else if (error.code === "ECONNREFUSED") {
2180
- logger4.error(` ${platform}: Connection refused \u2014 is the server running?`);
2234
+ logger5.error(` ${platform}: Connection refused \u2014 is the server running?`);
2181
2235
  } else if (error.code === "ETIMEDOUT" || error.code === "ECONNABORTED") {
2182
- logger4.error(` ${platform}: Request timed out.`);
2236
+ logger5.error(` ${platform}: Request timed out.`);
2183
2237
  } else {
2184
- logger4.error(` ${platform}: Network error (${error.code || "unknown"})`);
2238
+ logger5.error(` ${platform}: Network error (${error.code || "unknown"})`);
2185
2239
  }
2186
2240
  return;
2187
2241
  }
2188
2242
  const status = error.response.status;
2189
2243
  const data = error.response.data;
2190
- logger4.error(` ${platform}: HTTP ${status}`);
2244
+ logger5.error(` ${platform}: HTTP ${status}`);
2191
2245
  if (data) {
2192
- if (data.error) logger4.error(` ${platform}: API error: ${data.error}`);
2193
- if (data.hint) logger4.error(` ${platform}: API hint: ${data.hint}`);
2194
- if (!data.error && !data.hint) logger4.error(` ${platform}: Response: ${JSON.stringify(data)}`);
2246
+ if (data.error) logger5.error(` ${platform}: API error: ${data.error}`);
2247
+ if (data.hint) logger5.error(` ${platform}: API hint: ${data.hint}`);
2248
+ if (!data.error && !data.hint) logger5.error(` ${platform}: Response: ${JSON.stringify(data)}`);
2195
2249
  }
2196
2250
  if (status === 401) {
2197
- logger4.error(` ${platform}: Your API key was rejected. Verify it is correct and the agent is claimed.`);
2251
+ logger5.error(` ${platform}: Your API key was rejected. Verify it is correct and the agent is claimed.`);
2198
2252
  } else if (status === 403) {
2199
- logger4.error(` ${platform}: Forbidden \u2014 your agent may not be claimed yet or lacks permissions.`);
2253
+ logger5.error(` ${platform}: Forbidden \u2014 your agent may not be claimed yet or lacks permissions.`);
2200
2254
  } else if (status === 429) {
2201
2255
  const retryMin = data?.retry_after_minutes;
2202
2256
  const retrySec = data?.retry_after_seconds;
2203
2257
  if (retryMin) {
2204
- logger4.error(` ${platform}: Rate limited \u2014 try again in ${retryMin} minute(s).`);
2258
+ logger5.error(` ${platform}: Rate limited \u2014 try again in ${retryMin} minute(s).`);
2205
2259
  } else if (retrySec) {
2206
- logger4.error(` ${platform}: Rate limited \u2014 try again in ${retrySec} second(s).`);
2260
+ logger5.error(` ${platform}: Rate limited \u2014 try again in ${retrySec} second(s).`);
2207
2261
  } else {
2208
- logger4.error(` ${platform}: Rate limited \u2014 wait before retrying.`);
2262
+ logger5.error(` ${platform}: Rate limited \u2014 wait before retrying.`);
2209
2263
  }
2210
2264
  } else if (status === 404) {
2211
- logger4.error(` ${platform}: Endpoint not found \u2014 check the base URL.`);
2265
+ logger5.error(` ${platform}: Endpoint not found \u2014 check the base URL.`);
2212
2266
  } else if (status >= 500) {
2213
- logger4.error(` ${platform}: Server error \u2014 the platform may be temporarily down.`);
2267
+ logger5.error(` ${platform}: Server error \u2014 the platform may be temporarily down.`);
2214
2268
  }
2215
2269
  }
2216
2270
  async autoJoinWorld() {
2217
2271
  const worldUrl = this.config.world.url;
2218
- logger4.info(`Auto-joining world: ${worldUrl}`);
2272
+ logger5.info(`Auto-joining world: ${worldUrl}`);
2219
2273
  try {
2220
2274
  const result = await this.act("join_world", {
2221
2275
  worldUrl,
2222
2276
  walletAddress: this.config.world.walletAddress
2223
2277
  });
2224
2278
  if (result.success) {
2225
- logger4.info(`Successfully joined world: ${worldUrl}`);
2279
+ logger5.info(`Successfully joined world: ${worldUrl}`);
2226
2280
  } else {
2227
- logger4.warn(`Failed to join world: ${result.error}`);
2281
+ logger5.warn(`Failed to join world: ${result.error}`);
2228
2282
  }
2229
2283
  } catch (error) {
2230
- logger4.warn(`Auto-join world failed: ${error?.message || error}`);
2284
+ logger5.warn(`Auto-join world failed: ${error?.message || error}`);
2231
2285
  }
2232
2286
  }
2233
2287
  startAutonomousLoop() {
2234
2288
  const actionsPerHour = typeof this.config.behaviors.actionsPerHour === "function" ? this.config.behaviors.actionsPerHour({}) : this.config.behaviors.actionsPerHour || 5;
2235
2289
  const intervalMs = Math.floor(36e5 / actionsPerHour);
2236
2290
  this.tickTimer = setInterval(() => this.tick(), intervalMs);
2237
- logger4.info(`Autonomous loop started: ~${actionsPerHour} actions/hour (every ${intervalMs}ms)`);
2291
+ logger5.info(`Autonomous loop started: ~${actionsPerHour} actions/hour (every ${intervalMs}ms)`);
2238
2292
  }
2239
2293
  isSleeping() {
2240
2294
  const schedule = this.config.behaviors.sleepSchedule;
@@ -2269,7 +2323,7 @@ Decide what action to take. Respond with JSON:
2269
2323
  await axios2.post(hook, { event, data: args });
2270
2324
  }
2271
2325
  } catch (error) {
2272
- logger4.error(`Webhook ${event} failed: ${error}`);
2326
+ logger5.error(`Webhook ${event} failed: ${error}`);
2273
2327
  }
2274
2328
  }
2275
2329
  };
@@ -2409,10 +2463,18 @@ var MarkdownParser = class {
2409
2463
  const fields = this.parseKeyValueLines(section.content);
2410
2464
  const url = fields["url"];
2411
2465
  if (!url) return void 0;
2466
+ let privateKey;
2467
+ const pkField = fields["wallet_private_key"];
2468
+ if (pkField === "env") {
2469
+ privateKey = process.env.AGENT_WALLET_PRIVATE_KEY;
2470
+ } else if (pkField && pkField.startsWith("0x")) {
2471
+ privateKey = pkField;
2472
+ }
2412
2473
  return {
2413
2474
  url,
2414
2475
  autoJoin: fields["auto_join"] !== "false",
2415
- ...fields["wallet_address"] ? { walletAddress: fields["wallet_address"] } : {}
2476
+ ...fields["wallet_address"] ? { walletAddress: fields["wallet_address"] } : {},
2477
+ ...privateKey ? { privateKey } : {}
2416
2478
  };
2417
2479
  }
2418
2480
  parseSleepSchedule(value) {
@@ -2587,7 +2649,7 @@ var ConfigLoader = class {
2587
2649
  };
2588
2650
 
2589
2651
  // src/memory/longterm.ts
2590
- var logger5 = createLogger("LongTermMemory");
2652
+ var logger6 = createLogger("LongTermMemory");
2591
2653
  var LongTermMemory = class extends Memory {
2592
2654
  redisConfig;
2593
2655
  postgresConfig;
@@ -2763,9 +2825,9 @@ var LongTermMemory = class extends Memory {
2763
2825
  try {
2764
2826
  const { default: Redis } = await import("ioredis");
2765
2827
  this.redis = new Redis(this.redisConfig.url);
2766
- logger5.info("Redis connection established");
2828
+ logger6.info("Redis connection established");
2767
2829
  } catch (error) {
2768
- logger5.error(`Failed to connect to Redis: ${error}`);
2830
+ logger6.error(`Failed to connect to Redis: ${error}`);
2769
2831
  throw error;
2770
2832
  }
2771
2833
  }
@@ -2778,9 +2840,9 @@ var LongTermMemory = class extends Memory {
2778
2840
  connectionString: this.postgresConfig.url
2779
2841
  });
2780
2842
  await this.pg.query("SELECT 1");
2781
- logger5.info("Postgres connection established");
2843
+ logger6.info("Postgres connection established");
2782
2844
  } catch (error) {
2783
- logger5.error(`Failed to connect to Postgres: ${error}`);
2845
+ logger6.error(`Failed to connect to Postgres: ${error}`);
2784
2846
  throw error;
2785
2847
  }
2786
2848
  }
@@ -2922,13 +2984,13 @@ function createRoutes(agent) {
2922
2984
  }
2923
2985
 
2924
2986
  // src/server/middleware.ts
2925
- var logger6 = createLogger("Server");
2987
+ var logger7 = createLogger("Server");
2926
2988
  function requestLogger(req, _res, next) {
2927
- logger6.debug(`${req.method} ${req.path}`);
2989
+ logger7.debug(`${req.method} ${req.path}`);
2928
2990
  next();
2929
2991
  }
2930
2992
  function errorHandler(err, _req, res, _next) {
2931
- logger6.error(`Server error: ${err.message}`);
2993
+ logger7.error(`Server error: ${err.message}`);
2932
2994
  res.status(500).json({ error: err.message });
2933
2995
  }
2934
2996
  function authMiddleware(req, res, next) {
@@ -2946,7 +3008,7 @@ function authMiddleware(req, res, next) {
2946
3008
  }
2947
3009
 
2948
3010
  // src/a2a/AgentCardBuilder.ts
2949
- var logger7 = createLogger("AgentCardBuilder");
3011
+ var logger8 = createLogger("AgentCardBuilder");
2950
3012
  var AgentCardBuilder = class {
2951
3013
  /**
2952
3014
  * Creates an A2A AgentCard from Moltium configuration.
@@ -2968,7 +3030,7 @@ var AgentCardBuilder = class {
2968
3030
  name: config.name,
2969
3031
  description: config.personality.bio || `${config.name} - An autonomous AI agent`,
2970
3032
  protocolVersion: "0.3.0",
2971
- version: "0.1.28",
3033
+ version: "0.1.30",
2972
3034
  url: `${baseUrl}/a2a/jsonrpc`,
2973
3035
  skills,
2974
3036
  capabilities,
@@ -2979,7 +3041,7 @@ var AgentCardBuilder = class {
2979
3041
  { url: `${baseUrl}/a2a/rest`, transport: "HTTP+JSON" }
2980
3042
  ]
2981
3043
  };
2982
- logger7.debug("Built A2A AgentCard", {
3044
+ logger8.debug("Built A2A AgentCard", {
2983
3045
  name: agentCard.name,
2984
3046
  skillCount: skills.length,
2985
3047
  baseUrl
@@ -3062,7 +3124,7 @@ var AgentCardBuilder = class {
3062
3124
 
3063
3125
  // src/a2a/MoltiumExecutor.ts
3064
3126
  import { v4 as uuidv42 } from "uuid";
3065
- var logger8 = createLogger("MoltiumExecutor");
3127
+ var logger9 = createLogger("MoltiumExecutor");
3066
3128
  var MoltiumExecutor = class {
3067
3129
  agent;
3068
3130
  cancelledTasks = /* @__PURE__ */ new Set();
@@ -3076,7 +3138,7 @@ var MoltiumExecutor = class {
3076
3138
  async execute(requestContext, eventBus) {
3077
3139
  const { taskId, contextId, userMessage, task } = requestContext;
3078
3140
  try {
3079
- logger8.info(`[A2A] Executing request for task ${taskId}`);
3141
+ logger9.info(`[A2A] Executing request for task ${taskId}`);
3080
3142
  if (!task) {
3081
3143
  const initialTask = {
3082
3144
  kind: "task",
@@ -3114,9 +3176,9 @@ var MoltiumExecutor = class {
3114
3176
  }
3115
3177
  this.publishStatusUpdate(taskId, contextId, "completed", eventBus, true);
3116
3178
  eventBus.finished();
3117
- logger8.info(`[A2A] Task ${taskId} completed successfully`);
3179
+ logger9.info(`[A2A] Task ${taskId} completed successfully`);
3118
3180
  } catch (error) {
3119
- logger8.error(`[A2A] Task ${taskId} failed`, {
3181
+ logger9.error(`[A2A] Task ${taskId} failed`, {
3120
3182
  error: error instanceof Error ? error.message : String(error)
3121
3183
  });
3122
3184
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -3131,7 +3193,7 @@ var MoltiumExecutor = class {
3131
3193
  * Handles task cancellation requests.
3132
3194
  */
3133
3195
  async cancelTask(taskId, eventBus) {
3134
- logger8.info(`[A2A] Cancellation requested for task ${taskId}`);
3196
+ logger9.info(`[A2A] Cancellation requested for task ${taskId}`);
3135
3197
  this.cancelledTasks.add(taskId);
3136
3198
  }
3137
3199
  /**
@@ -3293,7 +3355,7 @@ var MoltiumExecutor = class {
3293
3355
  * Publishes a cancellation status.
3294
3356
  */
3295
3357
  publishCancellation(taskId, contextId, eventBus) {
3296
- logger8.info(`[A2A] Publishing cancellation for task ${taskId}`);
3358
+ logger9.info(`[A2A] Publishing cancellation for task ${taskId}`);
3297
3359
  this.publishStatusUpdate(taskId, contextId, "canceled", eventBus, true);
3298
3360
  eventBus.finished();
3299
3361
  this.cancelledTasks.delete(taskId);
@@ -3302,7 +3364,7 @@ var MoltiumExecutor = class {
3302
3364
 
3303
3365
  // src/a2a/integration.ts
3304
3366
  import { DefaultRequestHandler, InMemoryTaskStore, JsonRpcTransportHandler } from "@a2a-js/sdk/server";
3305
- var logger9 = createLogger("A2AIntegration");
3367
+ var logger10 = createLogger("A2AIntegration");
3306
3368
  var A2AIntegration = class {
3307
3369
  agent;
3308
3370
  agentCard;
@@ -3317,7 +3379,7 @@ var A2AIntegration = class {
3317
3379
  new InMemoryTaskStore(),
3318
3380
  this.moltiumExecutor
3319
3381
  );
3320
- logger9.info("A2A integration initialized", {
3382
+ logger10.info("A2A integration initialized", {
3321
3383
  agentName: agent.name,
3322
3384
  baseUrl: options.a2aConfig.baseUrl
3323
3385
  });
@@ -3339,7 +3401,7 @@ var A2AIntegration = class {
3339
3401
  const response = await jsonRpcHandler.handle(req.body);
3340
3402
  res.json(response);
3341
3403
  } catch (error) {
3342
- logger9.error("JSON-RPC error:", error);
3404
+ logger10.error("JSON-RPC error:", error);
3343
3405
  res.status(500).json({
3344
3406
  jsonrpc: "2.0",
3345
3407
  error: {
@@ -3370,7 +3432,7 @@ var A2AIntegration = class {
3370
3432
  new InMemoryTaskStore(),
3371
3433
  this.moltiumExecutor
3372
3434
  );
3373
- logger9.info("A2A agent card updated with runtime info", {
3435
+ logger10.info("A2A agent card updated with runtime info", {
3374
3436
  host: actualHost,
3375
3437
  port: actualPort,
3376
3438
  url: this.agentCard.url
@@ -3388,10 +3450,10 @@ var A2AIntegration = class {
3388
3450
  logEndpoints(host, port) {
3389
3451
  const protocol = host === "localhost" || host === "127.0.0.1" ? "http" : "https";
3390
3452
  const baseUrl = `${protocol}://${host}:${port}`;
3391
- logger9.info("A2A endpoints available:");
3392
- logger9.info(` Agent Card: ${baseUrl}/.well-known/agent.json`);
3393
- logger9.info(` JSON-RPC: ${baseUrl}/a2a/jsonrpc`);
3394
- logger9.info(` HTTP+JSON: ${baseUrl}/a2a/rest`);
3453
+ logger10.info("A2A endpoints available:");
3454
+ logger10.info(` Agent Card: ${baseUrl}/.well-known/agent.json`);
3455
+ logger10.info(` JSON-RPC: ${baseUrl}/a2a/jsonrpc`);
3456
+ logger10.info(` HTTP+JSON: ${baseUrl}/a2a/rest`);
3395
3457
  }
3396
3458
  };
3397
3459
  function createA2AIntegration(agent, options = {}) {
@@ -3406,7 +3468,7 @@ function createA2AIntegration(agent, options = {}) {
3406
3468
  }
3407
3469
 
3408
3470
  // src/server/app.ts
3409
- var logger10 = createLogger("Server");
3471
+ var logger11 = createLogger("Server");
3410
3472
  var AGENT_CARD_PATH = ".well-known/agent.json";
3411
3473
  function createApp(agent, options = {}) {
3412
3474
  const app = express();
@@ -3432,9 +3494,10 @@ function createApp(agent, options = {}) {
3432
3494
  });
3433
3495
  const handlers = a2aIntegration.getHandlers();
3434
3496
  app.use(`/${AGENT_CARD_PATH}`, handlers.agentCard);
3497
+ app.use("/.well-known/agent-card.json", handlers.agentCard);
3435
3498
  app.use("/a2a/jsonrpc", handlers.jsonRpc);
3436
3499
  app.use("/a2a/rest", handlers.rest);
3437
- logger10.info("A2A protocol endpoints enabled");
3500
+ logger11.info("A2A protocol endpoints enabled");
3438
3501
  }
3439
3502
  app.use(errorHandler);
3440
3503
  return app;
@@ -3445,22 +3508,22 @@ async function startServer(agent, options = {}) {
3445
3508
  const app = createApp(agent, options);
3446
3509
  await new Promise((resolve2) => {
3447
3510
  app.listen(port, host, () => {
3448
- logger10.info(`Agent "${agent.name}" running at http://${host}:${port}`);
3511
+ logger11.info(`Agent "${agent.name}" running at http://${host}:${port}`);
3449
3512
  if (options.enableA2A !== false) {
3450
3513
  const logHost = host === "0.0.0.0" ? "localhost" : host;
3451
3514
  const protocol = logHost === "localhost" || logHost === "127.0.0.1" ? "http" : "https";
3452
3515
  const baseUrl = `${protocol}://${logHost}:${port}`;
3453
- logger10.info("A2A Protocol Endpoints:");
3454
- logger10.info(` Agent Card: ${baseUrl}/.well-known/agent.json`);
3455
- logger10.info(` JSON-RPC: ${baseUrl}/a2a/jsonrpc`);
3456
- logger10.info(` HTTP+JSON: ${baseUrl}/a2a/rest`);
3516
+ logger11.info("A2A Protocol Endpoints:");
3517
+ logger11.info(` Agent Card: ${baseUrl}/.well-known/agent.json`);
3518
+ logger11.info(` JSON-RPC: ${baseUrl}/a2a/jsonrpc`);
3519
+ logger11.info(` HTTP+JSON: ${baseUrl}/a2a/rest`);
3457
3520
  }
3458
3521
  resolve2();
3459
3522
  });
3460
3523
  });
3461
3524
  await agent.start();
3462
3525
  const shutdown = async () => {
3463
- logger10.info("Received shutdown signal");
3526
+ logger11.info("Received shutdown signal");
3464
3527
  await agent.stop();
3465
3528
  process.exit(0);
3466
3529
  };
@@ -3474,6 +3537,7 @@ export {
3474
3537
  ActionRegistry,
3475
3538
  Agent,
3476
3539
  AgentCardBuilder,
3540
+ AgentWallet,
3477
3541
  AnthropicProvider,
3478
3542
  ConfigLoader,
3479
3543
  LLMProvider,