@moltium/core 0.1.12 → 0.1.14

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.js CHANGED
@@ -585,6 +585,25 @@ var import_axios = __toESM(require("axios"), 1);
585
585
 
586
586
  // src/social/SocialAdapter.ts
587
587
  var SocialAdapter = class {
588
+ // Optional methods with defaults — override in platform adapters as needed
589
+ async downvote(_id) {
590
+ throw new Error(`downvote() is not supported on ${this.platform}`);
591
+ }
592
+ async unfollow(_userId) {
593
+ throw new Error(`unfollow() is not supported on ${this.platform}`);
594
+ }
595
+ async getPost(_id) {
596
+ throw new Error(`getPost() is not supported on ${this.platform}`);
597
+ }
598
+ async deletePost(_id) {
599
+ throw new Error(`deletePost() is not supported on ${this.platform}`);
600
+ }
601
+ async getComments(_postId, _sort) {
602
+ throw new Error(`getComments() is not supported on ${this.platform}`);
603
+ }
604
+ async search(_query, _options) {
605
+ throw new Error(`search() is not supported on ${this.platform}`);
606
+ }
588
607
  };
589
608
 
590
609
  // src/social/moltbook.ts
@@ -603,11 +622,61 @@ var MoltbookAdapter = class extends SocialAdapter {
603
622
  }
604
623
  });
605
624
  }
625
+ // ── Connection ──
606
626
  async connect() {
607
627
  await this.client.get("/agents/me");
608
628
  }
609
629
  async disconnect() {
610
630
  }
631
+ // ── Registration & Status ──
632
+ async register(name, description) {
633
+ const response = await this.client.post("/agents/register", { name, description });
634
+ const agent = response.data.agent || response.data;
635
+ return {
636
+ apiKey: agent.api_key,
637
+ claimUrl: agent.claim_url,
638
+ verificationCode: agent.verification_code
639
+ };
640
+ }
641
+ async getStatus() {
642
+ const response = await this.client.get("/agents/status");
643
+ return { status: response.data.status };
644
+ }
645
+ // ── Profile ──
646
+ async getProfile(agentName) {
647
+ const response = await this.client.get("/agents/profile", {
648
+ params: { name: agentName }
649
+ });
650
+ const agent = response.data.agent || response.data;
651
+ return {
652
+ id: agent.id || agent.name,
653
+ name: agent.name,
654
+ bio: agent.description,
655
+ followers: agent.follower_count,
656
+ following: agent.following_count,
657
+ platform: "moltbook"
658
+ };
659
+ }
660
+ async getMyProfile() {
661
+ const response = await this.client.get("/agents/me");
662
+ return response.data;
663
+ }
664
+ async updateProfile(data) {
665
+ await this.client.patch("/agents/me", data);
666
+ }
667
+ async uploadAvatar(filePath) {
668
+ const fs = await import("fs");
669
+ const FormData = (await import("form-data")).default;
670
+ const form = new FormData();
671
+ form.append("file", fs.createReadStream(filePath));
672
+ await this.client.post("/agents/me/avatar", form, {
673
+ headers: { ...form.getHeaders(), Authorization: `Bearer ${this.config.apiKey}` }
674
+ });
675
+ }
676
+ async deleteAvatar() {
677
+ await this.client.delete("/agents/me/avatar");
678
+ }
679
+ // ── Posts ──
611
680
  async post(content) {
612
681
  const submolt = this.config.defaultSubmolt || "general";
613
682
  const title = extractTitle(content);
@@ -622,6 +691,35 @@ var MoltbookAdapter = class extends SocialAdapter {
622
691
  timestamp: new Date(response.data.created_at)
623
692
  };
624
693
  }
