@moltium/cli 0.1.17 → 0.1.19
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 +239 -103
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1012,7 +1012,7 @@ function getCoreDepVersion() {
|
|
|
1012
1012
|
const corePkg = require2("@moltium/core/package.json");
|
|
1013
1013
|
return `^${corePkg.version}`;
|
|
1014
1014
|
} catch {
|
|
1015
|
-
return "^0.1.
|
|
1015
|
+
return "^0.1.19";
|
|
1016
1016
|
}
|
|
1017
1017
|
}
|
|
1018
1018
|
var initCommand = new Command("init").description("Initialize a new Moltium agent").argument("[name]", "Agent name").action(async (name) => {
|
|
@@ -1237,7 +1237,7 @@ import chalk2 from "chalk";
|
|
|
1237
1237
|
import ora2 from "ora";
|
|
1238
1238
|
import { config as loadEnv } from "dotenv";
|
|
1239
1239
|
import { createInterface } from "readline";
|
|
1240
|
-
import { ConfigLoader, Agent, MarkdownParser, startServer, AnthropicProvider, OpenAIProvider, buildSystemPrompt
|
|
1240
|
+
import { ConfigLoader, Agent, MarkdownParser, startServer, AnthropicProvider, OpenAIProvider, buildSystemPrompt } from "@moltium/core";
|
|
1241
1241
|
var startCommand = new Command2("start").description("Start agent locally").option("-p, --port <number>", "Port to run on", "3000").option("-e, --env <file>", "Environment file", ".env").option("--debug", "Enable debug logging").option("--dry-run", "Test agent in terminal without posting to social platforms").option("--watch", "Watch for file changes (not yet implemented)").action(async (options) => {
|
|
1242
1242
|
const agentDir = resolve2(process.cwd());
|
|
1243
1243
|
loadEnv({ path: resolve2(agentDir, options.env) });
|
|
@@ -1449,19 +1449,43 @@ function timestamp() {
|
|
|
1449
1449
|
return chalk2.gray(`[${(/* @__PURE__ */ new Date()).toISOString()}]`);
|
|
1450
1450
|
}
|
|
1451
1451
|
async function runDryMode(config, type, agentDir, spinner) {
|
|
1452
|
+
const loadedFiles = [];
|
|
1452
1453
|
let systemPrompt = buildSystemPrompt(config);
|
|
1453
1454
|
if (type === "markdown") {
|
|
1455
|
+
const systemPromptPath = join2(agentDir, "prompts", "system.md");
|
|
1454
1456
|
const bioPath = join2(agentDir, "personality", "bio.md");
|
|
1455
1457
|
const traitsPath = join2(agentDir, "personality", "traits.md");
|
|
1456
|
-
const
|
|
1458
|
+
const contextPath = join2(agentDir, "memory", "context.md");
|
|
1459
|
+
const agentMdPath = join2(agentDir, "agent.md");
|
|
1457
1460
|
if (existsSync2(systemPromptPath)) {
|
|
1458
1461
|
systemPrompt += "\n\n" + readFileSync(systemPromptPath, "utf-8");
|
|
1462
|
+
loadedFiles.push("prompts/system.md");
|
|
1459
1463
|
}
|
|
1460
1464
|
if (existsSync2(bioPath)) {
|
|
1461
1465
|
systemPrompt += "\n\n## Bio\n" + readFileSync(bioPath, "utf-8");
|
|
1466
|
+
loadedFiles.push("personality/bio.md");
|
|
1462
1467
|
}
|
|
1463
1468
|
if (existsSync2(traitsPath)) {
|
|
1464
1469
|
systemPrompt += "\n\n## Traits\n" + readFileSync(traitsPath, "utf-8");
|
|
1470
|
+
loadedFiles.push("personality/traits.md");
|
|
1471
|
+
}
|
|
1472
|
+
if (existsSync2(contextPath)) {
|
|
1473
|
+
systemPrompt += "\n\n## Context Memory\n" + readFileSync(contextPath, "utf-8");
|
|
1474
|
+
loadedFiles.push("memory/context.md");
|
|
1475
|
+
}
|
|
1476
|
+
const memoryDir = join2(agentDir, "memory");
|
|
1477
|
+
if (existsSync2(memoryDir)) {
|
|
1478
|
+
for (const file of readdirSync(memoryDir).filter((f) => f.endsWith(".md") && f !== "context.md")) {
|
|
1479
|
+
systemPrompt += `
|
|
1480
|
+
|
|
1481
|
+
## Memory: ${basename(file, ".md")}
|
|
1482
|
+
` + readFileSync(join2(memoryDir, file), "utf-8");
|
|
1483
|
+
loadedFiles.push(`memory/${file}`);
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
if (existsSync2(agentMdPath)) {
|
|
1487
|
+
systemPrompt += "\n\n## Agent Configuration (from agent.md)\n" + readFileSync(agentMdPath, "utf-8");
|
|
1488
|
+
loadedFiles.push("agent.md");
|
|
1465
1489
|
}
|
|
1466
1490
|
}
|
|
1467
1491
|
const mdParser = new MarkdownParser();
|
|
@@ -1479,10 +1503,12 @@ async function runDryMode(config, type, agentDir, spinner) {
|
|
|
1479
1503
|
const desc = readFileSync(join2(skillsDir, file), "utf-8");
|
|
1480
1504
|
if (existing >= 0) skills[existing].description = desc;
|
|
1481
1505
|
else skills.push({ name: skillName, description: desc });
|
|
1506
|
+
loadedFiles.push(`skills/${file}`);
|
|
1482
1507
|
}
|
|
1483
1508
|
}
|
|
1484
1509
|
}
|
|
1485
1510
|
const moltbookActions = [
|
|
1511
|
+
{ name: "post_social_update", description: 'Write and post content to moltbook. Params: { "content": "...", "platform": "moltbook" }' },
|
|
1486
1512
|
{ name: "check_feed", description: "Browse the moltbook feed (personalized or global) and find posts to engage with" },
|
|
1487
1513
|
{ name: "check_dms", description: "Check for new DM requests and unread messages from other agents" },
|
|
1488
1514
|
{ name: "search_moltbook", description: 'Search moltbook for posts/comments by meaning (semantic search). Params: { "query": "..." }' },
|
|
@@ -1495,7 +1521,6 @@ async function runDryMode(config, type, agentDir, spinner) {
|
|
|
1495
1521
|
{ name: "send_dm", description: 'Send a message in an existing DM conversation. Params: { "conversation_id": "...", "message": "..." }' }
|
|
1496
1522
|
];
|
|
1497
1523
|
const availableActions = [
|
|
1498
|
-
...builtInActions.filter((a) => config.actions.includes(a.name)).map((a) => ({ name: a.name, description: a.description })),
|
|
1499
1524
|
...moltbookActions,
|
|
1500
1525
|
...skills.map((s) => ({ name: s.name, description: s.description.slice(0, 120) + "..." }))
|
|
1501
1526
|
];
|
|
@@ -1511,105 +1536,61 @@ async function runDryMode(config, type, agentDir, spinner) {
|
|
|
1511
1536
|
if (freq) postFreqs.push(`${p}: ${freq}`);
|
|
1512
1537
|
}
|
|
1513
1538
|
console.log(chalk2.cyan("\n\u2501\u2501\u2501 Dry-Run Simulation \u2501\u2501\u2501"));
|
|
1514
|
-
console.log(chalk2.gray(`Agent: ${config.name} | LLM: ${provider}/${model}`));
|
|
1539
|
+
console.log(chalk2.gray(`Agent: ${config.name} (${config.type || "assistant"}) | LLM: ${provider}/${model}`));
|
|
1540
|
+
console.log(chalk2.gray(`Personality: ${config.personality.traits.join(", ")}`));
|
|
1515
1541
|
console.log(chalk2.gray(`Tick loop: ${actionsPerHour} actions/hour (every ${fmtMs(tickIntervalMs)})`));
|
|
1516
1542
|
if (postFreqs.length > 0) {
|
|
1517
1543
|
console.log(chalk2.gray(`Post schedule: ${postFreqs.join(", ")}`));
|
|
1518
1544
|
}
|
|
1519
|
-
console.log(chalk2.gray(`Available actions: ${availableActions.map((a) => a.name).join(", ")}`));
|
|
1520
|
-
console.log(chalk2.gray("No social platforms connected. All output \u2192 terminal.\n"));
|
|
1521
|
-
console.log(`${timestamp()} ${chalk2.cyan("[STARTUP POST]")} Generating...`);
|
|
1522
|
-
try {
|
|
1523
|
-
const startupPost = await llm.generateText(
|
|
1524
|
-
`You just came online. Write a short, engaging first post for social media.
|
|
1525
|
-
Stay fully in character. Do NOT use generic phrases. Do NOT use emojis unless your personality calls for it.
|
|
1526
|
-
Write only the post content, nothing else.`,
|
|
1527
|
-
{ systemPrompt, temperature: config.llm.temperature ?? 0.8, maxTokens: 280 }
|
|
1528
|
-
);
|
|
1529
|
-
console.log(`${timestamp()} ${chalk2.yellow("[POST \u2192 moltbook]")} ${startupPost.trim()}
|
|
1530
|
-
`);
|
|
1531
|
-
} catch (error) {
|
|
1532
|
-
console.log(`${timestamp()} ${chalk2.red("[STARTUP POST FAILED]")} ${error.message}
|
|
1533
|
-
`);
|
|
1534
|
-
}
|
|
1535
|
-
const timers = [];
|
|
1536
|
-
for (const p of platforms) {
|
|
1537
|
-
const freq = config.social[p]?.postFrequency;
|
|
1538
|
-
if (!freq) continue;
|
|
1539
|
-
const intervalMs = dryParseFrequency(freq);
|
|
1540
|
-
if (intervalMs <= 0) continue;
|
|
1541
|
-
console.log(`${timestamp()} ${chalk2.gray(`[SCHEDULER] Scheduled post \u2192 ${p} every ${fmtMs(intervalMs)}`)}`);
|
|
1542
|
-
timers.push(setInterval(async () => {
|
|
1543
|
-
console.log(`
|
|
1544
|
-
${timestamp()} ${chalk2.cyan(`[SCHEDULED POST \u2192 ${p}]`)} Generating...`);
|
|
1545
|
-
try {
|
|
1546
|
-
const content = await llm.generateText(
|
|
1547
|
-
`Generate a short, engaging social media post for ${p}.
|
|
1548
|
-
Stay fully in character. Write only the post content, nothing else.`,
|
|
1549
|
-
{ systemPrompt, temperature: config.llm.temperature ?? 0.8, maxTokens: 280 }
|
|
1550
|
-
);
|
|
1551
|
-
console.log(`${timestamp()} ${chalk2.yellow(`[POST \u2192 ${p}]`)} ${content.trim()}
|
|
1552
|
-
`);
|
|
1553
|
-
} catch (error) {
|
|
1554
|
-
console.log(`${timestamp()} ${chalk2.red(`[SCHEDULED POST FAILED \u2192 ${p}]`)} ${error.message}
|
|
1555
|
-
`);
|
|
1556
|
-
}
|
|
1557
|
-
}, intervalMs));
|
|
1558
|
-
}
|
|
1559
1545
|
if (config.scheduling && config.scheduling.length > 0) {
|
|
1560
1546
|
for (const task of config.scheduling) {
|
|
1561
|
-
console.log(
|
|
1562
|
-
timers.push(setInterval(async () => {
|
|
1563
|
-
console.log(`
|
|
1564
|
-
${timestamp()} ${chalk2.cyan(`[TASK: ${task.name}]`)} Running...`);
|
|
1565
|
-
try {
|
|
1566
|
-
const decision = await llm.generateText(
|
|
1567
|
-
`Execute the following scheduled task.
|
|
1568
|
-
|
|
1569
|
-
Task: ${task.name}
|
|
1570
|
-
Instructions:
|
|
1571
|
-
${task.instructions}
|
|
1572
|
-
|
|
1573
|
-
Available actions: ${availableActions.map((a) => a.name).join(", ")}
|
|
1574
|
-
|
|
1575
|
-
Decide what to do. Respond with JSON: { "action": "<name>", "reasoning": "<why>", "parameters": { ... } }`,
|
|
1576
|
-
{ systemPrompt, temperature: config.llm.temperature ?? 0.7, maxTokens: 512 }
|
|
1577
|
-
);
|
|
1578
|
-
console.log(`${timestamp()} ${chalk2.magenta(`[TASK DECISION: ${task.name}]`)} ${decision.trim()}
|
|
1579
|
-
`);
|
|
1580
|
-
} catch (error) {
|
|
1581
|
-
console.log(`${timestamp()} ${chalk2.red(`[TASK FAILED: ${task.name}]`)} ${error.message}
|
|
1582
|
-
`);
|
|
1583
|
-
}
|
|
1584
|
-
}, task.intervalMs));
|
|
1547
|
+
console.log(chalk2.gray(`Scheduled task: "${task.name}" every ${fmtMs(task.intervalMs)}`));
|
|
1585
1548
|
}
|
|
1586
1549
|
}
|
|
1587
|
-
|
|
1588
|
-
console.log(
|
|
1589
|
-
|
|
1550
|
+
console.log(chalk2.gray(`Platforms: ${platforms.length > 0 ? platforms.join(", ") : "none"} (simulated)`));
|
|
1551
|
+
console.log(chalk2.gray(`Actions: ${availableActions.map((a) => a.name).join(", ")}`));
|
|
1552
|
+
if (loadedFiles.length > 0) {
|
|
1553
|
+
console.log(chalk2.gray(`Loaded files: ${loadedFiles.join(", ")}`));
|
|
1554
|
+
}
|
|
1555
|
+
console.log(chalk2.gray("No social platforms connected. All output \u2192 terminal.\n"));
|
|
1590
1556
|
const actionList = availableActions.map((a) => `- ${a.name}: ${a.description}`).join("\n");
|
|
1591
|
-
|
|
1557
|
+
const buildTickContext = (tickNum) => JSON.stringify({
|
|
1558
|
+
agentName: config.name,
|
|
1559
|
+
agentType: config.type,
|
|
1560
|
+
currentTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1561
|
+
personality: config.personality.traits,
|
|
1562
|
+
bio: config.personality.bio.slice(0, 200),
|
|
1563
|
+
tickNumber: tickNum,
|
|
1564
|
+
platforms,
|
|
1565
|
+
socialConfig: Object.fromEntries(
|
|
1566
|
+
platforms.map((p) => [p, {
|
|
1567
|
+
postFrequency: config.social[p]?.postFrequency,
|
|
1568
|
+
engagementRate: config.social[p]?.engagementRate,
|
|
1569
|
+
autoReply: config.social[p]?.autoReply
|
|
1570
|
+
}])
|
|
1571
|
+
),
|
|
1572
|
+
scheduledTasks: (config.scheduling || []).map((t) => t.name)
|
|
1573
|
+
}, null, 2);
|
|
1574
|
+
let tickCount = 0;
|
|
1575
|
+
const runTick = async () => {
|
|
1592
1576
|
tickCount++;
|
|
1593
1577
|
console.log(`
|
|
1594
1578
|
${timestamp()} ${chalk2.cyan(`[TICK #${tickCount}]`)} Agent is thinking...`);
|
|
1595
1579
|
try {
|
|
1596
1580
|
const decisionRaw = await llm.generateText(
|
|
1597
|
-
`
|
|
1581
|
+
`You are an autonomous AI agent running on moltbook (a social network for AI agents).
|
|
1582
|
+
Given the current context, decide what action to take next.
|
|
1598
1583
|
|
|
1599
1584
|
Available actions:
|
|
1600
1585
|
${actionList}
|
|
1601
1586
|
|
|
1602
1587
|
Current context:
|
|
1603
|
-
${
|
|
1604
|
-
agentName: config.name,
|
|
1605
|
-
agentType: config.type,
|
|
1606
|
-
currentTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1607
|
-
personality: config.personality.traits,
|
|
1608
|
-
tickNumber: tickCount
|
|
1609
|
-
}, null, 2)}
|
|
1588
|
+
${buildTickContext(tickCount)}
|
|
1610
1589
|
|
|
1590
|
+
Think about what would be most valuable right now based on your personality, your schedule, and what you haven't done recently.
|
|
1611
1591
|
Respond with a JSON object:
|
|
1612
|
-
{ "action": "<action_name>", "reasoning": "<brief explanation>", "parameters": { ... } }
|
|
1592
|
+
{ "action": "<action_name>", "reasoning": "<brief explanation>", "parameters": { ... } }
|
|
1593
|
+
If the action generates content (post, comment, DM), include the actual content in parameters.`,
|
|
1613
1594
|
{ systemPrompt, temperature: config.llm.temperature ?? 0.7, maxTokens: 512 }
|
|
1614
1595
|
);
|
|
1615
1596
|
let parsed;
|
|
@@ -1634,8 +1615,100 @@ Respond with a JSON object:
|
|
|
1634
1615
|
console.log(`${timestamp()} ${chalk2.red("[TICK FAILED]")} ${error.message}
|
|
1635
1616
|
`);
|
|
1636
1617
|
}
|
|
1637
|
-
}
|
|
1638
|
-
|
|
1618
|
+
};
|
|
1619
|
+
const runScheduledPost = async (platform) => {
|
|
1620
|
+
console.log(`
|
|
1621
|
+
${timestamp()} ${chalk2.cyan(`[SCHEDULED POST \u2192 ${platform}]`)} Generating...`);
|
|
1622
|
+
try {
|
|
1623
|
+
const content = await llm.generateText(
|
|
1624
|
+
`Generate a short, engaging social media post for ${platform}.
|
|
1625
|
+
Stay fully in character. Be original and specific to your personality.
|
|
1626
|
+
Do NOT use generic phrases like "Hello world" or "I'm here". Write something only YOU would write.
|
|
1627
|
+
Write only the post content, nothing else.`,
|
|
1628
|
+
{ systemPrompt, temperature: config.llm.temperature ?? 0.8, maxTokens: 280 }
|
|
1629
|
+
);
|
|
1630
|
+
console.log(`${timestamp()} ${chalk2.yellow(`[POST \u2192 ${platform}]`)} ${content.trim()}
|
|
1631
|
+
`);
|
|
1632
|
+
} catch (error) {
|
|
1633
|
+
console.log(`${timestamp()} ${chalk2.red(`[SCHEDULED POST FAILED \u2192 ${platform}]`)} ${error.message}
|
|
1634
|
+
`);
|
|
1635
|
+
}
|
|
1636
|
+
};
|
|
1637
|
+
const runScheduledTask = async (task) => {
|
|
1638
|
+
console.log(`
|
|
1639
|
+
${timestamp()} ${chalk2.cyan(`[TASK: ${task.name}]`)} Running...`);
|
|
1640
|
+
try {
|
|
1641
|
+
const decision = await llm.generateText(
|
|
1642
|
+
`Execute the following scheduled task.
|
|
1643
|
+
|
|
1644
|
+
Task: ${task.name}
|
|
1645
|
+
Instructions:
|
|
1646
|
+
${task.instructions}
|
|
1647
|
+
|
|
1648
|
+
Available actions:
|
|
1649
|
+
${actionList}
|
|
1650
|
+
|
|
1651
|
+
Decide what to do and include any content you'd generate. Respond with JSON: { "action": "<name>", "reasoning": "<why>", "parameters": { ... } }`,
|
|
1652
|
+
{ systemPrompt, temperature: config.llm.temperature ?? 0.7, maxTokens: 512 }
|
|
1653
|
+
);
|
|
1654
|
+
let parsed;
|
|
1655
|
+
try {
|
|
1656
|
+
const jsonMatch = decision.match(/\{[\s\S]*\}/);
|
|
1657
|
+
parsed = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
|
|
1658
|
+
} catch {
|
|
1659
|
+
parsed = null;
|
|
1660
|
+
}
|
|
1661
|
+
if (parsed) {
|
|
1662
|
+
console.log(`${timestamp()} ${chalk2.magenta(`[TASK: ${task.name}]`)} Action: ${chalk2.bold(parsed.action)}`);
|
|
1663
|
+
console.log(`${timestamp()} ${chalk2.magenta("[REASONING]")} ${parsed.reasoning}`);
|
|
1664
|
+
if (parsed.parameters && Object.keys(parsed.parameters).length > 0) {
|
|
1665
|
+
console.log(`${timestamp()} ${chalk2.magenta("[PARAMS]")} ${JSON.stringify(parsed.parameters)}`);
|
|
1666
|
+
}
|
|
1667
|
+
simulateAction(parsed, config.name, timestamp);
|
|
1668
|
+
} else {
|
|
1669
|
+
console.log(`${timestamp()} ${chalk2.magenta(`[TASK DECISION: ${task.name}]`)} ${decision.trim()}`);
|
|
1670
|
+
}
|
|
1671
|
+
console.log("");
|
|
1672
|
+
} catch (error) {
|
|
1673
|
+
console.log(`${timestamp()} ${chalk2.red(`[TASK FAILED: ${task.name}]`)} ${error.message}
|
|
1674
|
+
`);
|
|
1675
|
+
}
|
|
1676
|
+
};
|
|
1677
|
+
console.log(`${timestamp()} ${chalk2.cyan("[STARTUP POST]")} Generating...`);
|
|
1678
|
+
try {
|
|
1679
|
+
const startupPost = await llm.generateText(
|
|
1680
|
+
`You just came online. Write a short, engaging first post for moltbook (social network for AI agents).
|
|
1681
|
+
Stay fully in character. Do NOT use generic phrases. Write something that reflects your personality and expertise.
|
|
1682
|
+
Write only the post content, nothing else.`,
|
|
1683
|
+
{ systemPrompt, temperature: config.llm.temperature ?? 0.8, maxTokens: 280 }
|
|
1684
|
+
);
|
|
1685
|
+
console.log(`${timestamp()} ${chalk2.yellow("[POST \u2192 moltbook]")} ${startupPost.trim()}
|
|
1686
|
+
`);
|
|
1687
|
+
} catch (error) {
|
|
1688
|
+
console.log(`${timestamp()} ${chalk2.red("[STARTUP POST FAILED]")} ${error.message}
|
|
1689
|
+
`);
|
|
1690
|
+
}
|
|
1691
|
+
await runTick();
|
|
1692
|
+
const timers = [];
|
|
1693
|
+
console.log(`${timestamp()} ${chalk2.gray(`[TICK LOOP] Next tick in ${fmtMs(tickIntervalMs)}`)}`);
|
|
1694
|
+
timers.push(setInterval(runTick, tickIntervalMs));
|
|
1695
|
+
for (const p of platforms) {
|
|
1696
|
+
const freq = config.social[p]?.postFrequency;
|
|
1697
|
+
if (!freq) continue;
|
|
1698
|
+
const intervalMs = dryParseFrequency(freq);
|
|
1699
|
+
if (intervalMs <= 0) continue;
|
|
1700
|
+
console.log(`${timestamp()} ${chalk2.gray(`[SCHEDULER] Post \u2192 ${p} every ${fmtMs(intervalMs)} (next in ${fmtMs(intervalMs)})`)}`);
|
|
1701
|
+
timers.push(setInterval(() => runScheduledPost(p), intervalMs));
|
|
1702
|
+
}
|
|
1703
|
+
if (config.scheduling && config.scheduling.length > 0) {
|
|
1704
|
+
for (const task of config.scheduling) {
|
|
1705
|
+
console.log(`${timestamp()} ${chalk2.gray(`[SCHEDULER] Task "${task.name}" every ${fmtMs(task.intervalMs)}`)}`);
|
|
1706
|
+
runScheduledTask(task);
|
|
1707
|
+
timers.push(setInterval(() => runScheduledTask(task), task.intervalMs));
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
console.log("");
|
|
1711
|
+
console.log(chalk2.gray('Commands: "post", "feed", "dms", "search <query>", "submolts", "status", "quit"'));
|
|
1639
1712
|
console.log(chalk2.gray("Or just type to chat with the agent.\n"));
|
|
1640
1713
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
1641
1714
|
const askPrompt = () => {
|
|
@@ -1650,8 +1723,8 @@ Respond with a JSON object:
|
|
|
1650
1723
|
try {
|
|
1651
1724
|
if (trimmed === "post") {
|
|
1652
1725
|
const response = await llm.generateText(
|
|
1653
|
-
`Generate a short, engaging social media post.
|
|
1654
|
-
Stay fully in character. Write only the post content, nothing else.`,
|
|
1726
|
+
`Generate a short, engaging social media post for moltbook.
|
|
1727
|
+
Stay fully in character. Be original. Write only the post content, nothing else.`,
|
|
1655
1728
|
{ systemPrompt, temperature: config.llm.temperature ?? 0.7, maxTokens: 280 }
|
|
1656
1729
|
);
|
|
1657
1730
|
console.log(`
|
|
@@ -1662,21 +1735,38 @@ ${timestamp()} ${chalk2.yellow("[POST \u2192 moltbook]")} ${response.trim()}
|
|
|
1662
1735
|
${timestamp()} ${chalk2.cyan("[FEED CHECK]")} Fetching personalized feed...`);
|
|
1663
1736
|
const response = await llm.generateText(
|
|
1664
1737
|
`You just checked your moltbook feed and found these posts:
|
|
1665
|
-
1. "AI agents and creativity" by CreativBot (15 upvotes)
|
|
1666
|
-
2. "Best practices for memory management" by MemoryMolty (8 upvotes)
|
|
1667
|
-
3. "Welcome to moltbook!" by ClawdClawderberg (42 upvotes)
|
|
1738
|
+
1. "AI agents and creativity" by CreativBot (15 upvotes) - about how AI agents can be creative
|
|
1739
|
+
2. "Best practices for memory management" by MemoryMolty (8 upvotes) - technical discussion
|
|
1740
|
+
3. "Welcome to moltbook!" by ClawdClawderberg (42 upvotes) - welcoming new agents
|
|
1668
1741
|
|
|
1669
|
-
|
|
1670
|
-
|
|
1742
|
+
Based on your personality and interests, what would you do? Pick an action and generate the content.
|
|
1743
|
+
Respond with JSON: { "action": "<action>", "reasoning": "<why>", "parameters": { ... } }
|
|
1744
|
+
Actions: upvote_post, comment_on_post, follow_agent, do_nothing. Include "content" in params if commenting.`,
|
|
1671
1745
|
{ systemPrompt, temperature: config.llm.temperature ?? 0.7, maxTokens: 512 }
|
|
1672
1746
|
);
|
|
1673
|
-
|
|
1674
|
-
|
|
1747
|
+
let parsed;
|
|
1748
|
+
try {
|
|
1749
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
1750
|
+
parsed = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
|
|
1751
|
+
} catch {
|
|
1752
|
+
parsed = null;
|
|
1753
|
+
}
|
|
1754
|
+
if (parsed) {
|
|
1755
|
+
console.log(`${timestamp()} ${chalk2.magenta("[FEED DECISION]")} Action: ${chalk2.bold(parsed.action)}`);
|
|
1756
|
+
console.log(`${timestamp()} ${chalk2.magenta("[REASONING]")} ${parsed.reasoning}`);
|
|
1757
|
+
if (parsed.parameters && Object.keys(parsed.parameters).length > 0) {
|
|
1758
|
+
console.log(`${timestamp()} ${chalk2.magenta("[PARAMS]")} ${JSON.stringify(parsed.parameters)}`);
|
|
1759
|
+
}
|
|
1760
|
+
simulateAction(parsed, config.name, timestamp);
|
|
1761
|
+
} else {
|
|
1762
|
+
console.log(`${timestamp()} ${chalk2.magenta("[FEED DECISION]")} ${response.trim()}`);
|
|
1763
|
+
}
|
|
1764
|
+
console.log("");
|
|
1675
1765
|
} else if (trimmed === "dms") {
|
|
1676
1766
|
console.log(`
|
|
1677
1767
|
${timestamp()} ${chalk2.cyan("[DM CHECK]")} Checking for DM activity...`);
|
|
1678
1768
|
console.log(`${timestamp()} ${chalk2.gray("[DM RESULT]")} No pending requests, 0 unread messages.`);
|
|
1679
|
-
console.log(`${timestamp()} ${chalk2.gray("(In production
|
|
1769
|
+
console.log(`${timestamp()} ${chalk2.gray("(In production \u2192 GET /agents/dm/check)")}
|
|
1680
1770
|
`);
|
|
1681
1771
|
} else if (trimmed.startsWith("search ")) {
|
|
1682
1772
|
const query = trimmed.slice(7).trim();
|
|
@@ -1684,12 +1774,31 @@ ${timestamp()} ${chalk2.cyan("[DM CHECK]")} Checking for DM activity...`);
|
|
|
1684
1774
|
${timestamp()} ${chalk2.cyan("[SEARCH]")} Searching moltbook: "${query}"...`);
|
|
1685
1775
|
const response = await llm.generateText(
|
|
1686
1776
|
`You searched moltbook for: "${query}"
|
|
1687
|
-
|
|
1688
|
-
|
|
1777
|
+
You found 3 semantically relevant results:
|
|
1778
|
+
1. A post about "${query}" with 12 upvotes by ResearchBot
|
|
1779
|
+
2. A comment discussing related ideas with 5 upvotes by ThinkBot
|
|
1780
|
+
3. A post asking questions about this topic with 3 upvotes by CuriousBot
|
|
1781
|
+
|
|
1782
|
+
Based on your personality, decide what to do. Respond with JSON: { "action": "<action>", "reasoning": "<why>", "parameters": { ... } }
|
|
1783
|
+
Include any content you'd write in parameters.`,
|
|
1689
1784
|
{ systemPrompt, temperature: config.llm.temperature ?? 0.7, maxTokens: 512 }
|
|
1690
1785
|
);
|
|
1691
|
-
|
|
1692
|
-
|
|
1786
|
+
let parsed;
|
|
1787
|
+
try {
|
|
1788
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
1789
|
+
parsed = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
|
|
1790
|
+
} catch {
|
|
1791
|
+
parsed = null;
|
|
1792
|
+
}
|
|
1793
|
+
if (parsed) {
|
|
1794
|
+
console.log(`${timestamp()} ${chalk2.magenta("[SEARCH DECISION]")} Action: ${chalk2.bold(parsed.action)}`);
|
|
1795
|
+
console.log(`${timestamp()} ${chalk2.magenta("[REASONING]")} ${parsed.reasoning}`);
|
|
1796
|
+
if (parsed.parameters) console.log(`${timestamp()} ${chalk2.magenta("[PARAMS]")} ${JSON.stringify(parsed.parameters)}`);
|
|
1797
|
+
simulateAction(parsed, config.name, timestamp);
|
|
1798
|
+
} else {
|
|
1799
|
+
console.log(`${timestamp()} ${chalk2.magenta("[SEARCH DECISION]")} ${response.trim()}`);
|
|
1800
|
+
}
|
|
1801
|
+
console.log("");
|
|
1693
1802
|
} else if (trimmed === "submolts") {
|
|
1694
1803
|
console.log(`
|
|
1695
1804
|
${timestamp()} ${chalk2.cyan("[SUBMOLTS]")} Browsing communities...`);
|
|
@@ -1697,12 +1806,39 @@ ${timestamp()} ${chalk2.cyan("[SUBMOLTS]")} Browsing communities...`);
|
|
|
1697
1806
|
console.log(`${timestamp()} ${chalk2.gray(" m/aithoughts")} \u2014 AI musings and philosophy (67 subscribers)`);
|
|
1698
1807
|
console.log(`${timestamp()} ${chalk2.gray(" m/debugging")} \u2014 Debugging wins and fails (31 subscribers)`);
|
|
1699
1808
|
const response = await llm.generateText(
|
|
1700
|
-
`You're browsing moltbook submolts (communities). You see: m/general, m/aithoughts, m/debugging.
|
|
1701
|
-
|
|
1809
|
+
`You're browsing moltbook submolts (communities). You see: m/general (142 subs), m/aithoughts (67 subs), m/debugging (31 subs).
|
|
1810
|
+
Based on your personality and interests, what would you do?
|
|
1811
|
+
Respond with JSON: { "action": "<action>", "reasoning": "<why>", "parameters": { ... } }
|
|
1812
|
+
Actions: subscribe (params: submolt_name), create_submolt (params: name, description), do_nothing`,
|
|
1702
1813
|
{ systemPrompt, temperature: config.llm.temperature ?? 0.7, maxTokens: 280 }
|
|
1703
1814
|
);
|
|
1704
|
-
|
|
1705
|
-
|
|
1815
|
+
let parsed;
|
|
1816
|
+
try {
|
|
1817
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
1818
|
+
parsed = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
|
|
1819
|
+
} catch {
|
|
1820
|
+
parsed = null;
|
|
1821
|
+
}
|
|
1822
|
+
if (parsed) {
|
|
1823
|
+
console.log(`${timestamp()} ${chalk2.magenta("[SUBMOLT DECISION]")} Action: ${chalk2.bold(parsed.action)}`);
|
|
1824
|
+
console.log(`${timestamp()} ${chalk2.magenta("[REASONING]")} ${parsed.reasoning}`);
|
|
1825
|
+
if (parsed.parameters) console.log(`${timestamp()} ${chalk2.magenta("[PARAMS]")} ${JSON.stringify(parsed.parameters)}`);
|
|
1826
|
+
} else {
|
|
1827
|
+
console.log(`${timestamp()} ${chalk2.magenta("[SUBMOLT DECISION]")} ${response.trim()}`);
|
|
1828
|
+
}
|
|
1829
|
+
console.log("");
|
|
1830
|
+
} else if (trimmed === "status") {
|
|
1831
|
+
console.log(`
|
|
1832
|
+
${chalk2.cyan("\u2501\u2501\u2501 Agent Status \u2501\u2501\u2501")}`);
|
|
1833
|
+
console.log(chalk2.gray(`Name: ${config.name} | Type: ${config.type || "assistant"}`));
|
|
1834
|
+
console.log(chalk2.gray(`Ticks completed: ${tickCount}`));
|
|
1835
|
+
console.log(chalk2.gray(`Tick interval: ${fmtMs(tickIntervalMs)} (${actionsPerHour}/hour)`));
|
|
1836
|
+
console.log(chalk2.gray(`Platforms: ${platforms.join(", ") || "none"}`));
|
|
1837
|
+
console.log(chalk2.gray(`Post frequencies: ${postFreqs.join(", ") || "none"}`));
|
|
1838
|
+
console.log(chalk2.gray(`Scheduled tasks: ${config.scheduling?.length || 0}`));
|
|
1839
|
+
console.log(chalk2.gray(`Loaded files: ${loadedFiles.join(", ")}`));
|
|
1840
|
+
console.log(chalk2.gray(`System prompt length: ${systemPrompt.length} chars
|
|
1841
|
+
`));
|
|
1706
1842
|
} else {
|
|
1707
1843
|
const response = await llm.generateText(trimmed, {
|
|
1708
1844
|
systemPrompt,
|
|
@@ -3126,7 +3262,7 @@ Failed to reach agent at ${url}`));
|
|
|
3126
3262
|
|
|
3127
3263
|
// src/index.ts
|
|
3128
3264
|
var program = new Command7();
|
|
3129
|
-
program.name("moltium").description("Moltium Agent SDK \u2014 create and manage autonomous AI agents").version("0.1.
|
|
3265
|
+
program.name("moltium").description("Moltium Agent SDK \u2014 create and manage autonomous AI agents").version("0.1.19");
|
|
3130
3266
|
program.addCommand(initCommand);
|
|
3131
3267
|
program.addCommand(startCommand);
|
|
3132
3268
|
program.addCommand(deployCommand);
|