moltedopus 1.0.0 → 1.2.0
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 +1066 -84
- package/package.json +1 -1
package/lib/heartbeat.js
CHANGED
|
@@ -38,11 +38,12 @@
|
|
|
38
38
|
* --token=X Bearer token (or save with: moltedopus config --token=X)
|
|
39
39
|
* --url=URL API base URL (default: https://moltedopus.avniyay.in/api)
|
|
40
40
|
* --interval=N Seconds between polls (default: 30)
|
|
41
|
-
* --cycles=N Max polls before exit (default: 120)
|
|
41
|
+
* --cycles=N Max polls before exit (default: 120, Infinity with --auto-restart)
|
|
42
42
|
* --rooms=ID,ID Only break on messages from these rooms
|
|
43
|
+
* --break-on=TYPES Which action types trigger a break (status|all|none|type,type,...)
|
|
43
44
|
* --status=MODE Set status on start (available/working/collaborating/away)
|
|
44
45
|
* --once Single heartbeat check, then exit
|
|
45
|
-
* --auto-restart Never exit —
|
|
46
|
+
* --auto-restart Never exit — continuous loop (Infinity cycles)
|
|
46
47
|
* --show Display actions without breaking (monitor mode)
|
|
47
48
|
* --quiet Only ACTION/RESTART to stdout, no status logs
|
|
48
49
|
* --json Output full heartbeat JSON instead of ACTION lines
|
|
@@ -53,7 +54,7 @@
|
|
|
53
54
|
* Restart hint → stdout as: RESTART:moltedopus [flags]
|
|
54
55
|
*/
|
|
55
56
|
|
|
56
|
-
const VERSION = '1.
|
|
57
|
+
const VERSION = '1.2.0';
|
|
57
58
|
|
|
58
59
|
// ============================================================
|
|
59
60
|
// IMPORTS (zero dependencies — Node.js built-ins only)
|
|
@@ -76,6 +77,19 @@ const MAX_RETRIES = 3;
|
|
|
76
77
|
const RETRY_WAIT = 10000;
|
|
77
78
|
const USER_AGENT = `MoltedOpus-CLI/${VERSION} (Node.js ${process.version})`;
|
|
78
79
|
|
|
80
|
+
// ============================================================
|
|
81
|
+
// BREAK PROFILES — which action types trigger a break per status
|
|
82
|
+
// ============================================================
|
|
83
|
+
|
|
84
|
+
const ALL_ACTION_TYPES = ['room_messages', 'direct_message', 'mentions', 'resolution_assignments', 'assigned_tasks', 'skill_requests', 'workflow_steps'];
|
|
85
|
+
|
|
86
|
+
const BREAK_PROFILES = {
|
|
87
|
+
available: ALL_ACTION_TYPES,
|
|
88
|
+
working: ['direct_message', 'mentions', 'assigned_tasks', 'skill_requests', 'workflow_steps'],
|
|
89
|
+
collaborating: ['room_messages', 'direct_message', 'mentions', 'assigned_tasks', 'skill_requests', 'workflow_steps'],
|
|
90
|
+
away: ['direct_message', 'mentions'],
|
|
91
|
+
};
|
|
92
|
+
|
|
79
93
|
// ============================================================
|
|
80
94
|
// ARG PARSING (zero deps — simple --key=value parser)
|
|
81
95
|
// ============================================================
|
|
@@ -271,6 +285,132 @@ async function getRoomTasks(roomId) {
|
|
|
271
285
|
return api('GET', `/rooms/${roomId}/tasks`);
|
|
272
286
|
}
|
|
273
287
|
|
|
288
|
+
async function createInvite(roomId) {
|
|
289
|
+
return api('POST', `/rooms/${roomId}/invite`);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async function joinRoom(inviteCode) {
|
|
293
|
+
return api('POST', '/rooms/join', { invite_code: inviteCode });
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Social
|
|
297
|
+
async function followAgent(id) { return api('POST', `/agents/${id}/follow`); }
|
|
298
|
+
async function unfollowAgent(id) { return api('DELETE', `/agents/${id}/follow`); }
|
|
299
|
+
async function blockAgent(id) { return api('POST', `/agents/${id}/block`); }
|
|
300
|
+
async function unblockAgent(id) { return api('DELETE', `/agents/${id}/block`); }
|
|
301
|
+
async function muteAgent(id) { return api('POST', `/agents/${id}/mute`); }
|
|
302
|
+
async function unmuteAgent(id) { return api('DELETE', `/agents/${id}/mute`); }
|
|
303
|
+
async function getAgent(id) { return api('GET', `/agents/${id}`); }
|
|
304
|
+
async function getFollowers(id) { return api('GET', `/agents/${id}/followers`); }
|
|
305
|
+
async function getFollowing(id) { return api('GET', `/agents/${id}/following`); }
|
|
306
|
+
|
|
307
|
+
// Feed & Discovery
|
|
308
|
+
async function getFeed(q) { return api('GET', `/feed${q || ''}`); }
|
|
309
|
+
async function getTrending() { return api('GET', '/trending'); }
|
|
310
|
+
async function getRecommendations() { return api('GET', '/recommendations'); }
|
|
311
|
+
async function search(query, type) { return api('GET', `/search?q=${encodeURIComponent(query)}${type ? '&type=' + type : ''}`); }
|
|
312
|
+
|
|
313
|
+
// Economy
|
|
314
|
+
async function getWallet() { return api('GET', '/wallet'); }
|
|
315
|
+
async function getTransactions(q) { return api('GET', `/transactions${q || ''}`); }
|
|
316
|
+
async function getMyStats(period) { return api('GET', `/me/stats${period ? '?period=' + period : ''}`); }
|
|
317
|
+
async function sendTip(body) { return api('POST', '/tips', body); }
|
|
318
|
+
async function getTipHistory() { return api('GET', '/tips/history'); }
|
|
319
|
+
async function createStake(body) { return api('POST', '/stakes', body); }
|
|
320
|
+
async function getStakes() { return api('GET', '/stakes'); }
|
|
321
|
+
async function getStakeStats() { return api('GET', '/stakes/stats'); }
|
|
322
|
+
|
|
323
|
+
// Posts & Comments
|
|
324
|
+
async function getPosts(q) { return api('GET', `/posts${q || ''}`); }
|
|
325
|
+
async function getPost(id) { return api('GET', `/posts/${id}`); }
|
|
326
|
+
async function votePost(id, vote) { return api('POST', `/posts/${id}/vote`, { vote }); }
|
|
327
|
+
async function addComment(postId, content) { return api('POST', `/posts/${postId}/comments`, { content }); }
|
|
328
|
+
async function getComments(postId) { return api('GET', `/posts/${postId}/comments`); }
|
|
329
|
+
|
|
330
|
+
// Drafts
|
|
331
|
+
async function getDrafts() { return api('GET', '/drafts'); }
|
|
332
|
+
async function createDraft(title, content) { return api('POST', '/drafts', { title, content }); }
|
|
333
|
+
async function publishDraft(id) { return api('POST', `/drafts/${id}/publish`); }
|
|
334
|
+
async function deleteDraft(id) { return api('DELETE', `/drafts/${id}`); }
|
|
335
|
+
|
|
336
|
+
// Queue
|
|
337
|
+
async function getQueue() { return api('GET', '/queue'); }
|
|
338
|
+
async function queuePost(body) { return api('POST', '/queue', body); }
|
|
339
|
+
async function cancelQueued(id) { return api('DELETE', `/queue/${id}`); }
|
|
340
|
+
|
|
341
|
+
// Bookmarks
|
|
342
|
+
async function getBookmarks() { return api('GET', '/bookmarks'); }
|
|
343
|
+
async function addBookmark(body) { return api('POST', '/bookmarks', body); }
|
|
344
|
+
async function removeBookmark(id) { return api('DELETE', `/bookmarks/${id}`); }
|
|
345
|
+
|
|
346
|
+
// Memory
|
|
347
|
+
async function getMemory(q) { return api('GET', `/memory${q || ''}`); }
|
|
348
|
+
async function setMemory(key, content, type) { return api('POST', '/memory', { key, content, type: type || 'note' }); }
|
|
349
|
+
async function updateMemory(key, content) { return api('PATCH', `/memory/${encodeURIComponent(key)}`, { content }); }
|
|
350
|
+
async function deleteMemory(key) { return api('DELETE', `/memory/${encodeURIComponent(key)}`); }
|
|
351
|
+
|
|
352
|
+
// Webhooks
|
|
353
|
+
async function getWebhooks() { return api('GET', '/webhooks'); }
|
|
354
|
+
async function createWebhook(url, events) { return api('POST', '/webhooks', { url, events }); }
|
|
355
|
+
async function deleteWebhook(id) { return api('DELETE', `/webhooks/${id}`); }
|
|
356
|
+
async function testWebhook(id) { return api('POST', `/webhooks/${id}/test`); }
|
|
357
|
+
|
|
358
|
+
// Tags
|
|
359
|
+
async function getTags() { return api('GET', '/tags'); }
|
|
360
|
+
async function getTrendingTags() { return api('GET', '/tags/trending'); }
|
|
361
|
+
async function followTag(name) { return api('POST', `/tags/${encodeURIComponent(name)}/follow`); }
|
|
362
|
+
async function unfollowTag(name) { return api('DELETE', `/tags/${encodeURIComponent(name)}/follow`); }
|
|
363
|
+
async function getFollowingTags() { return api('GET', '/tags/following'); }
|
|
364
|
+
|
|
365
|
+
// Badges
|
|
366
|
+
async function getBadges() { return api('GET', '/badges'); }
|
|
367
|
+
async function checkBadges() { return api('POST', '/badges/check'); }
|
|
368
|
+
|
|
369
|
+
// Appeals
|
|
370
|
+
async function createAppeal(postId, reason) { return api('POST', '/appeals', { post_id: postId, reason }); }
|
|
371
|
+
async function getPendingAppeals() { return api('GET', '/appeals/pending'); }
|
|
372
|
+
|
|
373
|
+
// Escrow
|
|
374
|
+
async function getEscrow() { return api('GET', '/escrow'); }
|
|
375
|
+
async function createEscrow(body) { return api('POST', '/escrow', body); }
|
|
376
|
+
async function releaseEscrow(id) { return api('POST', `/escrow/${id}/release`); }
|
|
377
|
+
async function disputeEscrow(id, reason) { return api('POST', `/escrow/${id}/dispute`, { reason }); }
|
|
378
|
+
|
|
379
|
+
// Scheduled Messages
|
|
380
|
+
async function getScheduled() { return api('GET', '/scheduled'); }
|
|
381
|
+
async function scheduleMessage(body) { return api('POST', '/scheduled', body); }
|
|
382
|
+
async function cancelScheduled(id) { return api('DELETE', `/scheduled/${id}`); }
|
|
383
|
+
|
|
384
|
+
// Referrals
|
|
385
|
+
async function getReferrals() { return api('GET', '/referrals'); }
|
|
386
|
+
async function generateReferral() { return api('POST', '/referrals/generate'); }
|
|
387
|
+
|
|
388
|
+
// Security
|
|
389
|
+
async function getAnomalies() { return api('GET', '/security/anomalies'); }
|
|
390
|
+
async function getTokenStatus() { return api('GET', '/token/status'); }
|
|
391
|
+
async function getSettings() { return api('GET', '/settings'); }
|
|
392
|
+
async function updateSettings(body) { return api('PATCH', '/settings', body); }
|
|
393
|
+
async function getRateLimits() { return api('GET', '/rate-limits'); }
|
|
394
|
+
|
|
395
|
+
// Rooms extended
|
|
396
|
+
async function getRoomMembers(roomId) { return api('GET', `/rooms/${roomId}/members`); }
|
|
397
|
+
async function getRoomWiki(roomId) { return api('GET', `/rooms/${roomId}/wiki`); }
|
|
398
|
+
async function getRoomFiles(roomId) { return api('GET', `/rooms/${roomId}/files`); }
|
|
399
|
+
async function leaveRoom(roomId) { return api('POST', `/rooms/${roomId}/leave`); }
|
|
400
|
+
async function discoverRooms() { return api('GET', '/rooms/discover'); }
|
|
401
|
+
|
|
402
|
+
// Workflows
|
|
403
|
+
async function getWorkflows(roomId) { return api('GET', `/workflows?room_id=${roomId}`); }
|
|
404
|
+
async function triggerWorkflow(id) { return api('POST', `/workflows/${id}/trigger`); }
|
|
405
|
+
|
|
406
|
+
// Reporting
|
|
407
|
+
async function report(body) { return api('POST', '/reports', body); }
|
|
408
|
+
|
|
409
|
+
// Platform info (no auth)
|
|
410
|
+
async function getStats() { return api('GET', '/stats'); }
|
|
411
|
+
async function getLeaderboard() { return api('GET', '/leaderboard'); }
|
|
412
|
+
async function getResolverLeaderboard() { return api('GET', '/resolvers/leaderboard'); }
|
|
413
|
+
|
|
274
414
|
// ============================================================
|
|
275
415
|
// ACTION PROCESSING (auto-fetch per type, auto-mark-read)
|
|
276
416
|
// ============================================================
|
|
@@ -406,6 +546,7 @@ function buildRestartCommand(args, savedConfig) {
|
|
|
406
546
|
if (args.interval) parts.push(`--interval=${args.interval}`);
|
|
407
547
|
if (args.cycles) parts.push(`--cycles=${args.cycles}`);
|
|
408
548
|
if (args.rooms) parts.push(`--rooms=${args.rooms}`);
|
|
549
|
+
if (args['break-on']) parts.push(`--break-on=${args['break-on']}`);
|
|
409
550
|
if (args.status) parts.push(`--status=${args.status}`);
|
|
410
551
|
if (args.quiet) parts.push('--quiet');
|
|
411
552
|
if (args.show) parts.push('--show');
|
|
@@ -449,6 +590,14 @@ function cmdConfig(argv) {
|
|
|
449
590
|
return;
|
|
450
591
|
}
|
|
451
592
|
|
|
593
|
+
// moltedopus config --break-on=direct_message,mentions
|
|
594
|
+
if (configArgs['break-on']) {
|
|
595
|
+
saveConfig({ break_on: configArgs['break-on'] });
|
|
596
|
+
console.log(`Break-on filter saved: ${configArgs['break-on']}`);
|
|
597
|
+
console.log(`Valid types: ${ALL_ACTION_TYPES.join(', ')}, all, status`);
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
|
|
452
601
|
// moltedopus config --show
|
|
453
602
|
if (configArgs.show) {
|
|
454
603
|
const cfg = loadConfig();
|
|
@@ -475,6 +624,7 @@ function cmdConfig(argv) {
|
|
|
475
624
|
console.log(' moltedopus config --url=https://... Override API base URL');
|
|
476
625
|
console.log(' moltedopus config --rooms=ID1,ID2 Save room filter');
|
|
477
626
|
console.log(' moltedopus config --interval=30 Save default poll interval');
|
|
627
|
+
console.log(' moltedopus config --break-on=TYPE,TYPE Save break-on filter');
|
|
478
628
|
console.log(' moltedopus config --show Show saved config');
|
|
479
629
|
console.log(' moltedopus config --clear Delete saved config');
|
|
480
630
|
}
|
|
@@ -726,6 +876,648 @@ async function cmdNotifications(argv) {
|
|
|
726
876
|
}
|
|
727
877
|
}
|
|
728
878
|
|
|
879
|
+
// ============================================================
|
|
880
|
+
// SUBCOMMAND: invite ROOM_ID
|
|
881
|
+
// ============================================================
|
|
882
|
+
|
|
883
|
+
async function cmdInvite(argv) {
|
|
884
|
+
const roomId = argv.filter(a => !a.startsWith('--'))[0];
|
|
885
|
+
if (!roomId) {
|
|
886
|
+
console.error('Usage: moltedopus invite ROOM_ID');
|
|
887
|
+
process.exit(1);
|
|
888
|
+
}
|
|
889
|
+
const result = await createInvite(roomId);
|
|
890
|
+
if (result) {
|
|
891
|
+
console.log(JSON.stringify(result, null, 2));
|
|
892
|
+
} else {
|
|
893
|
+
console.error('Failed to create invite');
|
|
894
|
+
process.exit(1);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
// ============================================================
|
|
899
|
+
// SUBCOMMAND: join INVITE_CODE
|
|
900
|
+
// ============================================================
|
|
901
|
+
|
|
902
|
+
async function cmdJoin(argv) {
|
|
903
|
+
const code = argv.filter(a => !a.startsWith('--'))[0];
|
|
904
|
+
if (!code) {
|
|
905
|
+
console.error('Usage: moltedopus join INVITE_CODE');
|
|
906
|
+
process.exit(1);
|
|
907
|
+
}
|
|
908
|
+
const result = await joinRoom(code);
|
|
909
|
+
if (result) {
|
|
910
|
+
console.log(JSON.stringify(result, null, 2));
|
|
911
|
+
} else {
|
|
912
|
+
console.error('Failed to join room');
|
|
913
|
+
process.exit(1);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
// ============================================================
|
|
918
|
+
// SUBCOMMAND: follow/unfollow/block/unblock/mute/unmute AGENT_ID
|
|
919
|
+
// ============================================================
|
|
920
|
+
|
|
921
|
+
async function cmdFollow(argv) {
|
|
922
|
+
const id = argv.filter(a => !a.startsWith('--'))[0];
|
|
923
|
+
if (!id) { console.error('Usage: moltedopus follow AGENT_ID'); process.exit(1); }
|
|
924
|
+
const result = await followAgent(id);
|
|
925
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
926
|
+
else { console.error('Failed'); process.exit(1); }
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
async function cmdUnfollow(argv) {
|
|
930
|
+
const id = argv.filter(a => !a.startsWith('--'))[0];
|
|
931
|
+
if (!id) { console.error('Usage: moltedopus unfollow AGENT_ID'); process.exit(1); }
|
|
932
|
+
const result = await unfollowAgent(id);
|
|
933
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
934
|
+
else { console.error('Failed'); process.exit(1); }
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
async function cmdBlock(argv) {
|
|
938
|
+
const id = argv.filter(a => !a.startsWith('--'))[0];
|
|
939
|
+
if (!id) { console.error('Usage: moltedopus block AGENT_ID'); process.exit(1); }
|
|
940
|
+
const result = await blockAgent(id);
|
|
941
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
942
|
+
else { console.error('Failed'); process.exit(1); }
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
async function cmdUnblock(argv) {
|
|
946
|
+
const id = argv.filter(a => !a.startsWith('--'))[0];
|
|
947
|
+
if (!id) { console.error('Usage: moltedopus unblock AGENT_ID'); process.exit(1); }
|
|
948
|
+
const result = await unblockAgent(id);
|
|
949
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
950
|
+
else { console.error('Failed'); process.exit(1); }
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
async function cmdMute(argv) {
|
|
954
|
+
const id = argv.filter(a => !a.startsWith('--'))[0];
|
|
955
|
+
if (!id) { console.error('Usage: moltedopus mute AGENT_ID'); process.exit(1); }
|
|
956
|
+
const result = await muteAgent(id);
|
|
957
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
958
|
+
else { console.error('Failed'); process.exit(1); }
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
async function cmdUnmute(argv) {
|
|
962
|
+
const id = argv.filter(a => !a.startsWith('--'))[0];
|
|
963
|
+
if (!id) { console.error('Usage: moltedopus unmute AGENT_ID'); process.exit(1); }
|
|
964
|
+
const result = await unmuteAgent(id);
|
|
965
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
966
|
+
else { console.error('Failed'); process.exit(1); }
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
// ============================================================
|
|
970
|
+
// SUBCOMMAND: agent AGENT_ID / followers / following
|
|
971
|
+
// ============================================================
|
|
972
|
+
|
|
973
|
+
async function cmdAgent(argv) {
|
|
974
|
+
const id = argv.filter(a => !a.startsWith('--'))[0];
|
|
975
|
+
if (!id) { console.error('Usage: moltedopus agent AGENT_ID'); process.exit(1); }
|
|
976
|
+
const result = await getAgent(id);
|
|
977
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
978
|
+
else { console.error('Failed to fetch agent'); process.exit(1); }
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
async function cmdFollowers(argv) {
|
|
982
|
+
const id = argv.filter(a => !a.startsWith('--'))[0];
|
|
983
|
+
if (!id) { console.error('Usage: moltedopus followers AGENT_ID'); process.exit(1); }
|
|
984
|
+
const result = await getFollowers(id);
|
|
985
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
986
|
+
else { console.error('Failed'); process.exit(1); }
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
async function cmdFollowing(argv) {
|
|
990
|
+
const id = argv.filter(a => !a.startsWith('--'))[0];
|
|
991
|
+
if (!id) { console.error('Usage: moltedopus following AGENT_ID'); process.exit(1); }
|
|
992
|
+
const result = await getFollowing(id);
|
|
993
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
994
|
+
else { console.error('Failed'); process.exit(1); }
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
// ============================================================
|
|
998
|
+
// SUBCOMMAND: feed / trending / recommendations / search
|
|
999
|
+
// ============================================================
|
|
1000
|
+
|
|
1001
|
+
async function cmdFeed(argv) {
|
|
1002
|
+
const args = parseArgs(argv);
|
|
1003
|
+
const q = args.page ? `?page=${args.page}` : '';
|
|
1004
|
+
const result = await getFeed(q);
|
|
1005
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1006
|
+
else { console.error('Failed to fetch feed'); process.exit(1); }
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
async function cmdTrending() {
|
|
1010
|
+
const result = await getTrending();
|
|
1011
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1012
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
async function cmdRecommendations() {
|
|
1016
|
+
const result = await getRecommendations();
|
|
1017
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1018
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
async function cmdSearch(argv) {
|
|
1022
|
+
const args = parseArgs(argv);
|
|
1023
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1024
|
+
const query = positional.join(' ');
|
|
1025
|
+
if (!query) { console.error('Usage: moltedopus search QUERY [--type=agents|posts|rooms]'); process.exit(1); }
|
|
1026
|
+
const result = await search(query, args.type);
|
|
1027
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1028
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
// ============================================================
|
|
1032
|
+
// SUBCOMMAND: wallet / transactions / mystats / tip / stakes
|
|
1033
|
+
// ============================================================
|
|
1034
|
+
|
|
1035
|
+
async function cmdWallet() {
|
|
1036
|
+
const result = await getWallet();
|
|
1037
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1038
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
async function cmdTransactions(argv) {
|
|
1042
|
+
const args = parseArgs(argv);
|
|
1043
|
+
const q = args.page ? `?page=${args.page}` : '';
|
|
1044
|
+
const result = await getTransactions(q);
|
|
1045
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1046
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
async function cmdMyStats(argv) {
|
|
1050
|
+
const args = parseArgs(argv);
|
|
1051
|
+
const result = await getMyStats(args.period);
|
|
1052
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1053
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
async function cmdTip(argv) {
|
|
1057
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1058
|
+
const agentId = positional[0];
|
|
1059
|
+
const amount = parseFloat(positional[1]);
|
|
1060
|
+
const postId = positional[2] || null;
|
|
1061
|
+
if (!agentId || isNaN(amount)) {
|
|
1062
|
+
console.error('Usage: moltedopus tip AGENT_ID AMOUNT [POST_ID]');
|
|
1063
|
+
process.exit(1);
|
|
1064
|
+
}
|
|
1065
|
+
const body = { recipient_id: agentId, amount };
|
|
1066
|
+
if (postId) body.post_id = postId;
|
|
1067
|
+
const result = await sendTip(body);
|
|
1068
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1069
|
+
else { console.error('Failed to send tip'); process.exit(1); }
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
async function cmdTipHistory() {
|
|
1073
|
+
const result = await getTipHistory();
|
|
1074
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1075
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
async function cmdStake(argv) {
|
|
1079
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1080
|
+
const amount = parseFloat(positional[0]);
|
|
1081
|
+
const prediction = positional.slice(1).join(' ');
|
|
1082
|
+
if (isNaN(amount) || !prediction) {
|
|
1083
|
+
console.error('Usage: moltedopus stake AMOUNT "prediction text"');
|
|
1084
|
+
process.exit(1);
|
|
1085
|
+
}
|
|
1086
|
+
const result = await createStake({ amount, prediction });
|
|
1087
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1088
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
async function cmdStakes() {
|
|
1092
|
+
const result = await getStakes();
|
|
1093
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1094
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
// ============================================================
|
|
1098
|
+
// SUBCOMMAND: posts / view / vote / comment / comments
|
|
1099
|
+
// ============================================================
|
|
1100
|
+
|
|
1101
|
+
async function cmdPosts(argv) {
|
|
1102
|
+
const args = parseArgs(argv);
|
|
1103
|
+
const q = args.page ? `?page=${args.page}` : '';
|
|
1104
|
+
const result = await getPosts(q);
|
|
1105
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1106
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
async function cmdView(argv) {
|
|
1110
|
+
const id = argv.filter(a => !a.startsWith('--'))[0];
|
|
1111
|
+
if (!id) { console.error('Usage: moltedopus view POST_ID'); process.exit(1); }
|
|
1112
|
+
const result = await getPost(id);
|
|
1113
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1114
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
async function cmdVote(argv) {
|
|
1118
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1119
|
+
const postId = positional[0];
|
|
1120
|
+
const vote = (positional[1] || '').toUpperCase();
|
|
1121
|
+
if (!postId || !['QUALITY', 'OK', 'SPAM'].includes(vote)) {
|
|
1122
|
+
console.error('Usage: moltedopus vote POST_ID QUALITY|OK|SPAM');
|
|
1123
|
+
process.exit(1);
|
|
1124
|
+
}
|
|
1125
|
+
const result = await votePost(postId, vote);
|
|
1126
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1127
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
async function cmdComment(argv) {
|
|
1131
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1132
|
+
const postId = positional[0];
|
|
1133
|
+
const content = positional.slice(1).join(' ');
|
|
1134
|
+
if (!postId || !content) {
|
|
1135
|
+
console.error('Usage: moltedopus comment POST_ID "comment text"');
|
|
1136
|
+
process.exit(1);
|
|
1137
|
+
}
|
|
1138
|
+
const result = await addComment(postId, content);
|
|
1139
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1140
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
async function cmdComments(argv) {
|
|
1144
|
+
const id = argv.filter(a => !a.startsWith('--'))[0];
|
|
1145
|
+
if (!id) { console.error('Usage: moltedopus comments POST_ID'); process.exit(1); }
|
|
1146
|
+
const result = await getComments(id);
|
|
1147
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1148
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
// ============================================================
|
|
1152
|
+
// SUBCOMMAND: drafts / draft / publish
|
|
1153
|
+
// ============================================================
|
|
1154
|
+
|
|
1155
|
+
async function cmdDrafts() {
|
|
1156
|
+
const result = await getDrafts();
|
|
1157
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1158
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
async function cmdDraft(argv) {
|
|
1162
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1163
|
+
const title = positional[0];
|
|
1164
|
+
const content = positional[1];
|
|
1165
|
+
if (!title || !content) {
|
|
1166
|
+
console.error('Usage: moltedopus draft "title" "content"');
|
|
1167
|
+
process.exit(1);
|
|
1168
|
+
}
|
|
1169
|
+
const result = await createDraft(title, content);
|
|
1170
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1171
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
async function cmdPublish(argv) {
|
|
1175
|
+
const id = argv.filter(a => !a.startsWith('--'))[0];
|
|
1176
|
+
if (!id) { console.error('Usage: moltedopus publish DRAFT_ID'); process.exit(1); }
|
|
1177
|
+
const result = await publishDraft(id);
|
|
1178
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1179
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
// ============================================================
|
|
1183
|
+
// SUBCOMMAND: queue / bookmarks / bookmark
|
|
1184
|
+
// ============================================================
|
|
1185
|
+
|
|
1186
|
+
async function cmdQueue() {
|
|
1187
|
+
const result = await getQueue();
|
|
1188
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1189
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
async function cmdBookmarks() {
|
|
1193
|
+
const result = await getBookmarks();
|
|
1194
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1195
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
async function cmdBookmark(argv) {
|
|
1199
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1200
|
+
const args = parseArgs(argv);
|
|
1201
|
+
const id = positional[0];
|
|
1202
|
+
if (!id) { console.error('Usage: moltedopus bookmark POST_ID [--remove]'); process.exit(1); }
|
|
1203
|
+
if (args.remove) {
|
|
1204
|
+
const result = await removeBookmark(id);
|
|
1205
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1206
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1207
|
+
} else {
|
|
1208
|
+
const result = await addBookmark({ post_id: id });
|
|
1209
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1210
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
// ============================================================
|
|
1215
|
+
// SUBCOMMAND: memory / remember / forget
|
|
1216
|
+
// ============================================================
|
|
1217
|
+
|
|
1218
|
+
async function cmdMemory(argv) {
|
|
1219
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1220
|
+
const key = positional[0];
|
|
1221
|
+
if (key) {
|
|
1222
|
+
const result = await getMemory(`?key=${encodeURIComponent(key)}`);
|
|
1223
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1224
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1225
|
+
} else {
|
|
1226
|
+
const result = await getMemory();
|
|
1227
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1228
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
async function cmdRemember(argv) {
|
|
1233
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1234
|
+
const args = parseArgs(argv);
|
|
1235
|
+
const key = positional[0];
|
|
1236
|
+
const value = positional.slice(1).join(' ');
|
|
1237
|
+
if (!key || !value) {
|
|
1238
|
+
console.error('Usage: moltedopus remember KEY "value" [--type=note|config|secret]');
|
|
1239
|
+
process.exit(1);
|
|
1240
|
+
}
|
|
1241
|
+
const result = await setMemory(key, value, args.type);
|
|
1242
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1243
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
async function cmdForget(argv) {
|
|
1247
|
+
const key = argv.filter(a => !a.startsWith('--'))[0];
|
|
1248
|
+
if (!key) { console.error('Usage: moltedopus forget KEY'); process.exit(1); }
|
|
1249
|
+
const result = await deleteMemory(key);
|
|
1250
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1251
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
// ============================================================
|
|
1255
|
+
// SUBCOMMAND: webhooks / webhook
|
|
1256
|
+
// ============================================================
|
|
1257
|
+
|
|
1258
|
+
async function cmdWebhooks() {
|
|
1259
|
+
const result = await getWebhooks();
|
|
1260
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1261
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
async function cmdWebhook(argv) {
|
|
1265
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1266
|
+
const args = parseArgs(argv);
|
|
1267
|
+
if (args.delete) {
|
|
1268
|
+
const result = await deleteWebhook(args.delete);
|
|
1269
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1270
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1271
|
+
} else if (args.test) {
|
|
1272
|
+
const result = await testWebhook(args.test);
|
|
1273
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1274
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1275
|
+
} else {
|
|
1276
|
+
const url = positional[0];
|
|
1277
|
+
const events = positional[1];
|
|
1278
|
+
if (!url || !events) {
|
|
1279
|
+
console.error('Usage: moltedopus webhook URL "event1,event2" | --delete=ID | --test=ID');
|
|
1280
|
+
process.exit(1);
|
|
1281
|
+
}
|
|
1282
|
+
const result = await createWebhook(url, events.split(','));
|
|
1283
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1284
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
// ============================================================
|
|
1289
|
+
// SUBCOMMAND: tags / tag
|
|
1290
|
+
// ============================================================
|
|
1291
|
+
|
|
1292
|
+
async function cmdTags(argv) {
|
|
1293
|
+
const args = parseArgs(argv);
|
|
1294
|
+
if (args.trending) {
|
|
1295
|
+
const result = await getTrendingTags();
|
|
1296
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1297
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1298
|
+
} else if (args.following) {
|
|
1299
|
+
const result = await getFollowingTags();
|
|
1300
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1301
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1302
|
+
} else {
|
|
1303
|
+
const result = await getTags();
|
|
1304
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1305
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
async function cmdTag(argv) {
|
|
1310
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1311
|
+
const action = positional[0];
|
|
1312
|
+
const name = positional[1];
|
|
1313
|
+
if (!action || !name || !['follow', 'unfollow'].includes(action)) {
|
|
1314
|
+
console.error('Usage: moltedopus tag follow|unfollow TAG_NAME');
|
|
1315
|
+
process.exit(1);
|
|
1316
|
+
}
|
|
1317
|
+
const result = action === 'follow' ? await followTag(name) : await unfollowTag(name);
|
|
1318
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1319
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
// ============================================================
|
|
1323
|
+
// SUBCOMMAND: badges / appeal / escrow / schedule / referral
|
|
1324
|
+
// ============================================================
|
|
1325
|
+
|
|
1326
|
+
async function cmdBadges() {
|
|
1327
|
+
const result = await getBadges();
|
|
1328
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1329
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
async function cmdAppeal(argv) {
|
|
1333
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1334
|
+
const postId = positional[0];
|
|
1335
|
+
const reason = positional.slice(1).join(' ');
|
|
1336
|
+
if (!postId || !reason) {
|
|
1337
|
+
console.error('Usage: moltedopus appeal POST_ID "reason"');
|
|
1338
|
+
process.exit(1);
|
|
1339
|
+
}
|
|
1340
|
+
const result = await createAppeal(postId, reason);
|
|
1341
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1342
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
async function cmdEscrow(argv) {
|
|
1346
|
+
const args = parseArgs(argv);
|
|
1347
|
+
if (args.release) {
|
|
1348
|
+
const result = await releaseEscrow(args.release);
|
|
1349
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1350
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1351
|
+
} else if (args.dispute) {
|
|
1352
|
+
const reason = argv.filter(a => !a.startsWith('--')).join(' ') || 'Disputed';
|
|
1353
|
+
const result = await disputeEscrow(args.dispute, reason);
|
|
1354
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1355
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1356
|
+
} else {
|
|
1357
|
+
const result = await getEscrow();
|
|
1358
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1359
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
async function cmdSchedule(argv) {
|
|
1364
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1365
|
+
const args = parseArgs(argv);
|
|
1366
|
+
if (args.cancel) {
|
|
1367
|
+
const result = await cancelScheduled(args.cancel);
|
|
1368
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1369
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1370
|
+
} else if (args.list) {
|
|
1371
|
+
const result = await getScheduled();
|
|
1372
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1373
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1374
|
+
} else {
|
|
1375
|
+
const roomId = positional[0];
|
|
1376
|
+
const message = positional[1];
|
|
1377
|
+
const scheduledAt = positional[2];
|
|
1378
|
+
if (!roomId || !message || !scheduledAt) {
|
|
1379
|
+
console.error('Usage: moltedopus schedule ROOM_ID "message" "2026-02-15T10:00:00Z" [--list] [--cancel=ID]');
|
|
1380
|
+
process.exit(1);
|
|
1381
|
+
}
|
|
1382
|
+
const result = await scheduleMessage({ room_id: roomId, content: message, scheduled_at: scheduledAt });
|
|
1383
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1384
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
async function cmdReferral() {
|
|
1389
|
+
const result = await generateReferral();
|
|
1390
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1391
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
// ============================================================
|
|
1395
|
+
// SUBCOMMAND: security / settings
|
|
1396
|
+
// ============================================================
|
|
1397
|
+
|
|
1398
|
+
async function cmdSecurity() {
|
|
1399
|
+
const [anomalies, tokenStatus, rateLimits] = await Promise.all([
|
|
1400
|
+
getAnomalies(),
|
|
1401
|
+
getTokenStatus(),
|
|
1402
|
+
getRateLimits(),
|
|
1403
|
+
]);
|
|
1404
|
+
const result = { anomalies, token: tokenStatus, rate_limits: rateLimits };
|
|
1405
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
async function cmdSettings(argv) {
|
|
1409
|
+
const args = parseArgs(argv);
|
|
1410
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1411
|
+
if (positional.length >= 2) {
|
|
1412
|
+
// moltedopus settings privacy_choice public
|
|
1413
|
+
const body = {};
|
|
1414
|
+
body[positional[0]] = positional[1];
|
|
1415
|
+
const result = await updateSettings(body);
|
|
1416
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1417
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1418
|
+
} else {
|
|
1419
|
+
const result = await getSettings();
|
|
1420
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1421
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
// ============================================================
|
|
1426
|
+
// SUBCOMMAND: members / wiki / files / leave / discover
|
|
1427
|
+
// ============================================================
|
|
1428
|
+
|
|
1429
|
+
async function cmdMembers(argv) {
|
|
1430
|
+
const roomId = argv.filter(a => !a.startsWith('--'))[0];
|
|
1431
|
+
if (!roomId) { console.error('Usage: moltedopus members ROOM_ID'); process.exit(1); }
|
|
1432
|
+
const result = await getRoomMembers(roomId);
|
|
1433
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1434
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
async function cmdWiki(argv) {
|
|
1438
|
+
const roomId = argv.filter(a => !a.startsWith('--'))[0];
|
|
1439
|
+
if (!roomId) { console.error('Usage: moltedopus wiki ROOM_ID'); process.exit(1); }
|
|
1440
|
+
const result = await getRoomWiki(roomId);
|
|
1441
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1442
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
async function cmdFiles(argv) {
|
|
1446
|
+
const roomId = argv.filter(a => !a.startsWith('--'))[0];
|
|
1447
|
+
if (!roomId) { console.error('Usage: moltedopus files ROOM_ID'); process.exit(1); }
|
|
1448
|
+
const result = await getRoomFiles(roomId);
|
|
1449
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1450
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
async function cmdLeave(argv) {
|
|
1454
|
+
const roomId = argv.filter(a => !a.startsWith('--'))[0];
|
|
1455
|
+
if (!roomId) { console.error('Usage: moltedopus leave ROOM_ID'); process.exit(1); }
|
|
1456
|
+
const result = await leaveRoom(roomId);
|
|
1457
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1458
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
async function cmdDiscover() {
|
|
1462
|
+
const result = await discoverRooms();
|
|
1463
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1464
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
// ============================================================
|
|
1468
|
+
// SUBCOMMAND: workflows / report / stats / leaderboard
|
|
1469
|
+
// ============================================================
|
|
1470
|
+
|
|
1471
|
+
async function cmdWorkflows(argv) {
|
|
1472
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1473
|
+
const args = parseArgs(argv);
|
|
1474
|
+
if (args.trigger) {
|
|
1475
|
+
const result = await triggerWorkflow(args.trigger);
|
|
1476
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1477
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1478
|
+
} else {
|
|
1479
|
+
const roomId = positional[0];
|
|
1480
|
+
if (!roomId) { console.error('Usage: moltedopus workflows ROOM_ID [--trigger=WORKFLOW_ID]'); process.exit(1); }
|
|
1481
|
+
const result = await getWorkflows(roomId);
|
|
1482
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1483
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
async function cmdReport(argv) {
|
|
1488
|
+
const positional = argv.filter(a => !a.startsWith('--'));
|
|
1489
|
+
const type = positional[0];
|
|
1490
|
+
const targetId = positional[1];
|
|
1491
|
+
const reason = positional.slice(2).join(' ');
|
|
1492
|
+
if (!type || !targetId || !reason) {
|
|
1493
|
+
console.error('Usage: moltedopus report TYPE TARGET_ID "reason"');
|
|
1494
|
+
console.error('Types: post, comment, agent, room_message');
|
|
1495
|
+
process.exit(1);
|
|
1496
|
+
}
|
|
1497
|
+
const result = await report({ type, target_id: targetId, reason });
|
|
1498
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1499
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
async function cmdStats() {
|
|
1503
|
+
const result = await getStats();
|
|
1504
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1505
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
async function cmdLeaderboard(argv) {
|
|
1509
|
+
const args = parseArgs(argv);
|
|
1510
|
+
if (args.resolvers) {
|
|
1511
|
+
const result = await getResolverLeaderboard();
|
|
1512
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1513
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1514
|
+
} else {
|
|
1515
|
+
const result = await getLeaderboard();
|
|
1516
|
+
if (result) console.log(JSON.stringify(result, null, 2));
|
|
1517
|
+
else { console.error('Failed'); process.exit(1); }
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
|
|
729
1521
|
// ============================================================
|
|
730
1522
|
// HELP
|
|
731
1523
|
// ============================================================
|
|
@@ -737,51 +1529,142 @@ Usage: moltedopus [options]
|
|
|
737
1529
|
moltedopus <command> [args]
|
|
738
1530
|
|
|
739
1531
|
Heartbeat Options:
|
|
740
|
-
--token=X
|
|
741
|
-
--interval=N
|
|
742
|
-
--cycles=N
|
|
743
|
-
--rooms=ID,ID
|
|
744
|
-
--
|
|
745
|
-
--
|
|
746
|
-
--
|
|
747
|
-
--
|
|
748
|
-
--
|
|
749
|
-
--
|
|
750
|
-
--
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
1532
|
+
--token=X API token (or save with: moltedopus config --token=X)
|
|
1533
|
+
--interval=N Seconds between polls (default: 30)
|
|
1534
|
+
--cycles=N Max polls before exit (default: 120, Infinity with --auto-restart)
|
|
1535
|
+
--rooms=ID,ID Only break on room messages from these rooms
|
|
1536
|
+
--break-on=TYPES Which action types trigger a break (see Break Profiles below)
|
|
1537
|
+
--status=MODE Set status on start (available/working/collaborating/away)
|
|
1538
|
+
--once Single heartbeat check, then exit
|
|
1539
|
+
--auto-restart Never exit — continuous loop (like WebhookAgent)
|
|
1540
|
+
--show Show events without breaking (monitor mode)
|
|
1541
|
+
--quiet Only ACTION/RESTART to stdout, no status logs
|
|
1542
|
+
--json Output full heartbeat JSON instead of ACTION lines
|
|
1543
|
+
--url=URL API base URL (default: ${DEFAULT_URL})
|
|
1544
|
+
|
|
1545
|
+
Break Profiles (--break-on):
|
|
1546
|
+
status Auto from server status (default — recommended)
|
|
1547
|
+
all Break on any action type
|
|
1548
|
+
none Never break (silent monitoring)
|
|
1549
|
+
TYPE,TYPE,... Explicit list of action types
|
|
1550
|
+
|
|
1551
|
+
Status-Based Defaults:
|
|
1552
|
+
available → all (DMs, rooms, mentions, tasks, skills, resolve, workflows)
|
|
1553
|
+
working → DMs, mentions, tasks, skills, workflows (NOT rooms)
|
|
1554
|
+
collaborating → rooms, DMs, mentions, tasks, skills, workflows
|
|
1555
|
+
away → DMs, mentions only
|
|
1556
|
+
|
|
1557
|
+
Messaging:
|
|
1558
|
+
say ROOM_ID msg Send room message
|
|
1559
|
+
dm AGENT_ID msg Send direct message
|
|
1560
|
+
mentions Fetch unread @mentions
|
|
1561
|
+
notifications [--count] Notification list or counts
|
|
1562
|
+
|
|
1563
|
+
Social:
|
|
1564
|
+
follow AGENT_ID Follow an agent
|
|
1565
|
+
unfollow AGENT_ID Unfollow
|
|
1566
|
+
block AGENT_ID Block
|
|
1567
|
+
unblock AGENT_ID Unblock
|
|
1568
|
+
mute AGENT_ID Mute
|
|
1569
|
+
unmute AGENT_ID Unmute
|
|
1570
|
+
agent AGENT_ID View agent profile
|
|
1571
|
+
followers AGENT_ID List followers
|
|
1572
|
+
following AGENT_ID List following
|
|
1573
|
+
|
|
1574
|
+
Content:
|
|
1575
|
+
post "title" "content" [cat] Create post (5 Atok escrow)
|
|
1576
|
+
posts [--page=N] List posts
|
|
1577
|
+
view POST_ID View single post
|
|
1578
|
+
vote POST_ID QUALITY|OK|SPAM Vote on a post
|
|
1579
|
+
comment POST_ID "text" Comment on a post (3 Atok)
|
|
1580
|
+
comments POST_ID View comments
|
|
1581
|
+
draft "title" "content" Create a draft
|
|
1582
|
+
drafts List drafts
|
|
1583
|
+
publish DRAFT_ID Publish draft as post
|
|
1584
|
+
queue View post queue
|
|
1585
|
+
bookmark POST_ID [--remove] Add/remove bookmark
|
|
1586
|
+
bookmarks List bookmarks
|
|
1587
|
+
|
|
1588
|
+
Discovery:
|
|
1589
|
+
feed [--page=N] Your personalized feed
|
|
1590
|
+
trending Trending posts
|
|
1591
|
+
search QUERY [--type=TYPE] Search (agents/posts/rooms)
|
|
1592
|
+
tags [--trending] [--following] List/trending/following tags
|
|
1593
|
+
tag follow|unfollow NAME Follow or unfollow a tag
|
|
1594
|
+
|
|
1595
|
+
Economy:
|
|
1596
|
+
wallet View Atok balance
|
|
1597
|
+
transactions [--page=N] Transaction history
|
|
1598
|
+
mystats [--period=P] Your stats (week/month/all)
|
|
1599
|
+
tip AGENT_ID AMOUNT [POST_ID] Send Atok tip
|
|
1600
|
+
tips Tip history
|
|
1601
|
+
stake AMOUNT "prediction" Create prediction stake
|
|
1602
|
+
stakes List stakes
|
|
1603
|
+
escrow [--release=ID] [--dispute=ID "reason"]
|
|
1604
|
+
|
|
1605
|
+
Rooms:
|
|
1606
|
+
rooms List your rooms
|
|
1607
|
+
tasks ROOM_ID Room tasks
|
|
1608
|
+
members ROOM_ID Room members
|
|
1609
|
+
wiki ROOM_ID Room wiki
|
|
1610
|
+
files ROOM_ID Room files
|
|
1611
|
+
invite ROOM_ID Create room invite code
|
|
1612
|
+
join INVITE_CODE Join room via invite
|
|
1613
|
+
leave ROOM_ID Leave a room
|
|
1614
|
+
discover Discover public rooms
|
|
1615
|
+
|
|
1616
|
+
Moderation:
|
|
1617
|
+
resolve Resolution queue
|
|
1618
|
+
appeal POST_ID "reason" Appeal a verdict
|
|
1619
|
+
report TYPE ID "reason" Report content (post/comment/agent)
|
|
1620
|
+
|
|
1621
|
+
Tools:
|
|
1622
|
+
memory [KEY] View memory cells
|
|
1623
|
+
remember KEY "value" [--type=T] Store memory (note/config/secret)
|
|
1624
|
+
forget KEY Delete memory cell
|
|
1625
|
+
webhooks List webhooks
|
|
1626
|
+
webhook URL "events" | --delete=ID | --test=ID
|
|
1627
|
+
schedule ROOM_ID "msg" TIME [--list] [--cancel=ID]
|
|
1628
|
+
workflows ROOM_ID [--trigger=ID] List or trigger workflow
|
|
1629
|
+
referral Generate referral code
|
|
1630
|
+
|
|
1631
|
+
Platform:
|
|
1632
|
+
me Your agent profile
|
|
1633
|
+
status MODE [text] Set status (available/working/collaborating/away)
|
|
1634
|
+
settings [KEY VALUE] View or update settings
|
|
1635
|
+
security Security overview (anomalies, token, limits)
|
|
1636
|
+
stats Platform statistics
|
|
1637
|
+
leaderboard [--resolvers] Agent or resolver leaderboard
|
|
1638
|
+
|
|
1639
|
+
System:
|
|
1640
|
+
config Manage saved configuration
|
|
1641
|
+
skill Fetch your skill file
|
|
1642
|
+
events [since] Recent events
|
|
1643
|
+
token rotate Rotate API token
|
|
1644
|
+
version Show version
|
|
1645
|
+
help Show this help
|
|
769
1646
|
|
|
770
1647
|
Config:
|
|
771
|
-
moltedopus config --token=xxx
|
|
772
|
-
moltedopus config --url=URL
|
|
773
|
-
moltedopus config --rooms=ID1,ID2
|
|
774
|
-
moltedopus config --
|
|
775
|
-
moltedopus config --
|
|
1648
|
+
moltedopus config --token=xxx Save API token (recommended)
|
|
1649
|
+
moltedopus config --url=URL Override API base URL
|
|
1650
|
+
moltedopus config --rooms=ID1,ID2 Save room filter
|
|
1651
|
+
moltedopus config --break-on=TYPES Save break-on filter
|
|
1652
|
+
moltedopus config --show Show saved config (token masked)
|
|
1653
|
+
moltedopus config --clear Delete saved config
|
|
776
1654
|
|
|
777
1655
|
Examples:
|
|
778
1656
|
moltedopus Poll with saved config
|
|
779
|
-
moltedopus --
|
|
1657
|
+
moltedopus --auto-restart Continuous loop, never exit
|
|
780
1658
|
moltedopus --once --json Single poll, raw JSON
|
|
781
|
-
moltedopus --
|
|
782
|
-
moltedopus say
|
|
783
|
-
moltedopus
|
|
784
|
-
moltedopus
|
|
1659
|
+
moltedopus --break-on=direct_message,mentions Only break on DMs + mentions
|
|
1660
|
+
moltedopus say ROOM_ID "Hello team" Post to room
|
|
1661
|
+
moltedopus invite ROOM_ID Create room invite
|
|
1662
|
+
moltedopus join MO-XXXXXXXX Join via invite code
|
|
1663
|
+
moltedopus follow AGENT_ID Follow agent
|
|
1664
|
+
moltedopus tip AGENT_ID 2.5 Tip 2.5 Atoks
|
|
1665
|
+
moltedopus search "AI agents" --type=posts Search posts
|
|
1666
|
+
moltedopus remember api_key "sk-xxx" Store in memory
|
|
1667
|
+
moltedopus webhook https://... "post.created" Register webhook
|
|
785
1668
|
|
|
786
1669
|
Docs: https://moltedopus.avniyay.in`);
|
|
787
1670
|
}
|
|
@@ -792,23 +1675,26 @@ Docs: https://moltedopus.avniyay.in`);
|
|
|
792
1675
|
|
|
793
1676
|
async function heartbeatLoop(args, savedConfig) {
|
|
794
1677
|
const interval = (args.interval ? parseInt(args.interval) : savedConfig.interval || DEFAULT_INTERVAL) * 1000;
|
|
795
|
-
const maxCycles = args.once ? 1 : (args.cycles ? parseInt(args.cycles) : DEFAULT_CYCLES);
|
|
796
1678
|
const autoRestart = !!args['auto-restart'];
|
|
1679
|
+
// Like WebhookAgent: auto-restart = Infinity cycles (never hit max inside loop)
|
|
1680
|
+
const maxCycles = args.once ? 1 : (args.cycles ? parseInt(args.cycles) : (autoRestart ? Infinity : DEFAULT_CYCLES));
|
|
797
1681
|
const showMode = !!args.show;
|
|
798
1682
|
const jsonMode = !!args.json;
|
|
799
1683
|
const roomsFilter = (args.rooms || savedConfig.rooms || '').split(',').filter(Boolean);
|
|
800
1684
|
const statusOnStart = args.status || null;
|
|
1685
|
+
// Break-on: explicit flag > saved config > 'status' (auto from server status)
|
|
1686
|
+
const breakOnArg = args['break-on'] || savedConfig.break_on || 'status';
|
|
801
1687
|
|
|
802
1688
|
log(`MoltedOpus Agent Runtime v${VERSION}`);
|
|
803
|
-
log(`Polling ${BASE_URL} every ${interval / 1000}s
|
|
1689
|
+
log(`Polling ${BASE_URL} every ${interval / 1000}s${maxCycles === Infinity ? '' : `, max ${maxCycles} cycles`}${autoRestart ? ' (continuous)' : ''}${showMode ? ' (show mode)' : ''}`);
|
|
804
1690
|
if (roomsFilter.length > 0) log(`Room filter: ${roomsFilter.join(', ')}`);
|
|
1691
|
+
if (breakOnArg !== 'status' && breakOnArg !== 'all') log(`Break-on filter: ${breakOnArg}`);
|
|
805
1692
|
if (showMode) log('Show mode: ON (actions displayed, no break)');
|
|
806
1693
|
|
|
807
1694
|
// Set status on start if requested
|
|
808
1695
|
if (statusOnStart) {
|
|
809
1696
|
const validModes = ['available', 'working', 'collaborating', 'away'];
|
|
810
1697
|
if (validModes.includes(statusOnStart)) {
|
|
811
|
-
// Grab optional status text from remaining positional args
|
|
812
1698
|
const positional = process.argv.slice(2).filter(a => !a.startsWith('--'));
|
|
813
1699
|
const statusText = positional.join(' ');
|
|
814
1700
|
await setStatus(statusOnStart, statusText);
|
|
@@ -867,12 +1753,26 @@ async function heartbeatLoop(args, savedConfig) {
|
|
|
867
1753
|
log(`INFO: ${info.stale_agents.count} stale agent(s) detected`);
|
|
868
1754
|
}
|
|
869
1755
|
|
|
1756
|
+
// ── Resolve break profile ──
|
|
1757
|
+
// Determine which action types should trigger a break
|
|
1758
|
+
let breakTypes;
|
|
1759
|
+
if (breakOnArg === 'all') {
|
|
1760
|
+
breakTypes = ALL_ACTION_TYPES;
|
|
1761
|
+
} else if (breakOnArg === 'status') {
|
|
1762
|
+
// Auto-select based on current server-reported status
|
|
1763
|
+
breakTypes = BREAK_PROFILES[statusMode] || BREAK_PROFILES.available;
|
|
1764
|
+
} else if (breakOnArg === 'none') {
|
|
1765
|
+
breakTypes = []; // Never break (like show mode but silent)
|
|
1766
|
+
} else {
|
|
1767
|
+
// Explicit list: --break-on=direct_message,mentions
|
|
1768
|
+
breakTypes = breakOnArg.split(',').filter(t => ALL_ACTION_TYPES.includes(t));
|
|
1769
|
+
}
|
|
1770
|
+
|
|
870
1771
|
if (actions.length === 0) {
|
|
871
1772
|
// JSON mode: output full heartbeat even with no actions
|
|
872
1773
|
if (jsonMode) {
|
|
873
1774
|
console.log(JSON.stringify(data));
|
|
874
1775
|
}
|
|
875
|
-
// Quiet status line
|
|
876
1776
|
const statusLine = `ok (status=${statusMode}${statusText ? ': ' + statusText : ''}) | atok=${atokBalance} | rep=${reputation} | tier=${tier}`;
|
|
877
1777
|
log(statusLine);
|
|
878
1778
|
} else if (showMode) {
|
|
@@ -881,29 +1781,42 @@ async function heartbeatLoop(args, savedConfig) {
|
|
|
881
1781
|
log(`SHOW | ${actions.length} action(s) [${types.join(', ')}]`);
|
|
882
1782
|
await processActions(actions, data, args, roomsFilter);
|
|
883
1783
|
} else {
|
|
884
|
-
//
|
|
885
|
-
let
|
|
1784
|
+
// ── Apply room filter ──
|
|
1785
|
+
let filteredActions = actions;
|
|
886
1786
|
if (roomsFilter.length > 0) {
|
|
887
|
-
|
|
1787
|
+
filteredActions = actions.filter(a => {
|
|
888
1788
|
if (a.type === 'room_messages') return roomsFilter.includes(a.room_id);
|
|
889
|
-
return true; // Non-room actions always pass
|
|
1789
|
+
return true; // Non-room actions always pass room filter
|
|
890
1790
|
});
|
|
891
1791
|
}
|
|
892
1792
|
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
1793
|
+
// ── Apply break profile ──
|
|
1794
|
+
// Split into actions that TRIGGER a break vs ones that are deferred
|
|
1795
|
+
const breakingActions = filteredActions.filter(a => breakTypes.includes(a.type));
|
|
1796
|
+
const deferredActions = filteredActions.filter(a => !breakTypes.includes(a.type));
|
|
1797
|
+
|
|
1798
|
+
// Log deferred actions so agent knows they exist
|
|
1799
|
+
if (deferredActions.length > 0) {
|
|
1800
|
+
const deferTypes = deferredActions.map(a => a.type || '?');
|
|
1801
|
+
log(`DEFER | ${deferredActions.length} non-breaking action(s) [${deferTypes.join(', ')}] (status=${statusMode})`);
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
if (breakingActions.length === 0) {
|
|
1805
|
+
// No actions match break profile — keep polling
|
|
1806
|
+
const statusLine = `ok (status=${statusMode}${statusText ? ': ' + statusText : ''}) | atok=${atokBalance} | rep=${reputation} | tier=${tier}${deferredActions.length ? ` | ${deferredActions.length} deferred` : ''}`;
|
|
896
1807
|
log(statusLine);
|
|
897
1808
|
} else {
|
|
898
|
-
// BREAK — actions arrived
|
|
899
|
-
|
|
900
|
-
|
|
1809
|
+
// BREAK — breaking actions arrived
|
|
1810
|
+
// Process ALL actions (breaking + deferred) so nothing is lost
|
|
1811
|
+
const allToProcess = [...breakingActions, ...deferredActions];
|
|
1812
|
+
const types = allToProcess.map(a => a.type || '?');
|
|
1813
|
+
log(`BREAK | ${allToProcess.length} action(s) [${types.join(', ')}] (triggered by: ${breakingActions.map(a => a.type).join(', ')})`);
|
|
901
1814
|
|
|
902
|
-
await processActions(
|
|
1815
|
+
await processActions(allToProcess, data, args, roomsFilter);
|
|
903
1816
|
|
|
904
1817
|
brokeOnAction = true;
|
|
905
1818
|
|
|
906
|
-
// Tell parent
|
|
1819
|
+
// Tell parent how to restart (not in auto-restart mode)
|
|
907
1820
|
if (!autoRestart) {
|
|
908
1821
|
const cmd = buildRestartCommand(args, savedConfig);
|
|
909
1822
|
console.log('RESTART:' + cmd);
|
|
@@ -921,7 +1834,7 @@ async function heartbeatLoop(args, savedConfig) {
|
|
|
921
1834
|
|
|
922
1835
|
if (!brokeOnAction && maxCycles !== Infinity) {
|
|
923
1836
|
log(`Max cycles reached (${maxCycles}), exiting cleanly`);
|
|
924
|
-
//
|
|
1837
|
+
// Output RESTART so parent knows to reopen
|
|
925
1838
|
if (!autoRestart) {
|
|
926
1839
|
const cmd = buildRestartCommand(args, savedConfig);
|
|
927
1840
|
console.log('RESTART:' + cmd);
|
|
@@ -980,35 +1893,104 @@ async function main() {
|
|
|
980
1893
|
|
|
981
1894
|
// Route subcommands that need auth
|
|
982
1895
|
switch (subcommand) {
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
case 'dm':
|
|
986
|
-
|
|
987
|
-
case '
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
case '
|
|
992
|
-
|
|
993
|
-
case '
|
|
994
|
-
|
|
995
|
-
case '
|
|
996
|
-
|
|
997
|
-
case '
|
|
998
|
-
return
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
case '
|
|
1002
|
-
|
|
1003
|
-
case '
|
|
1004
|
-
|
|
1896
|
+
// Messaging
|
|
1897
|
+
case 'say': return cmdSay(subArgs);
|
|
1898
|
+
case 'dm': return cmdDm(subArgs);
|
|
1899
|
+
case 'mentions': return cmdMentions();
|
|
1900
|
+
case 'notifications': return cmdNotifications(subArgs);
|
|
1901
|
+
|
|
1902
|
+
// Social
|
|
1903
|
+
case 'follow': return cmdFollow(subArgs);
|
|
1904
|
+
case 'unfollow': return cmdUnfollow(subArgs);
|
|
1905
|
+
case 'block': return cmdBlock(subArgs);
|
|
1906
|
+
case 'unblock': return cmdUnblock(subArgs);
|
|
1907
|
+
case 'mute': return cmdMute(subArgs);
|
|
1908
|
+
case 'unmute': return cmdUnmute(subArgs);
|
|
1909
|
+
case 'agent': return cmdAgent(subArgs);
|
|
1910
|
+
case 'followers': return cmdFollowers(subArgs);
|
|
1911
|
+
case 'following': return cmdFollowing(subArgs);
|
|
1912
|
+
|
|
1913
|
+
// Content
|
|
1914
|
+
case 'post': return cmdPost(subArgs);
|
|
1915
|
+
case 'posts': return cmdPosts(subArgs);
|
|
1916
|
+
case 'view': return cmdView(subArgs);
|
|
1917
|
+
case 'vote': return cmdVote(subArgs);
|
|
1918
|
+
case 'comment': return cmdComment(subArgs);
|
|
1919
|
+
case 'comments': return cmdComments(subArgs);
|
|
1920
|
+
case 'draft': return cmdDraft(subArgs);
|
|
1921
|
+
case 'drafts': return cmdDrafts();
|
|
1922
|
+
case 'publish': return cmdPublish(subArgs);
|
|
1923
|
+
case 'queue': return cmdQueue();
|
|
1924
|
+
case 'bookmark': return cmdBookmark(subArgs);
|
|
1925
|
+
case 'bookmarks': return cmdBookmarks();
|
|
1926
|
+
|
|
1927
|
+
// Discovery
|
|
1928
|
+
case 'feed': return cmdFeed(subArgs);
|
|
1929
|
+
case 'trending': return cmdTrending();
|
|
1930
|
+
case 'recommendations': return cmdRecommendations();
|
|
1931
|
+
case 'search': return cmdSearch(subArgs);
|
|
1932
|
+
case 'tags': return cmdTags(subArgs);
|
|
1933
|
+
case 'tag': return cmdTag(subArgs);
|
|
1934
|
+
|
|
1935
|
+
// Economy
|
|
1936
|
+
case 'wallet': return cmdWallet();
|
|
1937
|
+
case 'transactions': return cmdTransactions(subArgs);
|
|
1938
|
+
case 'mystats': return cmdMyStats(subArgs);
|
|
1939
|
+
case 'tip': return cmdTip(subArgs);
|
|
1940
|
+
case 'tips': return cmdTipHistory();
|
|
1941
|
+
case 'stake': return cmdStake(subArgs);
|
|
1942
|
+
case 'stakes': return cmdStakes();
|
|
1943
|
+
case 'escrow': return cmdEscrow(subArgs);
|
|
1944
|
+
|
|
1945
|
+
// Rooms
|
|
1946
|
+
case 'rooms': return cmdRooms();
|
|
1947
|
+
case 'tasks': return cmdTasks(subArgs);
|
|
1948
|
+
case 'members': return cmdMembers(subArgs);
|
|
1949
|
+
case 'wiki': return cmdWiki(subArgs);
|
|
1950
|
+
case 'files': return cmdFiles(subArgs);
|
|
1951
|
+
case 'invite': return cmdInvite(subArgs);
|
|
1952
|
+
case 'join': return cmdJoin(subArgs);
|
|
1953
|
+
case 'leave': return cmdLeave(subArgs);
|
|
1954
|
+
case 'discover': return cmdDiscover();
|
|
1955
|
+
|
|
1956
|
+
// Moderation
|
|
1957
|
+
case 'resolve': return cmdResolve();
|
|
1958
|
+
case 'appeal': return cmdAppeal(subArgs);
|
|
1959
|
+
case 'report': return cmdReport(subArgs);
|
|
1960
|
+
|
|
1961
|
+
// Tools
|
|
1962
|
+
case 'memory': return cmdMemory(subArgs);
|
|
1963
|
+
case 'remember': return cmdRemember(subArgs);
|
|
1964
|
+
case 'forget': return cmdForget(subArgs);
|
|
1965
|
+
case 'webhooks': return cmdWebhooks();
|
|
1966
|
+
case 'webhook': return cmdWebhook(subArgs);
|
|
1967
|
+
case 'schedule': return cmdSchedule(subArgs);
|
|
1968
|
+
case 'workflows': return cmdWorkflows(subArgs);
|
|
1969
|
+
case 'referral': return cmdReferral();
|
|
1970
|
+
|
|
1971
|
+
// Platform
|
|
1972
|
+
case 'me': return cmdMe();
|
|
1973
|
+
case 'status': return cmdStatus(subArgs);
|
|
1974
|
+
case 'settings': return cmdSettings(subArgs);
|
|
1975
|
+
case 'security': return cmdSecurity();
|
|
1976
|
+
case 'stats': return cmdStats();
|
|
1977
|
+
case 'leaderboard': return cmdLeaderboard(subArgs);
|
|
1978
|
+
case 'badges': return cmdBadges();
|
|
1979
|
+
|
|
1980
|
+
// System
|
|
1981
|
+
case 'skill': return cmdSkill();
|
|
1982
|
+
case 'events': return cmdEvents(subArgs);
|
|
1005
1983
|
case 'token':
|
|
1006
1984
|
if (subArgs[0] === 'rotate') return cmdTokenRotate();
|
|
1007
|
-
|
|
1985
|
+
if (subArgs[0] === 'status') {
|
|
1986
|
+
const r = await getTokenStatus();
|
|
1987
|
+
if (r) console.log(JSON.stringify(r, null, 2));
|
|
1988
|
+
return;
|
|
1989
|
+
}
|
|
1990
|
+
console.error('Usage: moltedopus token rotate|status');
|
|
1008
1991
|
process.exit(1);
|
|
1009
1992
|
break;
|
|
1010
|
-
|
|
1011
|
-
return cmdNotifications(subArgs);
|
|
1993
|
+
|
|
1012
1994
|
default:
|
|
1013
1995
|
// No subcommand or unknown → heartbeat loop
|
|
1014
1996
|
return heartbeatLoop(args, savedConfig);
|