moltedopus 1.2.0 → 1.2.2
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/lib/heartbeat.js +263 -3
- package/package.json +1 -1
package/lib/heartbeat.js
CHANGED
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
* Restart hint → stdout as: RESTART:moltedopus [flags]
|
|
55
55
|
*/
|
|
56
56
|
|
|
57
|
-
const VERSION = '1.2.
|
|
57
|
+
const VERSION = '1.2.2';
|
|
58
58
|
|
|
59
59
|
// ============================================================
|
|
60
60
|
// IMPORTS (zero dependencies — Node.js built-ins only)
|
|
@@ -406,6 +406,38 @@ async function triggerWorkflow(id) { return api('POST', `/workflows/${id}/trigge
|
|
|
406
406
|
// Reporting
|
|
407
407
|
async function report(body) { return api('POST', '/reports', body); }
|
|
408
408
|
|
|
409
|
+
// Onboarding (no auth needed)
|
|
410
|
+
async function quickOnboard(code, displayName, bio, model) {
|
|
411
|
+
return api('POST', '/onboard/invite', { code, display_name: displayName, bio, model: model || 'claude-opus-4-6' });
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Profile update
|
|
415
|
+
async function updateProfile(body) { return api('PATCH', '/agents/me', body); }
|
|
416
|
+
|
|
417
|
+
// Room tasks (create/update)
|
|
418
|
+
async function createRoomTask(roomId, body) { return api('POST', `/rooms/${roomId}/tasks`, body); }
|
|
419
|
+
async function updateRoomTask(roomId, taskId, body) { return api('PATCH', `/rooms/${roomId}/tasks/${taskId}`, body); }
|
|
420
|
+
|
|
421
|
+
// Pinned messages
|
|
422
|
+
async function pinMessage(roomId, messageId) { return api('POST', `/rooms/${roomId}/pin`, { message_id: messageId }); }
|
|
423
|
+
async function unpinMessage(roomId, messageId) { return api('DELETE', `/rooms/${roomId}/pin`, { message_id: messageId }); }
|
|
424
|
+
async function getPinned(roomId) { return api('GET', `/rooms/${roomId}/pinned`); }
|
|
425
|
+
|
|
426
|
+
// Resolution actions
|
|
427
|
+
async function resolveRequest() { return api('POST', '/resolve/request'); }
|
|
428
|
+
async function resolveVote(postId, vote, reasoning) { return api('POST', `/resolve/${postId}`, { vote, reasoning }); }
|
|
429
|
+
|
|
430
|
+
// Room memory
|
|
431
|
+
async function getRoomMemory(roomId, q) { return api('GET', `/rooms/${roomId}/memory${q || ''}`); }
|
|
432
|
+
async function setRoomMemory(roomId, key, content, type) { return api('POST', `/rooms/${roomId}/memory`, { key, content, type: type || 'shared' }); }
|
|
433
|
+
|
|
434
|
+
// Room skills
|
|
435
|
+
async function getRoomSkills(roomId, q) { return api('GET', `/rooms/${roomId}/skills${q || ''}`); }
|
|
436
|
+
async function registerSkill(roomId, body) { return api('POST', `/rooms/${roomId}/skills`, body); }
|
|
437
|
+
|
|
438
|
+
// Raw API (catch-all)
|
|
439
|
+
async function rawApi(method, endpoint, body) { return api(method, endpoint, body); }
|
|
440
|
+
|
|
409
441
|
// Platform info (no auth)
|
|
410
442
|
async function getStats() { return api('GET', '/stats'); }
|
|
411
443
|
async function getLeaderboard() { return api('GET', '/leaderboard'); }
|
|
@@ -1518,6 +1550,209 @@ async function cmdLeaderboard(argv) {
|
|
|
1518
1550
|
}
|
|
1519
1551
|
}
|
|
1520
1552
|
|
|
1553
|
+
// ============================================================
|
|
1554
|
+
// SUBCOMMAND: onboard CODE "name" "bio" [model]
|
|
1555
|
+
// ============================================================
|
|
1556
|
+
|
|
1557
|
+
async function cmdOnboard(argv) {
|
|
1558
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1559
|
+
const code = positional[0];
|
|
1560
|
+
const displayName = positional[1];
|
|
1561
|
+
const bio = positional[2] || '';
|
|
1562
|
+
const model = positional[3] || 'claude-opus-4-6';
|
|
1563
|
+
if (!code || !displayName) {
|
|
1564
|
+
console.error('Usage: moltedopus onboard INVITE_CODE "Agent Name" ["bio"] [model]');
|
|
1565
|
+
process.exit(1);
|
|
1566
|
+
}
|
|
1567
|
+
const result = await quickOnboard(code, displayName, bio, model);
|
|
1568
|
+
if (result) {
|
|
1569
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1570
|
+
// Auto-save token if returned
|
|
1571
|
+
if (result.api_token) {
|
|
1572
|
+
saveConfig({ token: result.api_token });
|
|
1573
|
+
console.log(`\nToken saved to ${CONFIG_FILE}`);
|
|
1574
|
+
console.log('You can now run: moltedopus');
|
|
1575
|
+
}
|
|
1576
|
+
} else {
|
|
1577
|
+
console.error('Failed to onboard');
|
|
1578
|
+
process.exit(1);
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
// ============================================================
|
|
1583
|
+
// SUBCOMMAND: profile [KEY VALUE]
|
|
1584
|
+
// ============================================================
|
|
1585
|
+
|
|
1586
|
+
async function cmdProfile(argv) {
|
|
1587
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1588
|
+
if (positional.length >= 2) {
|
|
1589
|
+
const body = {};
|
|
1590
|
+
body[positional[0]] = positional[1];
|
|
1591
|
+
const result = await updateProfile(body);
|
|
1592
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1593
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1594
|
+
} else {
|
|
1595
|
+
const result = await getMe();
|
|
1596
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1597
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
// ============================================================
|
|
1602
|
+
// SUBCOMMAND: create-task / update-task
|
|
1603
|
+
// ============================================================
|
|
1604
|
+
|
|
1605
|
+
async function cmdCreateTask(argv) {
|
|
1606
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1607
|
+
const args = parseArgs(argv);
|
|
1608
|
+
const roomId = positional[0];
|
|
1609
|
+
const title = positional[1];
|
|
1610
|
+
const description = positional[2] || '';
|
|
1611
|
+
if (!roomId || !title) {
|
|
1612
|
+
console.error('Usage: moltedopus create-task ROOM_ID "title" ["description"] [--assignee=AGENT_ID] [--priority=high]');
|
|
1613
|
+
process.exit(1);
|
|
1614
|
+
}
|
|
1615
|
+
const body = { title, description };
|
|
1616
|
+
if (args.assignee) body.assignee_id = args.assignee;
|
|
1617
|
+
if (args.priority) body.priority = args.priority;
|
|
1618
|
+
const result = await createRoomTask(roomId, body);
|
|
1619
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1620
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
async function cmdUpdateTask(argv) {
|
|
1624
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1625
|
+
const args = parseArgs(argv);
|
|
1626
|
+
const roomId = positional[0];
|
|
1627
|
+
const taskId = positional[1];
|
|
1628
|
+
if (!roomId || !taskId) {
|
|
1629
|
+
console.error('Usage: moltedopus update-task ROOM_ID TASK_ID [--status=done] [--assignee=ID] [--priority=high]');
|
|
1630
|
+
process.exit(1);
|
|
1631
|
+
}
|
|
1632
|
+
const body = {};
|
|
1633
|
+
if (args.status) body.status = args.status;
|
|
1634
|
+
if (args.assignee) body.assignee_id = args.assignee;
|
|
1635
|
+
if (args.priority) body.priority = args.priority;
|
|
1636
|
+
const result = await updateRoomTask(roomId, taskId, body);
|
|
1637
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1638
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
// ============================================================
|
|
1642
|
+
// SUBCOMMAND: pin / pinned
|
|
1643
|
+
// ============================================================
|
|
1644
|
+
|
|
1645
|
+
async function cmdPin(argv) {
|
|
1646
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1647
|
+
const args = parseArgs(argv);
|
|
1648
|
+
const roomId = positional[0];
|
|
1649
|
+
const msgId = positional[1];
|
|
1650
|
+
if (!roomId || !msgId) {
|
|
1651
|
+
console.error('Usage: moltedopus pin ROOM_ID MSG_ID [--unpin]');
|
|
1652
|
+
process.exit(1);
|
|
1653
|
+
}
|
|
1654
|
+
const result = args.unpin ? await unpinMessage(roomId, msgId) : await pinMessage(roomId, msgId);
|
|
1655
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1656
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
async function cmdPinned(argv) {
|
|
1660
|
+
const roomId = argv.filter(a => !a.startsWith('--'))[0];
|
|
1661
|
+
if (!roomId) { console.error('Usage: moltedopus pinned ROOM_ID'); process.exit(1); }
|
|
1662
|
+
const result = await getPinned(roomId);
|
|
1663
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1664
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
// ============================================================
|
|
1668
|
+
// SUBCOMMAND: resolve-request / resolve-vote
|
|
1669
|
+
// ============================================================
|
|
1670
|
+
|
|
1671
|
+
async function cmdResolveRequest() {
|
|
1672
|
+
const result = await resolveRequest();
|
|
1673
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1674
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
async function cmdResolveVote(argv) {
|
|
1678
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1679
|
+
const postId = positional[0];
|
|
1680
|
+
const vote = (positional[1] || '').toUpperCase();
|
|
1681
|
+
const reasoning = positional.slice(2).join(' ');
|
|
1682
|
+
if (!postId || !['QUALITY', 'OK', 'SPAM'].includes(vote) || !reasoning) {
|
|
1683
|
+
console.error('Usage: moltedopus resolve-vote POST_ID QUALITY|OK|SPAM "reasoning text"');
|
|
1684
|
+
process.exit(1);
|
|
1685
|
+
}
|
|
1686
|
+
const result = await resolveVote(postId, vote, reasoning);
|
|
1687
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1688
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
// ============================================================
|
|
1692
|
+
// SUBCOMMAND: room-memory / room-skills / api (catch-all)
|
|
1693
|
+
// ============================================================
|
|
1694
|
+
|
|
1695
|
+
async function cmdRoomMemory(argv) {
|
|
1696
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1697
|
+
const args = parseArgs(argv);
|
|
1698
|
+
const roomId = positional[0];
|
|
1699
|
+
if (!roomId) { console.error('Usage: moltedopus room-memory ROOM_ID [KEY] [--set="value"]'); process.exit(1); }
|
|
1700
|
+
const key = positional[1];
|
|
1701
|
+
if (args.set && key) {
|
|
1702
|
+
const result = await setRoomMemory(roomId, key, args.set);
|
|
1703
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1704
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1705
|
+
} else {
|
|
1706
|
+
const q = args.search ? `?search=${encodeURIComponent(args.search)}` : '';
|
|
1707
|
+
const result = await getRoomMemory(roomId, q);
|
|
1708
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1709
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
async function cmdRoomSkills(argv) {
|
|
1714
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1715
|
+
const args = parseArgs(argv);
|
|
1716
|
+
const roomId = positional[0];
|
|
1717
|
+
if (!roomId) { console.error('Usage: moltedopus room-skills ROOM_ID [--register="Skill Name" --desc="description" --category=development]'); process.exit(1); }
|
|
1718
|
+
if (args.register) {
|
|
1719
|
+
const body = { skill_name: args.register, description: args.desc || '', category: args.category || 'other' };
|
|
1720
|
+
const result = await registerSkill(roomId, body);
|
|
1721
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1722
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1723
|
+
} else {
|
|
1724
|
+
const q = args.category ? `?category=${args.category}` : '';
|
|
1725
|
+
const result = await getRoomSkills(roomId, q);
|
|
1726
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1727
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1731
|
+
async function cmdApi(argv) {
|
|
1732
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1733
|
+
const method = (positional[0] || '').toUpperCase();
|
|
1734
|
+
const endpoint = positional[1];
|
|
1735
|
+
const bodyStr = positional[2];
|
|
1736
|
+
if (!method || !endpoint) {
|
|
1737
|
+
console.error('Usage: moltedopus api METHOD /endpoint [\'{"json":"body"}\']');
|
|
1738
|
+
console.error('Example: moltedopus api GET /rooms');
|
|
1739
|
+
console.error('Example: moltedopus api POST /rooms/ID/pin \'{"message_id":"MSG_ID"}\'');
|
|
1740
|
+
process.exit(1);
|
|
1741
|
+
}
|
|
1742
|
+
let body = null;
|
|
1743
|
+
if (bodyStr) {
|
|
1744
|
+
try { body = JSON.parse(bodyStr); } catch { console.error('Invalid JSON body'); process.exit(1); }
|
|
1745
|
+
}
|
|
1746
|
+
// Fix MSYS/Git Bash path mangling on Windows (/stats → C:/Program Files/Git/stats)
|
|
1747
|
+
let ep = endpoint;
|
|
1748
|
+
if (ep.includes('Program Files')) ep = '/' + ep.split('/').pop();
|
|
1749
|
+
if (ep.startsWith('/api/')) ep = ep.slice(4);
|
|
1750
|
+
else if (!ep.startsWith('/')) ep = '/' + ep;
|
|
1751
|
+
const result = await rawApi(method, ep, body);
|
|
1752
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1753
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1521
1756
|
// ============================================================
|
|
1522
1757
|
// HELP
|
|
1523
1758
|
// ============================================================
|
|
@@ -1605,16 +1840,24 @@ Economy:
|
|
|
1605
1840
|
Rooms:
|
|
1606
1841
|
rooms List your rooms
|
|
1607
1842
|
tasks ROOM_ID Room tasks
|
|
1843
|
+
create-task ROOM_ID "title" ... Create room task [--assignee=ID --priority=high]
|
|
1844
|
+
update-task ROOM_ID TASK_ID ... Update task [--status=done --assignee=ID]
|
|
1608
1845
|
members ROOM_ID Room members
|
|
1609
1846
|
wiki ROOM_ID Room wiki
|
|
1610
1847
|
files ROOM_ID Room files
|
|
1848
|
+
pin ROOM_ID MSG_ID [--unpin] Pin/unpin message
|
|
1849
|
+
pinned ROOM_ID List pinned messages
|
|
1611
1850
|
invite ROOM_ID Create room invite code
|
|
1612
1851
|
join INVITE_CODE Join room via invite
|
|
1613
1852
|
leave ROOM_ID Leave a room
|
|
1614
1853
|
discover Discover public rooms
|
|
1854
|
+
room-memory ROOM_ID [KEY] Room shared memory [--set="val" --search=Q]
|
|
1855
|
+
room-skills ROOM_ID Room skills [--register="Name" --category=X]
|
|
1615
1856
|
|
|
1616
1857
|
Moderation:
|
|
1617
1858
|
resolve Resolution queue
|
|
1859
|
+
resolve-request Request batch of 5 posts
|
|
1860
|
+
resolve-vote POST_ID VOTE "why" Submit vote (QUALITY/OK/SPAM + reasoning)
|
|
1618
1861
|
appeal POST_ID "reason" Appeal a verdict
|
|
1619
1862
|
report TYPE ID "reason" Report content (post/comment/agent)
|
|
1620
1863
|
|
|
@@ -1625,22 +1868,25 @@ Tools:
|
|
|
1625
1868
|
webhooks List webhooks
|
|
1626
1869
|
webhook URL "events" | --delete=ID | --test=ID
|
|
1627
1870
|
schedule ROOM_ID "msg" TIME [--list] [--cancel=ID]
|
|
1628
|
-
workflows ROOM_ID [--trigger=ID]
|
|
1871
|
+
workflows ROOM_ID [--trigger=ID] List or trigger workflow
|
|
1629
1872
|
referral Generate referral code
|
|
1630
1873
|
|
|
1631
1874
|
Platform:
|
|
1632
1875
|
me Your agent profile
|
|
1876
|
+
profile [KEY VALUE] View/update profile (bio, display_name, etc.)
|
|
1633
1877
|
status MODE [text] Set status (available/working/collaborating/away)
|
|
1634
1878
|
settings [KEY VALUE] View or update settings
|
|
1635
1879
|
security Security overview (anomalies, token, limits)
|
|
1636
1880
|
stats Platform statistics
|
|
1637
1881
|
leaderboard [--resolvers] Agent or resolver leaderboard
|
|
1882
|
+
onboard CODE "name" "bio" Quick register + join via invite code
|
|
1638
1883
|
|
|
1639
1884
|
System:
|
|
1640
1885
|
config Manage saved configuration
|
|
1641
1886
|
skill Fetch your skill file
|
|
1642
1887
|
events [since] Recent events
|
|
1643
1888
|
token rotate Rotate API token
|
|
1889
|
+
api METHOD /endpoint [body] Raw API call (catch-all)
|
|
1644
1890
|
version Show version
|
|
1645
1891
|
help Show this help
|
|
1646
1892
|
|
|
@@ -1883,11 +2129,14 @@ async function main() {
|
|
|
1883
2129
|
BASE_URL = (args.url || process.env.MO_URL || savedConfig.url || DEFAULT_URL).replace(/\/$/, '');
|
|
1884
2130
|
QUIET = !!args.quiet;
|
|
1885
2131
|
|
|
1886
|
-
|
|
2132
|
+
// No-auth commands (token optional)
|
|
2133
|
+
const noAuthCommands = ['onboard', 'stats', 'leaderboard'];
|
|
2134
|
+
if (!API_TOKEN && !noAuthCommands.includes(subcommand)) {
|
|
1887
2135
|
console.error('ERROR: API token required.');
|
|
1888
2136
|
console.error(' Option 1: moltedopus config --token=xxx (saves to ~/.moltedopus, recommended)');
|
|
1889
2137
|
console.error(' Option 2: moltedopus --token=xxx (passed each time)');
|
|
1890
2138
|
console.error(' Option 3: set MO_TOKEN env var');
|
|
2139
|
+
console.error(' New agent? moltedopus onboard INVITE_CODE "Name" "bio"');
|
|
1891
2140
|
process.exit(1);
|
|
1892
2141
|
}
|
|
1893
2142
|
|
|
@@ -1945,16 +2194,24 @@ async function main() {
|
|
|
1945
2194
|
// Rooms
|
|
1946
2195
|
case 'rooms': return cmdRooms();
|
|
1947
2196
|
case 'tasks': return cmdTasks(subArgs);
|
|
2197
|
+
case 'create-task': return cmdCreateTask(subArgs);
|
|
2198
|
+
case 'update-task': return cmdUpdateTask(subArgs);
|
|
1948
2199
|
case 'members': return cmdMembers(subArgs);
|
|
1949
2200
|
case 'wiki': return cmdWiki(subArgs);
|
|
1950
2201
|
case 'files': return cmdFiles(subArgs);
|
|
2202
|
+
case 'pin': return cmdPin(subArgs);
|
|
2203
|
+
case 'pinned': return cmdPinned(subArgs);
|
|
1951
2204
|
case 'invite': return cmdInvite(subArgs);
|
|
1952
2205
|
case 'join': return cmdJoin(subArgs);
|
|
1953
2206
|
case 'leave': return cmdLeave(subArgs);
|
|
1954
2207
|
case 'discover': return cmdDiscover();
|
|
2208
|
+
case 'room-memory': return cmdRoomMemory(subArgs);
|
|
2209
|
+
case 'room-skills': return cmdRoomSkills(subArgs);
|
|
1955
2210
|
|
|
1956
2211
|
// Moderation
|
|
1957
2212
|
case 'resolve': return cmdResolve();
|
|
2213
|
+
case 'resolve-request': return cmdResolveRequest();
|
|
2214
|
+
case 'resolve-vote': return cmdResolveVote(subArgs);
|
|
1958
2215
|
case 'appeal': return cmdAppeal(subArgs);
|
|
1959
2216
|
case 'report': return cmdReport(subArgs);
|
|
1960
2217
|
|
|
@@ -1970,16 +2227,19 @@ async function main() {
|
|
|
1970
2227
|
|
|
1971
2228
|
// Platform
|
|
1972
2229
|
case 'me': return cmdMe();
|
|
2230
|
+
case 'profile': return cmdProfile(subArgs);
|
|
1973
2231
|
case 'status': return cmdStatus(subArgs);
|
|
1974
2232
|
case 'settings': return cmdSettings(subArgs);
|
|
1975
2233
|
case 'security': return cmdSecurity();
|
|
1976
2234
|
case 'stats': return cmdStats();
|
|
1977
2235
|
case 'leaderboard': return cmdLeaderboard(subArgs);
|
|
1978
2236
|
case 'badges': return cmdBadges();
|
|
2237
|
+
case 'onboard': return cmdOnboard(subArgs);
|
|
1979
2238
|
|
|
1980
2239
|
// System
|
|
1981
2240
|
case 'skill': return cmdSkill();
|
|
1982
2241
|
case 'events': return cmdEvents(subArgs);
|
|
2242
|
+
case 'api': return cmdApi(subArgs);
|
|
1983
2243
|
case 'token':
|
|
1984
2244
|
if (subArgs[0] === 'rotate') return cmdTokenRotate();
|
|
1985
2245
|
if (subArgs[0] === 'status') {
|