@moltium/core 0.1.9 → 0.1.11

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
  }
@@ -1014,10 +1042,10 @@ var Agent = class {
1014
1042
  const configMoltbook = social.moltbook;
1015
1043
  const apiKey = configMoltbook?.apiKey || envKey || "";
1016
1044
  const isPlaceholder = !apiKey || apiKey === "your-moltbook-key-here";
1017
- const explicitlyDisabled = configMoltbook && configMoltbook.enabled === false;
1045
+ const explicitlyDisabled = configMoltbook && configMoltbook.enabled === false && !envKey;
1018
1046
  const shouldConnect = !isPlaceholder && !explicitlyDisabled;
1019
1047
  if (explicitlyDisabled) {
1020
- logger4.info("Moltbook: Disabled in config (enabled: false) \u2014 skipping");
1048
+ logger4.info("Moltbook: Disabled in config and no MOLTBOOK_API_KEY in env \u2014 skipping");
1021
1049
  return;
1022
1050
  }
1023
1051
  if (isPlaceholder) {
@@ -1067,9 +1095,9 @@ var Agent = class {
1067
1095
  const accessSecret = creds?.accessSecret || envAccessSecret || "";
1068
1096
  const hasKey = apiKey && apiKey !== "your-twitter-api-key";
1069
1097
  const hasAllCreds = hasKey && apiSecret && accessToken && accessSecret;
1070
- const explicitlyDisabled = configTwitter && configTwitter.enabled === false;
1098
+ const explicitlyDisabled = configTwitter && configTwitter.enabled === false && !envApiKey;
1071
1099
  if (explicitlyDisabled) {
1072
- logger4.info("Twitter: Disabled in config (enabled: false) \u2014 skipping");
1100
+ logger4.info("Twitter: Disabled in config and no TWITTER_API_KEY in env \u2014 skipping");
1073
1101
  return;
1074
1102
  }
1075
1103
  if (!hasKey) {
@@ -1120,6 +1148,107 @@ var Agent = class {
1120
1148
  }
1121
1149
  }
1122
1150
  }
1151
+ initScheduledJobs() {
1152
+ this.wirePostFrequencyJobs();
1153
+ this.wireSchedulingTasks();
1154
+ }
1155
+ wirePostFrequencyJobs() {
1156
+ const social = this.config.social;
1157
+ if (social.moltbook?.enabled !== false && this.socialAdapters["moltbook"]) {
1158
+ const freq = social.moltbook?.postFrequency;
1159
+ if (freq) {
1160
+ const intervalMs = parsePostFrequency(freq);
1161
+ if (intervalMs > 0) {
1162
+ this.scheduler.addJob({
1163
+ name: "moltbook_scheduled_post",
1164
+ intervalMs,
1165
+ handler: async () => {
1166
+ await this.scheduledPost("moltbook");
1167
+ }
1168
+ });
1169
+ logger4.info(`Scheduler: Moltbook posting every ${formatInterval(intervalMs)}`);
1170
+ }
1171
+ }
1172
+ }
1173
+ if (social.twitter?.enabled !== false && this.socialAdapters["twitter"]) {
1174
+ const freq = social.twitter?.postFrequency;
1175
+ if (freq) {
1176
+ const intervalMs = parsePostFrequency(freq);
1177
+ if (intervalMs > 0) {
1178
+ this.scheduler.addJob({
1179
+ name: "twitter_scheduled_post",
1180
+ intervalMs,
1181
+ handler: async () => {
1182
+ await this.scheduledPost("twitter");
1183
+ }
1184
+ });
1185
+ logger4.info(`Scheduler: Twitter posting every ${formatInterval(intervalMs)}`);
1186
+ }
1187
+ }
1188
+ }
1189
+ }
1190
+ wireSchedulingTasks() {
1191
+ const tasks = this.config.scheduling;
1192
+ if (!tasks || tasks.length === 0) return;
1193
+ for (const task of tasks) {
1194
+ this.scheduler.addJob({
1195
+ name: task.name,
1196
+ intervalMs: task.intervalMs,
1197
+ handler: async () => {
1198
+ await this.executeScheduledTask(task);
1199
+ }
1200
+ });
1201
+ logger4.info(`Scheduler: "${task.name}" every ${formatInterval(task.intervalMs)}`);
1202
+ }
1203
+ }
1204
+ async scheduledPost(platform) {
1205
+ const adapter = this.socialAdapters[platform];
1206
+ if (!adapter) return;
1207
+ try {
1208
+ 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.`;
1209
+ const content = await this.llm.generateText(prompt, {
1210
+ temperature: this.config.llm.temperature ?? 0.8,
1211
+ maxTokens: 280
1212
+ });
1213
+ const result = await adapter.post(content.trim());
1214
+ logger4.info(`Scheduled post: ${platform} SUCCESS \u2014 id=${result.id}`);
1215
+ } catch (error) {
1216
+ logger4.error(`Scheduled post: ${platform} FAILED \u2014 ${error.message || error}`);
1217
+ this.logPlatformError(platform, error);
1218
+ }
1219
+ }
1220
+ async executeScheduledTask(task) {
1221
+ try {
1222
+ logger4.info(`Scheduled task: Running "${task.name}"`);
1223
+ const prompt = `You are ${this.config.name}, an autonomous agent. Execute the following scheduled task.
1224
+
1225
+ Task: ${task.name}
1226
+ Instructions:
1227
+ ${task.instructions}
1228
+
1229
+ Available social platforms: ${Object.keys(this.socialAdapters).join(", ") || "none"}
1230
+
1231
+ Decide what action to take. Respond with JSON:
1232
+ { "action": "<action_name>", "reasoning": "<why>", "parameters": { ... } }`;
1233
+ const decision = await this.llm.generateStructured(
1234
+ prompt,
1235
+ {
1236
+ type: "object",
1237
+ properties: {
1238
+ action: { type: "string" },
1239
+ reasoning: { type: "string" },
1240
+ parameters: { type: "object" }
1241
+ },
1242
+ required: ["action", "reasoning", "parameters"]
1243
+ },
1244
+ { systemPrompt: this.systemPrompt, temperature: this.config.llm.temperature }
1245
+ );
1246
+ const result = await this.act(decision.action, decision.parameters);
1247
+ logger4.info(`Scheduled task: "${task.name}" completed \u2014 action=${decision.action}, success=${result.success}`);
1248
+ } catch (error) {
1249
+ logger4.error(`Scheduled task: "${task.name}" FAILED \u2014 ${error.message || error}`);
1250
+ }
1251
+ }
1123
1252
  logPlatformError(platform, error) {
1124
1253
  if (!error.response) {
1125
1254
  if (error.code === "ENOTFOUND") {
@@ -1236,6 +1365,9 @@ var MarkdownParser = class {
1236
1365
  if (skills) {
1237
1366
  config.actions = skills.children.map((s) => this.toSnakeCase(s.title));
1238
1367
  }
1368
+ if (scheduling && scheduling.children.length > 0) {
1369
+ config.scheduling = this.parseScheduling(scheduling);
1370
+ }
1239
1371
  return config;
1240
1372
  }
1241
1373
  parseSkills(markdown) {
@@ -1300,9 +1432,13 @@ var MarkdownParser = class {
1300
1432
  const fields = this.parseKeyValueLines(child.content);
1301
1433
  const enabled = fields["enabled"] === "true";
1302
1434
  delete fields["enabled"];
1435
+ const camelFields = {};
1436
+ for (const [key, value] of Object.entries(fields)) {
1437
+ camelFields[this.toCamelCase(key)] = value;
1438
+ }
1303
1439
  social[platform] = {
1304
1440
  enabled,
1305
- ...fields
1441
+ ...camelFields
1306
1442
  };
1307
1443
  }
1308
1444
  return social;
@@ -1342,6 +1478,37 @@ var MarkdownParser = class {
1342
1478
  }
1343
1479
  return result;
1344
1480
  }
1481
+ parseScheduling(section) {
1482
+ const tasks = [];
1483
+ for (const child of section.children) {
1484
+ const title = child.title.trim();
1485
+ if (/^on\s+startup$/i.test(title)) continue;
1486
+ const intervalMs = this.parseIntervalFromTitle(title);
1487
+ if (intervalMs <= 0) continue;
1488
+ const instructions = child.content.trim();
1489
+ if (!instructions) continue;
1490
+ tasks.push({
1491
+ name: this.toSnakeCase(title),
1492
+ intervalMs,
1493
+ instructions
1494
+ });
1495
+ }
1496
+ return tasks;
1497
+ }
1498
+ parseIntervalFromTitle(title) {
1499
+ const lower = title.toLowerCase();
1500
+ const minMatch = lower.match(/every\s+(\d+)\s+minutes?/);
1501
+ if (minMatch) return parseInt(minMatch[1], 10) * 60 * 1e3;
1502
+ if (/every\s+hour$/i.test(lower)) return 60 * 60 * 1e3;
1503
+ const hourMatch = lower.match(/every\s+(\d+)\s+hours?/);
1504
+ if (hourMatch) return parseInt(hourMatch[1], 10) * 60 * 60 * 1e3;
1505
+ if (/every\s+day/i.test(lower)) return 24 * 60 * 60 * 1e3;
1506
+ if (/every\s+week/i.test(lower)) return 7 * 24 * 60 * 60 * 1e3;
1507
+ return 0;
1508
+ }
1509
+ toCamelCase(str) {
1510
+ return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
1511
+ }
1345
1512
  toSnakeCase(str) {
1346
1513
  return str.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
1347
1514
  }