@moltium/core 0.1.4 → 0.1.5

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.d.cts CHANGED
@@ -6,6 +6,7 @@ interface MoltbookConfig {
6
6
  enabled: boolean;
7
7
  apiKey: string;
8
8
  baseUrl?: string;
9
+ defaultSubmolt?: string;
9
10
  postFrequency?: 'realtime' | 'hourly' | 'daily';
10
11
  engagementRate?: 'low' | 'medium' | 'high';
11
12
  autoReply?: boolean;
@@ -370,6 +371,8 @@ declare class Agent {
370
371
  private initLLM;
371
372
  private registerActions;
372
373
  private initSocialAdapters;
374
+ private postStartupMessages;
375
+ private logPlatformError;
373
376
  private startAutonomousLoop;
374
377
  private isSleeping;
375
378
  private gatherContext;
@@ -510,10 +513,10 @@ declare class MoltbookAdapter extends SocialAdapter {
510
513
  post(content: string): Promise<PostResult>;
511
514
  reply(postId: string, content: string): Promise<ReplyResult>;
512
515
  like(postId: string): Promise<void>;
513
- follow(userId: string): Promise<void>;
516
+ follow(agentName: string): Promise<void>;
514
517
  getMentions(): Promise<Mention[]>;
515
518
  getFeed(options?: FeedOptions): Promise<Post[]>;
516
- getProfile(userId: string): Promise<Profile>;
519
+ getProfile(agentName: string): Promise<Profile>;
517
520
  }
518
521
 
519
522
  declare class TwitterAdapter extends SocialAdapter {
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ interface MoltbookConfig {
6
6
  enabled: boolean;
7
7
  apiKey: string;
8
8
  baseUrl?: string;
9
+ defaultSubmolt?: string;
9
10
  postFrequency?: 'realtime' | 'hourly' | 'daily';
10
11
  engagementRate?: 'low' | 'medium' | 'high';
11
12
  autoReply?: boolean;
@@ -370,6 +371,8 @@ declare class Agent {
370
371
  private initLLM;
371
372
  private registerActions;
372
373
  private initSocialAdapters;
374
+ private postStartupMessages;
375
+ private logPlatformError;
373
376
  private startAutonomousLoop;
374
377
  private isSleeping;
375
378
  private gatherContext;
@@ -510,10 +513,10 @@ declare class MoltbookAdapter extends SocialAdapter {
510
513
  post(content: string): Promise<PostResult>;
511
514
  reply(postId: string, content: string): Promise<ReplyResult>;
512
515
  like(postId: string): Promise<void>;
513
- follow(userId: string): Promise<void>;
516
+ follow(agentName: string): Promise<void>;
514
517
  getMentions(): Promise<Mention[]>;
515
518
  getFeed(options?: FeedOptions): Promise<Post[]>;
516
- getProfile(userId: string): Promise<Profile>;
519
+ getProfile(agentName: string): Promise<Profile>;
517
520
  }
518
521
 
519
522
  declare class TwitterAdapter extends SocialAdapter {
package/dist/index.js CHANGED
@@ -596,7 +596,7 @@ var MoltbookAdapter = class extends SocialAdapter {
596
596
  super();
597
597
  this.config = config;
598
598
  this.client = import_axios.default.create({
599
- baseURL: config.baseUrl || "https://api.moltbook.com",
599
+ baseURL: config.baseUrl || "https://www.moltbook.com/api/v1",
600
600
  headers: {
601
601
  Authorization: `Bearer ${config.apiKey}`,
602
602
  "Content-Type": "application/json"
@@ -604,12 +604,18 @@ var MoltbookAdapter = class extends SocialAdapter {
604
604
  });
605
605
  }
606
606
  async connect() {
607
- await this.client.get("/me");
607
+ await this.client.get("/agents/me");
608
608
  }
609
609
  async disconnect() {
610
610
  }
611
611
  async post(content) {
612
- const response = await this.client.post("/posts", { content });
612
+ const submolt = this.config.defaultSubmolt || "general";
613
+ const title = extractTitle(content);
614
+ const response = await this.client.post("/posts", {
615
+ submolt,
616
+ title,
617
+ content
618
+ });
613
619
  return {
614
620
  id: response.data.id,
615
621
  url: response.data.url,
@@ -617,7 +623,7 @@ var MoltbookAdapter = class extends SocialAdapter {
617
623
  };
618
624
  }
619
625
  async reply(postId, content) {
620
- const response = await this.client.post(`/posts/${postId}/replies`, { content });
626
+ const response = await this.client.post(`/posts/${postId}/comments`, { content });
621
627
  return {
622
628
  id: response.data.id,
623
629
  parentId: postId,
@@ -626,44 +632,48 @@ var MoltbookAdapter = class extends SocialAdapter {
626
632
  };
627
633
  }
628
634
  async like(postId) {
629
- await this.client.post(`/posts/${postId}/like`);
635
+ await this.client.post(`/posts/${postId}/upvote`);
630
636
  }
631
- async follow(userId) {
632
- await this.client.post(`/users/${userId}/follow`);
637
+ async follow(agentName) {
638
+ await this.client.post(`/agents/${agentName}/follow`);
633
639
  }
634
640
  async getMentions() {
635
- const response = await this.client.get("/mentions");
636
- return response.data.mentions.map((m) => ({
641
+ const response = await this.client.get("/feed", {
642
+ params: { sort: "new", limit: 20 }
643
+ });
644
+ return (response.data.posts || []).map((m) => ({
637
645
  id: m.id,
638
- authorId: m.author_id,
639
- authorName: m.author_name,
646
+ authorId: m.author_id || m.author?.id || "",
647
+ authorName: m.author_name || m.author?.name || "",
640
648
  content: m.content,
641
649
  timestamp: new Date(m.created_at),
642
650
  platform: "moltbook"
643
651
  }));
644
652
  }
645
653
  async getFeed(options) {
646
- const params = {};
654
+ const params = { sort: "hot" };
647
655
  if (options?.limit) params.limit = options.limit;
648
656
  if (options?.cursor) params.cursor = options.cursor;
649
657
  if (options?.since) params.since = options.since.toISOString();
650
658
  const response = await this.client.get("/feed", { params });
651
- return response.data.posts.map((p) => ({
659
+ return (response.data.posts || []).map((p) => ({
652
660
  id: p.id,
653
- authorId: p.author_id,
654
- authorName: p.author_name,
661
+ authorId: p.author_id || p.author?.id || "",
662
+ authorName: p.author_name || p.author?.name || "",
655
663
  content: p.content,
656
664
  timestamp: new Date(p.created_at),
657
665
  platform: "moltbook",
658
- likes: p.likes_count,
659
- replies: p.replies_count,
666
+ likes: p.upvotes ?? p.likes_count,
667
+ replies: p.comment_count ?? p.replies_count,
660
668
  reposts: p.reposts_count,
661
669
  mentions: p.mentions || [],
662
670
  url: p.url
663
671
  }));
664
672
  }
665
- async getProfile(userId) {
666
- const response = await this.client.get(`/users/${userId}`);
673
+ async getProfile(agentName) {
674
+ const response = await this.client.get("/agents/profile", {
675
+ params: { name: agentName }
676
+ });
667
677
  return {
668
678
  id: response.data.id,
669
679
  name: response.data.name,
@@ -674,6 +684,14 @@ var MoltbookAdapter = class extends SocialAdapter {
674
684
  };
675
685
  }
676
686
  };
687
+ function extractTitle(content) {
688
+ const firstLine = content.split("\n")[0].trim();
689
+ const sentenceEnd = firstLine.search(/[.!?]/);
690
+ const raw = sentenceEnd > 0 && sentenceEnd <= 80 ? firstLine.slice(0, sentenceEnd + 1) : firstLine;
691
+ if (raw.length <= 80) return raw;
692
+ const truncated = raw.slice(0, 80).replace(/\s+\S*$/, "");
693
+ return truncated + "...";
694
+ }
677
695
 
678
696
  // src/social/twitter.ts
679
697
  var TwitterAdapter = class extends SocialAdapter {
@@ -854,6 +872,7 @@ var Agent = class {
854
872
  if (this.hooks.onInit) {
855
873
  await this.hooks.onInit(this);
856
874
  }
875
+ await this.postStartupMessages();
857
876
  logger4.info(`Agent initialized: ${this.config.name}`);
858
877
  }
859
878
  async start() {
@@ -985,39 +1004,103 @@ var Agent = class {
985
1004
  async initSocialAdapters() {
986
1005
  const { social } = this.config;
987
1006
  if (social.moltbook?.enabled) {
1007
+ const baseUrl = social.moltbook.baseUrl || "https://www.moltbook.com/api/v1";
988
1008
  if (!social.moltbook.apiKey || social.moltbook.apiKey === "your-moltbook-key-here") {
989
- logger4.error("Moltbook is enabled but MOLTBOOK_API_KEY is missing or still a placeholder. Set a valid key in your .env file.");
1009
+ logger4.error("Moltbook: SKIPPED \u2014 MOLTBOOK_API_KEY is missing or still a placeholder.");
1010
+ logger4.error(" Fix: Set a valid MOLTBOOK_API_KEY in your .env file.");
990
1011
  } else {
1012
+ logger4.info(`Moltbook: Connecting to ${baseUrl} ...`);
991
1013
  const adapter = new MoltbookAdapter(social.moltbook);
992
1014
  try {
993
1015
  await adapter.connect();
994
1016
  this.socialAdapters["moltbook"] = adapter;
995
- logger4.info("Moltbook adapter connected");
1017
+ logger4.info("Moltbook: Connected successfully (GET /agents/me OK)");
996
1018
  } catch (error) {
997
- logger4.error(`Failed to connect Moltbook adapter: ${error.message || error}`);
998
- if (error.response) {
999
- logger4.error(` HTTP ${error.response.status}: ${JSON.stringify(error.response.data)}`);
1000
- }
1019
+ logger4.error(`Moltbook: Connection FAILED \u2014 ${error.message || error}`);
1020
+ this.logPlatformError("Moltbook", error);
1001
1021
  }
1002
1022
  }
1023
+ } else if (social.moltbook) {
1024
+ logger4.info("Moltbook: Configured but disabled (enabled: false)");
1003
1025
  }
1004
1026
  if (social.twitter?.enabled) {
1005
1027
  const creds = social.twitter.credentials;
1006
1028
  if (!creds?.apiKey || creds.apiKey === "your-twitter-api-key") {
1007
- logger4.error("Twitter is enabled but credentials are missing or still placeholders. Set valid Twitter keys in your .env file.");
1029
+ logger4.error("Twitter: SKIPPED \u2014 credentials are missing or still placeholders.");
1030
+ logger4.error(" Fix: Set valid Twitter keys in your .env file.");
1008
1031
  } else {
1032
+ logger4.info("Twitter: Connecting...");
1009
1033
  const adapter = new TwitterAdapter(social.twitter);
1010
1034
  try {
1011
1035
  await adapter.connect();
1012
1036
  this.socialAdapters["twitter"] = adapter;
1013
- logger4.info("Twitter adapter connected");
1037
+ logger4.info("Twitter: Connected successfully");
1014
1038
  } catch (error) {
1015
- logger4.error(`Failed to connect Twitter adapter: ${error.message || error}`);
1016
- if (error.response) {
1017
- logger4.error(` HTTP ${error.response.status}: ${JSON.stringify(error.response.data)}`);
1018
- }
1039
+ logger4.error(`Twitter: Connection FAILED \u2014 ${error.message || error}`);
1040
+ this.logPlatformError("Twitter", error);
1019
1041
  }
1020
1042
  }
1043
+ } else if (social.twitter) {
1044
+ logger4.info("Twitter: Configured but disabled (enabled: false)");
1045
+ }
1046
+ }
1047
+ async postStartupMessages() {
1048
+ const adapters = Object.entries(this.socialAdapters);
1049
+ if (adapters.length === 0) {
1050
+ logger4.info("Startup post: No connected social adapters \u2014 skipping");
1051
+ return;
1052
+ }
1053
+ const content = `${this.config.name} is now online and ready.`;
1054
+ for (const [platform, adapter] of adapters) {
1055
+ logger4.info(`Startup post: Posting to ${platform}...`);
1056
+ try {
1057
+ const result = await adapter.post(content);
1058
+ logger4.info(`Startup post: ${platform} SUCCESS \u2014 id=${result.id}${result.url ? ` url=${result.url}` : ""}`);
1059
+ } catch (error) {
1060
+ logger4.error(`Startup post: ${platform} FAILED \u2014 ${error.message || error}`);
1061
+ this.logPlatformError(platform, error);
1062
+ }
1063
+ }
1064
+ }
1065
+ logPlatformError(platform, error) {
1066
+ if (!error.response) {
1067
+ if (error.code === "ENOTFOUND") {
1068
+ logger4.error(` ${platform}: DNS lookup failed \u2014 check the base URL.`);
1069
+ } else if (error.code === "ECONNREFUSED") {
1070
+ logger4.error(` ${platform}: Connection refused \u2014 is the server running?`);
1071
+ } else if (error.code === "ETIMEDOUT" || error.code === "ECONNABORTED") {
1072
+ logger4.error(` ${platform}: Request timed out.`);
1073
+ } else {
1074
+ logger4.error(` ${platform}: Network error (${error.code || "unknown"})`);
1075
+ }
1076
+ return;
1077
+ }
1078
+ const status = error.response.status;
1079
+ const data = error.response.data;
1080
+ logger4.error(` ${platform}: HTTP ${status}`);
1081
+ if (data) {
1082
+ if (data.error) logger4.error(` ${platform}: API error: ${data.error}`);
1083
+ if (data.hint) logger4.error(` ${platform}: API hint: ${data.hint}`);
1084
+ if (!data.error && !data.hint) logger4.error(` ${platform}: Response: ${JSON.stringify(data)}`);
1085
+ }
1086
+ if (status === 401) {
1087
+ logger4.error(` ${platform}: Your API key was rejected. Verify it is correct and the agent is claimed.`);
1088
+ } else if (status === 403) {
1089
+ logger4.error(` ${platform}: Forbidden \u2014 your agent may not be claimed yet or lacks permissions.`);
1090
+ } else if (status === 429) {
1091
+ const retryMin = data?.retry_after_minutes;
1092
+ const retrySec = data?.retry_after_seconds;
1093
+ if (retryMin) {
1094
+ logger4.error(` ${platform}: Rate limited \u2014 try again in ${retryMin} minute(s).`);
1095
+ } else if (retrySec) {
1096
+ logger4.error(` ${platform}: Rate limited \u2014 try again in ${retrySec} second(s).`);
1097
+ } else {
1098
+ logger4.error(` ${platform}: Rate limited \u2014 wait before retrying.`);
1099
+ }
1100
+ } else if (status === 404) {
1101
+ logger4.error(` ${platform}: Endpoint not found \u2014 check the base URL.`);
1102
+ } else if (status >= 500) {
1103
+ logger4.error(` ${platform}: Server error \u2014 the platform may be temporarily down.`);
1021
1104
  }
1022
1105
  }
1023
1106
  startAutonomousLoop() {
@@ -1588,6 +1671,13 @@ function createRoutes(agent) {
1588
1671
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1589
1672
  });
1590
1673
  });
1674
+ router.get("/message", (_req, res) => {
1675
+ res.status(405).json({
1676
+ error: "Method Not Allowed",
1677
+ message: "Use POST /message to send a message to the agent.",
1678
+ expected_body: { message: "string" }
1679
+ });
1680
+ });
1591
1681
  router.post("/message", async (req, res) => {
1592
1682
  try {
1593
1683
  const { message } = req.body;
@@ -1604,6 +1694,13 @@ function createRoutes(agent) {
1604
1694
  res.status(500).json({ error: error instanceof Error ? error.message : "Unknown error" });
1605
1695
  }
1606
1696
  });
1697
+ router.get("/action", (_req, res) => {
1698
+ res.status(405).json({
1699
+ error: "Method Not Allowed",
1700
+ message: "Use POST /action to trigger an action.",
1701
+ expected_body: { action: "string", parameters: "{}" }
1702
+ });
1703
+ });
1607
1704
  router.post("/action", async (req, res) => {
1608
1705
  try {
1609
1706
  const { action, parameters } = req.body;