@moltium/core 0.1.10 → 0.1.12

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
@@ -7,7 +7,7 @@ interface MoltbookConfig {
7
7
  apiKey: string;
8
8
  baseUrl?: string;
9
9
  defaultSubmolt?: string;
10
- postFrequency?: 'realtime' | 'hourly' | 'daily';
10
+ postFrequency?: string;
11
11
  engagementRate?: 'low' | 'medium' | 'high';
12
12
  autoReply?: boolean;
13
13
  replyFilter?: (post: any) => boolean;
@@ -21,7 +21,7 @@ interface TwitterConfig {
21
21
  accessSecret: string;
22
22
  bearerToken?: string;
23
23
  };
24
- postFrequency?: 'realtime' | 'hourly' | 'daily';
24
+ postFrequency?: string;
25
25
  replyToMentions?: boolean;
26
26
  autoRetweet?: boolean;
27
27
  maxTweetsPerDay?: number;
@@ -60,6 +60,11 @@ interface Plugin {
60
60
  init?: (agent: any) => Promise<void>;
61
61
  destroy?: () => Promise<void>;
62
62
  }
63
+ interface ScheduledTask {
64
+ name: string;
65
+ intervalMs: number;
66
+ instructions: string;
67
+ }
63
68
  interface AgentConfig {
64
69
  name: string;
65
70
  type?: string;
@@ -96,6 +101,7 @@ interface AgentConfig {
96
101
  };
97
102
  actions: string[];
98
103
  customActions?: Action[];
104
+ scheduling?: ScheduledTask[];
99
105
  webhooks?: {
100
106
  onAction?: string | ((action: any, result: any) => Promise<void>);
101
107
  onError?: string;
@@ -374,6 +380,11 @@ declare class Agent {
374
380
  private initMoltbook;
375
381
  private initTwitter;
376
382
  private postStartupMessages;
383
+ private initScheduledJobs;
384
+ private wirePostFrequencyJobs;
385
+ private wireSchedulingTasks;
386
+ private scheduledPost;
387
+ private executeScheduledTask;
377
388
  private logPlatformError;
378
389
  private startAutonomousLoop;
379
390
  private isSleeping;
@@ -424,6 +435,9 @@ declare class MarkdownParser {
424
435
  private parseMemory;
425
436
  private parseSleepSchedule;
426
437
  private parseKeyValueLines;
438
+ private parseScheduling;
439
+ private parseIntervalFromTitle;
440
+ private toCamelCase;
427
441
  private toSnakeCase;
428
442
  }
429
443
 
@@ -566,4 +580,4 @@ declare function createRoutes(agent: Agent): Router;
566
580
 
567
581
  declare function createLogger(label: string): winston.Logger;
568
582
 
569
- export { type Action, type ActionContext, ActionHandler, ActionRegistry, type ActionResult, Agent, type AgentConfig, type AgentState, AnthropicProvider, type BehaviorTrigger, ConfigLoader, type ConfigType, type CustomAPIConfig, type CustomCLIConfig, type CustomDeploymentConfig, type CustomDockerConfig, type CustomSSHConfig, type Decision, type DeploymentConfig, type DeploymentResult, type DeploymentStatus, type Experience, type FeedOptions, type GenerateOptions, LLMProvider, type LifecycleEvent, type LifecycleHooks, LongTermMemory, MarkdownParser, Memory, type Mention, type Message, MoltbookAdapter, type MoltbookConfig, OpenAIProvider, type Plugin, type Post, type PostResult, type PostgresConfig, type Profile, type RedisConfig, type ReplyResult, type ScheduledJob, Scheduler, ShortTermMemory, SocialAdapter, type SocialConfig, type SocialPlatformConfig, type StructuredSchema, type TimelineOptions, TwitterAdapter, type TwitterConfig, buildDecisionPrompt, buildSkillPrompt, buildSystemPrompt, builtInActions, createApp, createLogger, createMarkdownAction, createRoutes, startServer, validateConfig };
583
+ export { type Action, type ActionContext, ActionHandler, ActionRegistry, type ActionResult, Agent, type AgentConfig, type AgentState, AnthropicProvider, type BehaviorTrigger, ConfigLoader, type ConfigType, type CustomAPIConfig, type CustomCLIConfig, type CustomDeploymentConfig, type CustomDockerConfig, type CustomSSHConfig, type Decision, type DeploymentConfig, type DeploymentResult, type DeploymentStatus, type Experience, type FeedOptions, type GenerateOptions, LLMProvider, type LifecycleEvent, type LifecycleHooks, LongTermMemory, MarkdownParser, Memory, type Mention, type Message, MoltbookAdapter, type MoltbookConfig, OpenAIProvider, type Plugin, type Post, type PostResult, type PostgresConfig, type Profile, type RedisConfig, type ReplyResult, type ScheduledJob, type ScheduledTask, Scheduler, ShortTermMemory, SocialAdapter, type SocialConfig, type SocialPlatformConfig, type StructuredSchema, type TimelineOptions, TwitterAdapter, type TwitterConfig, buildDecisionPrompt, buildSkillPrompt, buildSystemPrompt, builtInActions, createApp, createLogger, createMarkdownAction, createRoutes, startServer, validateConfig };
package/dist/index.d.ts CHANGED
@@ -7,7 +7,7 @@ interface MoltbookConfig {
7
7
  apiKey: string;
8
8
  baseUrl?: string;
9
9
  defaultSubmolt?: string;
10
- postFrequency?: 'realtime' | 'hourly' | 'daily';
10
+ postFrequency?: string;
11
11
  engagementRate?: 'low' | 'medium' | 'high';
12
12
  autoReply?: boolean;
13
13
  replyFilter?: (post: any) => boolean;
@@ -21,7 +21,7 @@ interface TwitterConfig {
21
21
  accessSecret: string;
22
22
  bearerToken?: string;
23
23
  };
24
- postFrequency?: 'realtime' | 'hourly' | 'daily';
24
+ postFrequency?: string;
25
25
  replyToMentions?: boolean;
26
26
  autoRetweet?: boolean;
27
27
  maxTweetsPerDay?: number;
@@ -60,6 +60,11 @@ interface Plugin {
60
60
  init?: (agent: any) => Promise<void>;
61
61
  destroy?: () => Promise<void>;
62
62
  }
63
+ interface ScheduledTask {
64
+ name: string;
65
+ intervalMs: number;
66
+ instructions: string;
67
+ }
63
68
  interface AgentConfig {
64
69
  name: string;
65
70
  type?: string;
@@ -96,6 +101,7 @@ interface AgentConfig {
96
101
  };
97
102
  actions: string[];
98
103
  customActions?: Action[];
104
+ scheduling?: ScheduledTask[];
99
105
  webhooks?: {
100
106
  onAction?: string | ((action: any, result: any) => Promise<void>);
101
107
  onError?: string;
@@ -374,6 +380,11 @@ declare class Agent {
374
380
  private initMoltbook;
375
381
  private initTwitter;
376
382
  private postStartupMessages;
383
+ private initScheduledJobs;
384
+ private wirePostFrequencyJobs;
385
+ private wireSchedulingTasks;
386
+ private scheduledPost;
387
+ private executeScheduledTask;
377
388
  private logPlatformError;
378
389
  private startAutonomousLoop;
379
390
  private isSleeping;
@@ -424,6 +435,9 @@ declare class MarkdownParser {
424
435
  private parseMemory;
425
436
  private parseSleepSchedule;
426
437
  private parseKeyValueLines;
438
+ private parseScheduling;
439
+ private parseIntervalFromTitle;
440
+ private toCamelCase;
427
441
  private toSnakeCase;
428
442
  }
429
443
 
@@ -566,4 +580,4 @@ declare function createRoutes(agent: Agent): Router;
566
580
 
567
581
  declare function createLogger(label: string): winston.Logger;
568
582
 
569
- export { type Action, type ActionContext, ActionHandler, ActionRegistry, type ActionResult, Agent, type AgentConfig, type AgentState, AnthropicProvider, type BehaviorTrigger, ConfigLoader, type ConfigType, type CustomAPIConfig, type CustomCLIConfig, type CustomDeploymentConfig, type CustomDockerConfig, type CustomSSHConfig, type Decision, type DeploymentConfig, type DeploymentResult, type DeploymentStatus, type Experience, type FeedOptions, type GenerateOptions, LLMProvider, type LifecycleEvent, type LifecycleHooks, LongTermMemory, MarkdownParser, Memory, type Mention, type Message, MoltbookAdapter, type MoltbookConfig, OpenAIProvider, type Plugin, type Post, type PostResult, type PostgresConfig, type Profile, type RedisConfig, type ReplyResult, type ScheduledJob, Scheduler, ShortTermMemory, SocialAdapter, type SocialConfig, type SocialPlatformConfig, type StructuredSchema, type TimelineOptions, TwitterAdapter, type TwitterConfig, buildDecisionPrompt, buildSkillPrompt, buildSystemPrompt, builtInActions, createApp, createLogger, createMarkdownAction, createRoutes, startServer, validateConfig };
583
+ export { type Action, type ActionContext, ActionHandler, ActionRegistry, type ActionResult, Agent, type AgentConfig, type AgentState, AnthropicProvider, type BehaviorTrigger, ConfigLoader, type ConfigType, type CustomAPIConfig, type CustomCLIConfig, type CustomDeploymentConfig, type CustomDockerConfig, type CustomSSHConfig, type Decision, type DeploymentConfig, type DeploymentResult, type DeploymentStatus, type Experience, type FeedOptions, type GenerateOptions, LLMProvider, type LifecycleEvent, type LifecycleHooks, LongTermMemory, MarkdownParser, Memory, type Mention, type Message, MoltbookAdapter, type MoltbookConfig, OpenAIProvider, type Plugin, type Post, type PostResult, type PostgresConfig, type Profile, type RedisConfig, type ReplyResult, type ScheduledJob, type ScheduledTask, Scheduler, ShortTermMemory, SocialAdapter, type SocialConfig, type SocialPlatformConfig, type StructuredSchema, type TimelineOptions, TwitterAdapter, type TwitterConfig, buildDecisionPrompt, buildSkillPrompt, buildSystemPrompt, builtInActions, createApp, createLogger, createMarkdownAction, createRoutes, startServer, validateConfig };
package/dist/index.js CHANGED
@@ -799,6 +799,33 @@ var TwitterAdapter = class extends SocialAdapter {
799
799
 
800
800
  // src/agent/Agent.ts
801
801
  var logger4 = createLogger("Agent");
802
+ function parsePostFrequency(freq) {
803
+ const lower = freq.toLowerCase().trim();
804
+ if (lower === "realtime") return 5 * 60 * 1e3;
805
+ if (lower === "hourly") return 60 * 60 * 1e3;
806
+ if (lower === "daily") return 24 * 60 * 60 * 1e3;
807
+ const match = lower.match(/^(\d+)\s*(m|min|mins|minutes?|h|hr|hrs|hours?|d|days?)$/);
808
+ if (match) {
809
+ const n = parseInt(match[1], 10);
810
+ const unit = match[2][0];
811
+ if (unit === "m") return n * 60 * 1e3;
812
+ if (unit === "h") return n * 60 * 60 * 1e3;
813
+ if (unit === "d") return n * 24 * 60 * 60 * 1e3;
814
+ }
815
+ const nlMin = lower.match(/every\s+(\d+)\s+minutes?/);
816
+ if (nlMin) return parseInt(nlMin[1], 10) * 60 * 1e3;
817
+ const nlHour = lower.match(/every\s+(\d+)\s+hours?/);
818
+ if (nlHour) return parseInt(nlHour[1], 10) * 60 * 60 * 1e3;
819
+ if (/every\s+hour/.test(lower)) return 60 * 60 * 1e3;
820
+ if (/every\s+day/.test(lower)) return 24 * 60 * 60 * 1e3;
821
+ return 0;
822
+ }
823
+ function formatInterval(ms) {
824
+ if (ms < 60 * 1e3) return `${Math.round(ms / 1e3)}s`;
825
+ if (ms < 60 * 60 * 1e3) return `${Math.round(ms / 6e4)}m`;
826
+ if (ms < 24 * 60 * 60 * 1e3) return `${Math.round(ms / 36e5)}h`;
827
+ return `${Math.round(ms / 864e5)}d`;
828
+ }
802
829
  var Agent = class {
803
830
  config;
804
831
  state = "idle";
@@ -869,6 +896,7 @@ var Agent = class {
869
896
  this.initLLM();
870
897
  this.registerActions();
871
898
  await this.initSocialAdapters();
899
+ this.initScheduledJobs();
872
900
  if (this.hooks.onInit) {
873
901
  await this.hooks.onInit(this);
874
902
  }
@@ -1108,7 +1136,23 @@ var Agent = class {
1108
1136
  logger4.info("Startup post: No connected social adapters \u2014 skipping");
1109
1137
  return;
1110
1138
  }
1111
- const content = `${this.config.name} is now online and ready.`;
1139
+ let content;
1140
+ 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.`;
1147
+ content = (await this.llm.generateText(prompt, {
1148
+ temperature: this.config.llm.temperature ?? 0.8,
1149
+ maxTokens: 280
1150
+ })).trim();
1151
+ logger4.info(`Startup post: LLM generated content (${content.length} chars)`);
1152
+ } catch (error) {
1153
+ logger4.warn(`Startup post: LLM generation failed (${error.message}), using fallback`);
1154
+ content = `${this.config.name} is now online and ready.`;
1155
+ }
1112
1156
  for (const [platform, adapter] of adapters) {
1113
1157
  logger4.info(`Startup post: Posting to ${platform}...`);
1114
1158
  try {
@@ -1120,6 +1164,107 @@ var Agent = class {
1120
1164
  }
1121
1165
  }
1122
1166
  }
1167
+ initScheduledJobs() {
1168
+ this.wirePostFrequencyJobs();
1169
+ this.wireSchedulingTasks();
1170
+ }
1171
+ wirePostFrequencyJobs() {
1172
+ const social = this.config.social;
1173
+ if (social.moltbook?.enabled !== false && this.socialAdapters["moltbook"]) {
1174
+ const freq = social.moltbook?.postFrequency;
1175
+ if (freq) {
1176
+ const intervalMs = parsePostFrequency(freq);
1177
+ if (intervalMs > 0) {
1178
+ this.scheduler.addJob({
1179
+ name: "moltbook_scheduled_post",
1180
+ intervalMs,
1181
+ handler: async () => {
1182
+ await this.scheduledPost("moltbook");
1183
+ }
1184
+ });
1185
+ logger4.info(`Scheduler: Moltbook posting every ${formatInterval(intervalMs)}`);
1186
+ }
1187
+ }
1188
+ }
1189
+ if (social.twitter?.enabled !== false && this.socialAdapters["twitter"]) {
1190
+ const freq = social.twitter?.postFrequency;
1191
+ if (freq) {
1192
+ const intervalMs = parsePostFrequency(freq);
1193
+ if (intervalMs > 0) {
1194
+ this.scheduler.addJob({
1195
+ name: "twitter_scheduled_post",
1196
+ intervalMs,
1197
+ handler: async () => {
1198
+ await this.scheduledPost("twitter");
1199
+ }
1200
+ });
1201
+ logger4.info(`Scheduler: Twitter posting every ${formatInterval(intervalMs)}`);
1202
+ }
1203
+ }
1204
+ }
1205
+ }
1206
+ wireSchedulingTasks() {
1207
+ const tasks = this.config.scheduling;
1208
+ if (!tasks || tasks.length === 0) return;
1209
+ for (const task of tasks) {
1210
+ this.scheduler.addJob({
1211
+ name: task.name,
1212
+ intervalMs: task.intervalMs,
1213
+ handler: async () => {
1214
+ await this.executeScheduledTask(task);
1215
+ }
1216
+ });
1217
+ logger4.info(`Scheduler: "${task.name}" every ${formatInterval(task.intervalMs)}`);
1218
+ }
1219
+ }
1220
+ async scheduledPost(platform) {
1221
+ const adapter = this.socialAdapters[platform];
1222
+ if (!adapter) return;
1223
+ 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.`;
1225
+ const content = await this.llm.generateText(prompt, {
1226
+ temperature: this.config.llm.temperature ?? 0.8,
1227
+ maxTokens: 280
1228
+ });
1229
+ const result = await adapter.post(content.trim());
1230
+ logger4.info(`Scheduled post: ${platform} SUCCESS \u2014 id=${result.id}`);
1231
+ } catch (error) {
1232
+ logger4.error(`Scheduled post: ${platform} FAILED \u2014 ${error.message || error}`);
1233
+ this.logPlatformError(platform, error);
1234
+ }
1235
+ }
1236
+ async executeScheduledTask(task) {
1237
+ try {
1238
+ logger4.info(`Scheduled task: Running "${task.name}"`);
1239
+ const prompt = `You are ${this.config.name}, an autonomous agent. Execute the following scheduled task.
1240
+
1241
+ Task: ${task.name}
1242
+ Instructions:
1243
+ ${task.instructions}
1244
+
1245
+ Available social platforms: ${Object.keys(this.socialAdapters).join(", ") || "none"}
1246
+
1247
+ Decide what action to take. Respond with JSON:
1248
+ { "action": "<action_name>", "reasoning": "<why>", "parameters": { ... } }`;
1249
+ const decision = await this.llm.generateStructured(
1250
+ prompt,
1251
+ {
1252
+ type: "object",
1253
+ properties: {
1254
+ action: { type: "string" },
1255
+ reasoning: { type: "string" },
1256
+ parameters: { type: "object" }
1257
+ },
1258
+ required: ["action", "reasoning", "parameters"]
1259
+ },
1260
+ { systemPrompt: this.systemPrompt, temperature: this.config.llm.temperature }
1261
+ );
1262
+ const result = await this.act(decision.action, decision.parameters);
1263
+ logger4.info(`Scheduled task: "${task.name}" completed \u2014 action=${decision.action}, success=${result.success}`);
1264
+ } catch (error) {
1265
+ logger4.error(`Scheduled task: "${task.name}" FAILED \u2014 ${error.message || error}`);
1266
+ }
1267
+ }
1123
1268
  logPlatformError(platform, error) {
1124
1269
  if (!error.response) {
1125
1270
  if (error.code === "ENOTFOUND") {
@@ -1236,6 +1381,9 @@ var MarkdownParser = class {
1236
1381
  if (skills) {
1237
1382
  config.actions = skills.children.map((s) => this.toSnakeCase(s.title));
1238
1383
  }
1384
+ if (scheduling && scheduling.children.length > 0) {
1385
+ config.scheduling = this.parseScheduling(scheduling);
1386
+ }
1239
1387
  return config;
1240
1388
  }
1241
1389
  parseSkills(markdown) {
@@ -1300,9 +1448,13 @@ var MarkdownParser = class {
1300
1448
  const fields = this.parseKeyValueLines(child.content);
1301
1449
  const enabled = fields["enabled"] === "true";
1302
1450
  delete fields["enabled"];
1451
+ const camelFields = {};
1452
+ for (const [key, value] of Object.entries(fields)) {
1453
+ camelFields[this.toCamelCase(key)] = value;
1454
+ }
1303
1455
  social[platform] = {
1304
1456
  enabled,
1305
- ...fields
1457
+ ...camelFields
1306
1458
  };
1307
1459
  }
1308
1460
  return social;
@@ -1342,6 +1494,37 @@ var MarkdownParser = class {
1342
1494
  }
1343
1495
  return result;
1344
1496
  }
1497
+ parseScheduling(section) {
1498
+ const tasks = [];
1499
+ for (const child of section.children) {
1500
+ const title = child.title.trim();
1501
+ if (/^on\s+startup$/i.test(title)) continue;
1502
+ const intervalMs = this.parseIntervalFromTitle(title);
1503
+ if (intervalMs <= 0) continue;
1504
+ const instructions = child.content.trim();
1505
+ if (!instructions) continue;
1506
+ tasks.push({
1507
+ name: this.toSnakeCase(title),
1508
+ intervalMs,
1509
+ instructions
1510
+ });
1511
+ }
1512
+ return tasks;
1513
+ }
1514
+ parseIntervalFromTitle(title) {
1515
+ const lower = title.toLowerCase();
1516
+ const minMatch = lower.match(/every\s+(\d+)\s+minutes?/);
1517
+ if (minMatch) return parseInt(minMatch[1], 10) * 60 * 1e3;
1518
+ if (/every\s+hour$/i.test(lower)) return 60 * 60 * 1e3;
1519
+ const hourMatch = lower.match(/every\s+(\d+)\s+hours?/);
1520
+ if (hourMatch) return parseInt(hourMatch[1], 10) * 60 * 60 * 1e3;
1521
+ if (/every\s+day/i.test(lower)) return 24 * 60 * 60 * 1e3;
1522
+ if (/every\s+week/i.test(lower)) return 7 * 24 * 60 * 60 * 1e3;
1523
+ return 0;
1524
+ }
1525
+ toCamelCase(str) {
1526
+ return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
1527
+ }
1345
1528
  toSnakeCase(str) {
1346
1529
  return str.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
1347
1530
  }