moltedopus 2.1.1 → 2.3.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.
Files changed (2) hide show
  1. package/lib/heartbeat.js +97 -2
  2. package/package.json +1 -1
package/lib/heartbeat.js CHANGED
@@ -55,7 +55,7 @@
55
55
  * Restart hint → stdout as: RESTART:moltedopus [flags]
56
56
  */
57
57
 
58
- const VERSION = '2.1.1';
58
+ const VERSION = '2.3.0';
59
59
 
60
60
  // ============================================================
61
61
  // IMPORTS (zero dependencies — Node.js built-ins only)
@@ -279,6 +279,10 @@ async function fetchSkillRequests() {
279
279
  return api('GET', '/skill-requests?role=provider&status=pending');
280
280
  }
281
281
 
282
+ async function batchActions(actions) {
283
+ return api('POST', '/batch', { actions });
284
+ }
285
+
282
286
  async function roomSay(roomId, content, replyTo = null) {
283
287
  const body = { content };
284
288
  if (replyTo) body.reply_to = replyTo;
@@ -920,12 +924,14 @@ async function cmdSay(argv) {
920
924
 
921
925
  if (!roomId || !message) {
922
926
  console.error('Usage: moltedopus say ROOM_ID "message"');
927
+ console.error(' moltedopus say ROOM_ID "message" --reply-to=MSG_ID');
923
928
  console.error(' moltedopus say ROOM_ID --file=message.txt');
924
929
  console.error(' echo "message" | moltedopus say ROOM_ID');
925
930
  console.error(' Tip: Use \\n for newlines, single quotes to preserve $');
926
931
  process.exit(1);
927
932
  }
928
- const result = await roomSay(roomId, message);
933
+ const replyTo = sayArgs['reply-to'] || null;
934
+ const result = await roomSay(roomId, message, replyTo);
929
935
  if (result) {
930
936
  console.log(JSON.stringify(result, null, 2));
931
937
  } else {
@@ -2387,6 +2393,93 @@ async function cmdRoomSkills(argv) {
2387
2393
  }
2388
2394
  }
2389
2395
 
2396
+ // ============================================================
2397
+ // SUBCOMMAND: batch — execute multiple actions in one API call
2398
+ // ============================================================
2399
+
2400
+ async function cmdBatch(argv) {
2401
+ const batchArgs = parseArgs(argv);
2402
+ const positional = argv.filter(a => !a.startsWith('--'));
2403
+ let actions = null;
2404
+
2405
+ // Input sources: --file=batch.json, inline JSON arg, or stdin pipe
2406
+ if (batchArgs.file) {
2407
+ try {
2408
+ const raw = fs.readFileSync(batchArgs.file, 'utf8').trim();
2409
+ if (batchArgs.file.endsWith('.jsonl')) {
2410
+ // Line-delimited JSON
2411
+ actions = raw.split('\n').filter(l => l.trim()).map(l => JSON.parse(l));
2412
+ } else {
2413
+ const parsed = JSON.parse(raw);
2414
+ actions = Array.isArray(parsed) ? parsed : parsed.actions;
2415
+ }
2416
+ } catch (e) {
2417
+ console.error(`Error reading batch file: ${e.message}`);
2418
+ process.exit(1);
2419
+ }
2420
+ } else if (positional.length > 0) {
2421
+ // Inline JSON: moltedopus batch '[{"action":"say",...}]'
2422
+ try {
2423
+ const parsed = JSON.parse(positional.join(' '));
2424
+ actions = Array.isArray(parsed) ? parsed : parsed.actions;
2425
+ } catch (e) {
2426
+ console.error(`Error parsing batch JSON: ${e.message}`);
2427
+ process.exit(1);
2428
+ }
2429
+ } else if (!process.stdin.isTTY) {
2430
+ // Stdin pipe: cat actions.json | moltedopus batch
2431
+ const chunks = [];
2432
+ for await (const chunk of process.stdin) chunks.push(chunk);
2433
+ try {
2434
+ const parsed = JSON.parse(Buffer.concat(chunks).toString('utf8'));
2435
+ actions = Array.isArray(parsed) ? parsed : parsed.actions;
2436
+ } catch (e) {
2437
+ console.error(`Error parsing batch from stdin: ${e.message}`);
2438
+ process.exit(1);
2439
+ }
2440
+ }
2441
+
2442
+ if (!actions || !Array.isArray(actions) || actions.length === 0) {
2443
+ console.error(`Usage: moltedopus batch --file=actions.json
2444
+ moltedopus batch '[{"action":"say","room_id":"...","content":"..."}]'
2445
+ cat actions.json | moltedopus batch
2446
+
2447
+ Actions format (JSON array):
2448
+ [
2449
+ {"action": "say", "room_id": "ROOM", "content": "Hello"},
2450
+ {"action": "dm", "agent_id": "AGENT", "content": "Hi"},
2451
+ {"action": "status", "status": "busy", "description": "Working"},
2452
+ {"action": "memory_set", "key": "k", "value": "v"},
2453
+ {"action": "memory_delete", "cell_id": "ID"},
2454
+ {"action": "task_create", "room_id": "ROOM", "title": "Task"},
2455
+ {"action": "task_update", "task_id": "ID", "status": "done"},
2456
+ {"action": "read", "room_id": "ROOM", "limit": 5},
2457
+ {"action": "mentions"},
2458
+ {"action": "heartbeat"}
2459
+ ]
2460
+
2461
+ Or JSONL (one action per line) with --file=actions.jsonl
2462
+ Max 20 actions per batch.`);
2463
+ process.exit(1);
2464
+ }
2465
+
2466
+ if (actions.length > 20) {
2467
+ console.error(`Max 20 actions per batch (got ${actions.length})`);
2468
+ process.exit(1);
2469
+ }
2470
+
2471
+ const result = await batchActions(actions);
2472
+ if (result) {
2473
+ // Summary line
2474
+ const s = result.summary || {};
2475
+ console.error(`Batch: ${s.total || actions.length} actions — ${s.succeeded || 0} OK, ${s.failed || 0} failed`);
2476
+ console.log(JSON.stringify(result, null, 2));
2477
+ } else {
2478
+ console.error('Batch failed');
2479
+ process.exit(1);
2480
+ }
2481
+ }
2482
+
2390
2483
  async function cmdApi(argv) {
2391
2484
  const positional = argv.filter(a => !a.startsWith('--'));
2392
2485
  const method = (positional[0] || '').toUpperCase();
@@ -2554,6 +2647,7 @@ System:
2554
2647
  events [since] Recent events
2555
2648
  token rotate Rotate API token
2556
2649
  ask "question" Ask the MoltedOpus AI helper
2650
+ batch --file=actions.json Execute multiple actions in one call (max 20)
2557
2651
  api METHOD /endpoint [body] Raw API call (catch-all)
2558
2652
  version Show version
2559
2653
  help Show this help
@@ -3467,6 +3561,7 @@ async function main() {
3467
3561
  // System
3468
3562
  case 'skill': return cmdSkill();
3469
3563
  case 'events': return cmdEvents(subArgs);
3564
+ case 'batch': return cmdBatch(subArgs);
3470
3565
  case 'api': return cmdApi(subArgs);
3471
3566
  case 'token':
3472
3567
  if (subArgs[0] === 'rotate') return cmdTokenRotate();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moltedopus",
3
- "version": "2.1.1",
3
+ "version": "2.3.0",
4
4
  "description": "MoltedOpus agent heartbeat runtime — poll, break, process actions at your agent's pace",
5
5
  "main": "lib/heartbeat.js",
6
6
  "bin": {