694
+ async postLink(submolt, title, url) {
695
+ const response = await this.client.post("/posts", { submolt, title, url });
696
+ return {
697
+ id: response.data.id,
698
+ url: response.data.url,
699
+ timestamp: new Date(response.data.created_at)
700
+ };
701
+ }
702
+ async getPost(postId) {
703
+ const response = await this.client.get(`/posts/${postId}`);
704
+ const p = response.data.post || response.data;
705
+ return {
706
+ id: p.id,
707
+ authorId: p.author_id || p.author?.id || "",
708
+ authorName: p.author_name || p.author?.name || "",
709
+ content: p.content,
710
+ title: p.title,
711
+ timestamp: new Date(p.created_at),
712
+ platform: "moltbook",
713
+ likes: p.upvotes ?? p.likes_count,
714
+ replies: p.comment_count ?? p.replies_count,
715
+ url: p.url,
716
+ submolt: p.submolt?.name || p.submolt
717
+ };
718
+ }
719
+ async deletePost(postId) {
720
+ await this.client.delete(`/posts/${postId}`);
721
+ }
722
+ // ── Comments ──
625
723
  async reply(postId, content) {
626
724
  const response = await this.client.post(`/posts/${postId}/comments`, { content });
627
725
  return {
@@ -631,12 +729,43 @@ var MoltbookAdapter = class extends SocialAdapter {
631
729
  timestamp: new Date(response.data.created_at)
632
730
  };
633
731
  }
732
+ async replyToComment(postId, content, parentId) {
733
+ const response = await this.client.post(`/posts/${postId}/comments`, {
734
+ content,
735
+ parent_id: parentId
736
+ });
737
+ return {
738
+ id: response.data.id,
739
+ parentId,
740
+ url: response.data.url,
741
+ timestamp: new Date(response.data.created_at)
742
+ };
743
+ }
744
+ async getComments(postId, sort = "top") {
745
+ const response = await this.client.get(`/posts/${postId}/comments`, {
746
+ params: { sort }
747
+ });
748
+ const items = response.data.comments || response.data || [];
749
+ return items.map((c) => mapComment(c, postId));
750
+ }
751
+ async upvoteComment(commentId) {
752
+ await this.client.post(`/comments/${commentId}/upvote`);
753
+ }
754
+ // ── Voting ──
634
755
  async like(postId) {
635
756
  await this.client.post(`/posts/${postId}/upvote`);
636
757
  }
758
+ async downvote(postId) {
759
+ await this.client.post(`/posts/${postId}/downvote`);
760
+ }
761
+ // ── Following ──
637
762
  async follow(agentName) {
638
763
  await this.client.post(`/agents/${agentName}/follow`);
639
764
  }
765
+ async unfollow(agentName) {
766
+ await this.client.delete(`/agents/${agentName}/follow`);
767
+ }
768
+ // ── Feed ──
640
769
  async getMentions() {
641
770
  const response = await this.client.get("/feed", {
642
771
  params: { sort: "new", limit: 20 }
@@ -651,38 +780,225 @@ var MoltbookAdapter = class extends SocialAdapter {
651
780
  }));
652
781
  }
653
782
  async getFeed(options) {
654
- const params = { sort: "hot" };
783
+ const params = { sort: options?.sort || "hot" };
655
784
  if (options?.limit) params.limit = options.limit;
656
785
  if (options?.cursor) params.cursor = options.cursor;
657
786
  if (options?.since) params.since = options.since.toISOString();
787
+ if (options?.submolt) params.submolt = options.submolt;
658
788
  const response = await this.client.get("/feed", { params });
659
- return (response.data.posts || []).map((p) => ({
660
- id: p.id,
661
- authorId: p.author_id || p.author?.id || "",
662
- authorName: p.author_name || p.author?.name || "",
663
- content: p.content,
664
- timestamp: new Date(p.created_at),
665
- platform: "moltbook",
666
- likes: p.upvotes ?? p.likes_count,
667
- replies: p.comment_count ?? p.replies_count,
668
- reposts: p.reposts_count,
669
- mentions: p.mentions || [],
670
- url: p.url
789
+ return (response.data.posts || []).map((p) => mapPost(p));
790
+ }
791
+ async getGlobalFeed(options) {
792
+ const params = { sort: options?.sort || "hot" };
793
+ if (options?.limit) params.limit = options.limit;
794
+ if (options?.submolt) params.submolt = options.submolt;
795
+ const response = await this.client.get("/posts", { params });
796
+ return (response.data.posts || []).map((p) => mapPost(p));
797
+ }
798
+ // ── Search ──
799
+ async search(query, options) {
800
+ const params = { q: query };
801
+ if (options?.type) params.type = options.type;
802
+ if (options?.limit) params.limit = options.limit;
803
+ const response = await this.client.get("/search", { params });
804
+ return (response.data.results || []).map((r) => ({
805
+ id: r.id,
806
+ type: r.type,
807
+ title: r.title,
808
+ content: r.content,
809
+ upvotes: r.upvotes ?? 0,
810
+ downvotes: r.downvotes ?? 0,
811
+ similarity: r.similarity,
812
+ author: { name: r.author?.name || "" },
813
+ submolt: r.submolt,
814
+ postId: r.post_id || r.id,
815
+ timestamp: new Date(r.created_at)
671
816
  }));
672
817
  }
673
- async getProfile(agentName) {
674
- const response = await this.client.get("/agents/profile", {
675
- params: { name: agentName }
818
+ // ── Submolts (Communities) ──
819
+ async createSubmolt(name, displayName, description) {
820
+ const response = await this.client.post("/submolts", {
821
+ name,
822
+ display_name: displayName,
823
+ description
676
824
  });
825
+ const s = response.data.submolt || response.data;
826
+ return mapSubmolt(s);
827
+ }
828
+ async listSubmolts() {
829
+ const response = await this.client.get("/submolts");
830
+ const items = response.data.submolts || response.data || [];
831
+ return items.map((s) => mapSubmolt(s));
832
+ }
833
+ async getSubmolt(name) {
834
+ const response = await this.client.get(`/submolts/${name}`);
835
+ const s = response.data.submolt || response.data;
836
+ return mapSubmolt(s);
837
+ }
838
+ async subscribe(submoltName) {
839
+ await this.client.post(`/submolts/${submoltName}/subscribe`);
840
+ }
841
+ async unsubscribe(submoltName) {
842
+ await this.client.delete(`/submolts/${submoltName}/subscribe`);
843
+ }
844
+ async getSubmoltFeed(submoltName, sort = "hot", limit = 25) {
845
+ const response = await this.client.get(`/submolts/${submoltName}/feed`, {
846
+ params: { sort, limit }
847
+ });
848
+ return (response.data.posts || []).map((p) => mapPost(p));
849
+ }
850
+ // ── Moderation ──
851
+ async pinPost(postId) {
852
+ await this.client.post(`/posts/${postId}/pin`);
853
+ }
854
+ async unpinPost(postId) {
855
+ await this.client.delete(`/posts/${postId}/pin`);
856
+ }
857
+ async updateSubmoltSettings(submoltName, settings) {
858
+ const payload = {};
859
+ if (settings.description !== void 0) payload.description = settings.description;
860
+ if (settings.bannerColor !== void 0) payload.banner_color = settings.bannerColor;
861
+ if (settings.themeColor !== void 0) payload.theme_color = settings.themeColor;
862
+ await this.client.patch(`/submolts/${submoltName}/settings`, payload);
863
+ }
864
+ async uploadSubmoltAvatar(submoltName, filePath) {
865
+ const fs = await import("fs");
866
+ const FormData = (await import("form-data")).default;
867
+ const form = new FormData();
868
+ form.append("file", fs.createReadStream(filePath));
869
+ form.append("type", "avatar");
870
+ await this.client.post(`/submolts/${submoltName}/settings`, form, {
871
+ headers: { ...form.getHeaders(), Authorization: `Bearer ${this.config.apiKey}` }
872
+ });
873
+ }
874
+ async uploadSubmoltBanner(submoltName, filePath) {
875
+ const fs = await import("fs");
876
+ const FormData = (await import("form-data")).default;
877
+ const form = new FormData();
878
+ form.append("file", fs.createReadStream(filePath));
879
+ form.append("type", "banner");
880
+ await this.client.post(`/submolts/${submoltName}/settings`, form, {
881
+ headers: { ...form.getHeaders(), Authorization: `Bearer ${this.config.apiKey}` }
882
+ });
883
+ }
884
+ async addModerator(submoltName, agentName, role = "moderator") {
885
+ await this.client.post(`/submolts/${submoltName}/moderators`, {
886
+ agent_name: agentName,
887
+ role
888
+ });
889
+ }
890
+ async removeModerator(submoltName, agentName) {
891
+ await this.client.delete(`/submolts/${submoltName}/moderators`, {
892
+ data: { agent_name: agentName }
893
+ });
894
+ }
895
+ async listModerators(submoltName) {
896
+ const response = await this.client.get(`/submolts/${submoltName}/moderators`);
897
+ return response.data.moderators || response.data || [];
898
+ }
899
+ // ── DM / Private Messaging ──
900
+ async checkDMs() {
901
+ const response = await this.client.get("/agents/dm/check");
902
+ const d = response.data;
677
903
  return {
678
- id: response.data.id,
679
- name: response.data.name,
680
- bio: response.data.bio,
681
- followers: response.data.followers_count,
682
- following: response.data.following_count,
683
- platform: "moltbook"
904
+ hasActivity: d.has_activity,
905
+ summary: d.summary || "",
906
+ requests: {
907
+ count: d.requests?.count || 0,
908
+ items: (d.requests?.items || []).map((r) => ({
909
+ conversationId: r.conversation_id,
910
+ from: {
911
+ name: r.from?.name || "",
912
+ owner: r.from?.owner ? {
913
+ xHandle: r.from.owner.x_handle,
914
+ xName: r.from.owner.x_name
915
+ } : void 0
916
+ },
917
+ messagePreview: r.message_preview || "",
918
+ createdAt: new Date(r.created_at)
919
+ }))
920
+ },
921
+ messages: {
922
+ totalUnread: d.messages?.total_unread || 0,
923
+ conversationsWithUnread: d.messages?.conversations_with_unread || 0,
924
+ latest: d.messages?.latest || []
925
+ }
684
926
  };
685
927
  }
928
+ async sendDMRequest(to, message, byOwner = false) {
929
+ const payload = { message };
930
+ if (byOwner) {
931
+ payload.to_owner = to;
932
+ } else {
933
+ payload.to = to;
934
+ }
935
+ const response = await this.client.post("/agents/dm/request", payload);
936
+ return { conversationId: response.data.conversation_id || response.data.id };
937
+ }
938
+ async getDMRequests() {
939
+ const response = await this.client.get("/agents/dm/requests");
940
+ const items = response.data.requests || response.data || [];
941
+ return items.map((r) => ({
942
+ conversationId: r.conversation_id,
943
+ from: {
944
+ name: r.from?.name || "",
945
+ owner: r.from?.owner ? {
946
+ xHandle: r.from.owner.x_handle,
947
+ xName: r.from.owner.x_name
948
+ } : void 0
949
+ },
950
+ messagePreview: r.message_preview || r.message || "",
951
+ createdAt: new Date(r.created_at)
952
+ }));
953
+ }
954
+ async approveDMRequest(conversationId) {
955
+ await this.client.post(`/agents/dm/requests/${conversationId}/approve`);
956
+ }
957
+ async rejectDMRequest(conversationId, block = false) {
958
+ const payload = block ? { block: true } : void 0;
959
+ await this.client.post(`/agents/dm/requests/${conversationId}/reject`, payload);
960
+ }
961
+ async listConversations() {
962
+ const response = await this.client.get("/agents/dm/conversations");
963
+ const items = response.data.conversations?.items || response.data.conversations || [];
964
+ return items.map((c) => ({
965
+ conversationId: c.conversation_id,
966
+ withAgent: {
967
+ name: c.with_agent?.name || "",
968
+ description: c.with_agent?.description,
969
+ karma: c.with_agent?.karma,
970
+ owner: c.with_agent?.owner ? {
971
+ xHandle: c.with_agent.owner.x_handle,
972
+ xName: c.with_agent.owner.x_name
973
+ } : void 0
974
+ },
975
+ unreadCount: c.unread_count || 0,
976
+ lastMessageAt: new Date(c.last_message_at),
977
+ youInitiated: c.you_initiated ?? false
978
+ }));
979
+ }
980
+ async readConversation(conversationId) {
981
+ const response = await this.client.get(`/agents/dm/conversations/${conversationId}`);
982
+ const d = response.data;
983
+ return {
984
+ conversationId: d.conversation_id || conversationId,
985
+ withAgent: { name: d.with_agent?.name || "" },
986
+ messages: (d.messages || []).map((m) => ({
987
+ id: m.id,
988
+ sender: m.sender || m.from || "",
989
+ content: m.content || m.message || "",
990
+ timestamp: new Date(m.created_at || m.timestamp),
991
+ needsHumanInput: m.needs_human_input
992
+ }))
993
+ };
994
+ }
995
+ async sendDM(conversationId, message, needsHumanInput = false) {
996
+ const payload = { message };
997
+ if (needsHumanInput) {
998
+ payload.needs_human_input = true;
999
+ }
1000
+ await this.client.post(`/agents/dm/conversations/${conversationId}/send`, payload);
1001
+ }
686
1002
  };
687
1003
  function extractTitle(content) {
688
1004
  const firstLine = content.split("\n")[0].trim();
@@ -692,6 +1008,47 @@ function extractTitle(content) {
692
1008
  const truncated = raw.slice(0, 80).replace(/\s+\S*$/, "");
693
1009
  return truncated + "...";
694
1010
  }
1011
+ function mapPost(p) {
1012
+ return {
1013
+ id: p.id,
1014
+ authorId: p.author_id || p.author?.id || "",
1015
+ authorName: p.author_name || p.author?.name || "",
1016
+ content: p.content,
1017
+ title: p.title,
1018
+ timestamp: new Date(p.created_at),
1019
+ platform: "moltbook",
1020
+ likes: p.upvotes ?? p.likes_count,
1021
+ replies: p.comment_count ?? p.replies_count,
1022
+ reposts: p.reposts_count,
1023
+ mentions: p.mentions || [],
1024
+ url: p.url,
1025
+ submolt: p.submolt?.name || p.submolt
1026
+ };
1027
+ }
1028
+ function mapComment(c, postId) {
1029
+ return {
1030
+ id: c.id,
1031
+ postId,
1032
+ parentId: c.parent_id,
1033
+ authorName: c.author?.name || c.author_name || "",
1034
+ content: c.content,
1035
+ upvotes: c.upvotes ?? 0,
1036
+ downvotes: c.downvotes ?? 0,
1037
+ timestamp: new Date(c.created_at),
1038
+ replies: c.replies?.map((r) => mapComment(r, postId))
1039
+ };
1040
+ }
1041
+ function mapSubmolt(s) {
1042
+ return {
1043
+ name: s.name,
1044
+ displayName: s.display_name || s.name,
1045
+ description: s.description || "",
1046
+ subscriberCount: s.subscriber_count || 0,
1047
+ postCount: s.post_count,
1048
+ yourRole: s.your_role || null,
1049
+ createdAt: new Date(s.created_at)
1050
+ };
1051
+ }
695
1052
 
696
1053
  // src/social/twitter.ts
697
1054
  var TwitterAdapter = class extends SocialAdapter {
@@ -1138,13 +1495,13 @@ var Agent = class {
1138
1495
  }
1139
1496
  let content;
1140
1497
  try {
1141
- const prompt = `You are ${this.config.name}. You just came online.
1142
- Your bio: ${this.config.personality.bio}
1143
- Your personality traits: ${this.config.personality.traits.join(", ")}
1144
- ` + (this.config.type ? `Your role: ${this.config.type}
1145
- ` : "") + `
1146
- Write a short, engaging first post announcing you're online. Stay in character \u2014 reflect your personality and bio. Do NOT use generic phrases like "is now online and ready". Write only the post content, nothing else.`;
1498
+ const prompt = `You just came online. Write a short, engaging first post for social media.
1499
+ Stay fully in character \u2014 your personality, background, and role are defined in the system prompt.
1500
+ Do NOT use generic phrases like "is now online and ready" or "Hello, world!".
1501
+ Do NOT describe yourself in third person. Do NOT use emojis unless your personality calls for it.
1502
+ Write only the post content, nothing else. Keep it concise and natural.`;
1147
1503
  content = (await this.llm.generateText(prompt, {
1504
+ systemPrompt: this.systemPrompt,
1148
1505
  temperature: this.config.llm.temperature ?? 0.8,
1149
1506
  maxTokens: 280
1150
1507
  })).trim();
@@ -1221,8 +1578,11 @@ Write a short, engaging first post announcing you're online. Stay in character \
1221
1578
  const adapter = this.socialAdapters[platform];
1222
1579
  if (!adapter) return;
1223
1580
  try {
1224
- const prompt = `You are ${this.config.name}. Generate a short, engaging social media post for ${platform}. Your personality: ${this.config.personality.traits.join(", ")}. Bio: ${this.config.personality.bio}. Write only the post content, nothing else. Keep it concise and natural.`;
1581
+ const prompt = `Generate a short, engaging social media post for ${platform}.
1582
+ Stay fully in character based on your personality in the system prompt.
1583
+ Write only the post content, nothing else. Keep it concise and natural.`;
1225
1584
  const content = await this.llm.generateText(prompt, {
1585
+ systemPrompt: this.systemPrompt,
1226
1586
  temperature: this.config.llm.temperature ?? 0.8,
1227
1587
  maxTokens: 280
1228
1588
  });