@moltium/core 0.1.10 → 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 +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.js +168 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +168 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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?:
|
|
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?:
|
|
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?:
|
|
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?:
|
|
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
|
}
|
|
@@ -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
|
-
...
|
|
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
|
}
|