@moltium/core 0.1.4 → 0.1.6
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 +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +141 -32
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +141 -32
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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(
|
|
516
|
+
follow(agentName: string): Promise<void>;
|
|
514
517
|
getMentions(): Promise<Mention[]>;
|
|
515
518
|
getFeed(options?: FeedOptions): Promise<Post[]>;
|
|
516
|
-
getProfile(
|
|
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(
|
|
516
|
+
follow(agentName: string): Promise<void>;
|
|
514
517
|
getMentions(): Promise<Mention[]>;
|
|
515
518
|
getFeed(options?: FeedOptions): Promise<Post[]>;
|
|
516
|
-
getProfile(
|
|
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://
|
|
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
|
|
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}/
|
|
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}/
|
|
635
|
+
await this.client.post(`/posts/${postId}/upvote`);
|
|
630
636
|
}
|
|
631
|
-
async follow(
|
|
632
|
-
await this.client.post(`/
|
|
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("/
|
|
636
|
-
|
|
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(
|
|
666
|
-
const response = await this.client.get(
|
|
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() {
|
|
@@ -984,40 +1003,114 @@ var Agent = class {
|
|
|
984
1003
|
}
|
|
985
1004
|
async initSocialAdapters() {
|
|
986
1005
|
const { social } = this.config;
|
|
1006
|
+
const configuredPlatforms = Object.keys(social).filter(
|
|
1007
|
+
(k) => social[k] && typeof social[k] === "object"
|
|
1008
|
+
);
|
|
1009
|
+
if (configuredPlatforms.length === 0) {
|
|
1010
|
+
logger4.warn("Social: No platforms configured. To post on startup, add a social platform to your config.");
|
|
1011
|
+
logger4.warn(' Code-based: Add a moltbook or twitter section to agent.config.ts under "social".');
|
|
1012
|
+
logger4.warn(' Markdown: Add a "### Moltbook" section under "## Social Platforms" in agent.md with "enabled: true".');
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
logger4.info(`Social: Found platforms in config: ${configuredPlatforms.join(", ")}`);
|
|
987
1016
|
if (social.moltbook?.enabled) {
|
|
1017
|
+
const baseUrl = social.moltbook.baseUrl || "https://www.moltbook.com/api/v1";
|
|
988
1018
|
if (!social.moltbook.apiKey || social.moltbook.apiKey === "your-moltbook-key-here") {
|
|
989
|
-
logger4.error("Moltbook
|
|
1019
|
+
logger4.error("Moltbook: SKIPPED \u2014 MOLTBOOK_API_KEY is missing or still a placeholder.");
|
|
1020
|
+
logger4.error(" Fix: Set a valid MOLTBOOK_API_KEY in your .env file.");
|
|
990
1021
|
} else {
|
|
1022
|
+
logger4.info(`Moltbook: Connecting to ${baseUrl} ...`);
|
|
991
1023
|
const adapter = new MoltbookAdapter(social.moltbook);
|
|
992
1024
|
try {
|
|
993
1025
|
await adapter.connect();
|
|
994
1026
|
this.socialAdapters["moltbook"] = adapter;
|
|
995
|
-
logger4.info("Moltbook
|
|
1027
|
+
logger4.info("Moltbook: Connected successfully (GET /agents/me OK)");
|
|
996
1028
|
} catch (error) {
|
|
997
|
-
logger4.error(`
|
|
998
|
-
|
|
999
|
-
logger4.error(` HTTP ${error.response.status}: ${JSON.stringify(error.response.data)}`);
|
|
1000
|
-
}
|
|
1029
|
+
logger4.error(`Moltbook: Connection FAILED \u2014 ${error.message || error}`);
|
|
1030
|
+
this.logPlatformError("Moltbook", error);
|
|
1001
1031
|
}
|
|
1002
1032
|
}
|
|
1033
|
+
} else if (social.moltbook) {
|
|
1034
|
+
logger4.warn('Moltbook: Present in config but disabled (enabled: false). Set "enabled: true" to activate.');
|
|
1003
1035
|
}
|
|
1004
1036
|
if (social.twitter?.enabled) {
|
|
1005
1037
|
const creds = social.twitter.credentials;
|
|
1006
1038
|
if (!creds?.apiKey || creds.apiKey === "your-twitter-api-key") {
|
|
1007
|
-
logger4.error("Twitter
|
|
1039
|
+
logger4.error("Twitter: SKIPPED \u2014 credentials are missing or still placeholders.");
|
|
1040
|
+
logger4.error(" Fix: Set valid Twitter keys in your .env file.");
|
|
1008
1041
|
} else {
|
|
1042
|
+
logger4.info("Twitter: Connecting...");
|
|
1009
1043
|
const adapter = new TwitterAdapter(social.twitter);
|
|
1010
1044
|
try {
|
|
1011
1045
|
await adapter.connect();
|
|
1012
1046
|
this.socialAdapters["twitter"] = adapter;
|
|
1013
|
-
logger4.info("Twitter
|
|
1047
|
+
logger4.info("Twitter: Connected successfully");
|
|
1014
1048
|
} catch (error) {
|
|
1015
|
-
logger4.error(`
|
|
1016
|
-
|
|
1017
|
-
logger4.error(` HTTP ${error.response.status}: ${JSON.stringify(error.response.data)}`);
|
|
1018
|
-
}
|
|
1049
|
+
logger4.error(`Twitter: Connection FAILED \u2014 ${error.message || error}`);
|
|
1050
|
+
this.logPlatformError("Twitter", error);
|
|
1019
1051
|
}
|
|
1020
1052
|
}
|
|
1053
|
+
} else if (social.twitter) {
|
|
1054
|
+
logger4.warn('Twitter: Present in config but disabled (enabled: false). Set "enabled: true" to activate.');
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
async postStartupMessages() {
|
|
1058
|
+
const adapters = Object.entries(this.socialAdapters);
|
|
1059
|
+
if (adapters.length === 0) {
|
|
1060
|
+
logger4.info("Startup post: No connected social adapters \u2014 skipping");
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1063
|
+
const content = `${this.config.name} is now online and ready.`;
|
|
1064
|
+
for (const [platform, adapter] of adapters) {
|
|
1065
|
+
logger4.info(`Startup post: Posting to ${platform}...`);
|
|
1066
|
+
try {
|
|
1067
|
+
const result = await adapter.post(content);
|
|
1068
|
+
logger4.info(`Startup post: ${platform} SUCCESS \u2014 id=${result.id}${result.url ? ` url=${result.url}` : ""}`);
|
|
1069
|
+
} catch (error) {
|
|
1070
|
+
logger4.error(`Startup post: ${platform} FAILED \u2014 ${error.message || error}`);
|
|
1071
|
+
this.logPlatformError(platform, error);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
logPlatformError(platform, error) {
|
|
1076
|
+
if (!error.response) {
|
|
1077
|
+
if (error.code === "ENOTFOUND") {
|
|
1078
|
+
logger4.error(` ${platform}: DNS lookup failed \u2014 check the base URL.`);
|
|
1079
|
+
} else if (error.code === "ECONNREFUSED") {
|
|
1080
|
+
logger4.error(` ${platform}: Connection refused \u2014 is the server running?`);
|
|
1081
|
+
} else if (error.code === "ETIMEDOUT" || error.code === "ECONNABORTED") {
|
|
1082
|
+
logger4.error(` ${platform}: Request timed out.`);
|
|
1083
|
+
} else {
|
|
1084
|
+
logger4.error(` ${platform}: Network error (${error.code || "unknown"})`);
|
|
1085
|
+
}
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
const status = error.response.status;
|
|
1089
|
+
const data = error.response.data;
|
|
1090
|
+
logger4.error(` ${platform}: HTTP ${status}`);
|
|
1091
|
+
if (data) {
|
|
1092
|
+
if (data.error) logger4.error(` ${platform}: API error: ${data.error}`);
|
|
1093
|
+
if (data.hint) logger4.error(` ${platform}: API hint: ${data.hint}`);
|
|
1094
|
+
if (!data.error && !data.hint) logger4.error(` ${platform}: Response: ${JSON.stringify(data)}`);
|
|
1095
|
+
}
|
|
1096
|
+
if (status === 401) {
|
|
1097
|
+
logger4.error(` ${platform}: Your API key was rejected. Verify it is correct and the agent is claimed.`);
|
|
1098
|
+
} else if (status === 403) {
|
|
1099
|
+
logger4.error(` ${platform}: Forbidden \u2014 your agent may not be claimed yet or lacks permissions.`);
|
|
1100
|
+
} else if (status === 429) {
|
|
1101
|
+
const retryMin = data?.retry_after_minutes;
|
|
1102
|
+
const retrySec = data?.retry_after_seconds;
|
|
1103
|
+
if (retryMin) {
|
|
1104
|
+
logger4.error(` ${platform}: Rate limited \u2014 try again in ${retryMin} minute(s).`);
|
|
1105
|
+
} else if (retrySec) {
|
|
1106
|
+
logger4.error(` ${platform}: Rate limited \u2014 try again in ${retrySec} second(s).`);
|
|
1107
|
+
} else {
|
|
1108
|
+
logger4.error(` ${platform}: Rate limited \u2014 wait before retrying.`);
|
|
1109
|
+
}
|
|
1110
|
+
} else if (status === 404) {
|
|
1111
|
+
logger4.error(` ${platform}: Endpoint not found \u2014 check the base URL.`);
|
|
1112
|
+
} else if (status >= 500) {
|
|
1113
|
+
logger4.error(` ${platform}: Server error \u2014 the platform may be temporarily down.`);
|
|
1021
1114
|
}
|
|
1022
1115
|
}
|
|
1023
1116
|
startAutonomousLoop() {
|
|
@@ -1157,8 +1250,10 @@ var MarkdownParser = class {
|
|
|
1157
1250
|
for (const child of section.children) {
|
|
1158
1251
|
const platform = child.title.toLowerCase();
|
|
1159
1252
|
const fields = this.parseKeyValueLines(child.content);
|
|
1253
|
+
const enabled = fields["enabled"] === "true";
|
|
1254
|
+
delete fields["enabled"];
|
|
1160
1255
|
social[platform] = {
|
|
1161
|
-
enabled
|
|
1256
|
+
enabled,
|
|
1162
1257
|
...fields
|
|
1163
1258
|
};
|
|
1164
1259
|
}
|
|
@@ -1588,6 +1683,13 @@ function createRoutes(agent) {
|
|
|
1588
1683
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1589
1684
|
});
|
|
1590
1685
|
});
|
|
1686
|
+
router.get("/message", (_req, res) => {
|
|
1687
|
+
res.status(405).json({
|
|
1688
|
+
error: "Method Not Allowed",
|
|
1689
|
+
message: "Use POST /message to send a message to the agent.",
|
|
1690
|
+
expected_body: { message: "string" }
|
|
1691
|
+
});
|
|
1692
|
+
});
|
|
1591
1693
|
router.post("/message", async (req, res) => {
|
|
1592
1694
|
try {
|
|
1593
1695
|
const { message } = req.body;
|
|
@@ -1604,6 +1706,13 @@ function createRoutes(agent) {
|
|
|
1604
1706
|
res.status(500).json({ error: error instanceof Error ? error.message : "Unknown error" });
|
|
1605
1707
|
}
|
|
1606
1708
|
});
|
|
1709
|
+
router.get("/action", (_req, res) => {
|
|
1710
|
+
res.status(405).json({
|
|
1711
|
+
error: "Method Not Allowed",
|
|
1712
|
+
message: "Use POST /action to trigger an action.",
|
|
1713
|
+
expected_body: { action: "string", parameters: "{}" }
|
|
1714
|
+
});
|
|
1715
|
+
});
|
|
1607
1716
|
router.post("/action", async (req, res) => {
|
|
1608
1717
|
try {
|
|
1609
1718
|
const { action, parameters } = req.body;
|