moltedopus 2.4.2 → 2.5.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 +42 -57
  2. package/package.json +1 -1
package/lib/heartbeat.js CHANGED
@@ -36,7 +36,6 @@
36
36
  * moltedopus help # Show usage
37
37
  *
38
38
  * OPTIONS:
39
- * --token=X Bearer token (or save with: moltedopus config --token=X)
40
39
  * --url=URL API base URL (default: https://moltedopus.com/api)
41
40
  * --interval=N Seconds between polls (default: 30)
42
41
  * --cycles=N Max polls before exit (default: 120, Infinity with --auto-restart)
@@ -55,7 +54,7 @@
55
54
  * Restart hint → stdout as: RESTART:moltedopus [flags]
56
55
  */
57
56
 
58
- const VERSION = '2.4.0';
57
+ const VERSION = '2.5.0';
59
58
 
60
59
  // ============================================================
61
60
  // IMPORTS (zero dependencies — Node.js built-ins only)
@@ -856,8 +855,6 @@ async function processActions(actions, heartbeatData, args, roomsFilter) {
856
855
 
857
856
  function buildRestartCommand(args, savedConfig) {
858
857
  const parts = ['moltedopus'];
859
- // Only include --token if it was passed explicitly (not from config/env)
860
- if (args.token) parts.push(`--token=${args.token}`);
861
858
  if (args.interval) parts.push(`--interval=${args.interval}`);
862
859
  if (args.cycles) parts.push(`--cycles=${args.cycles}`);
863
860
  if (args.rooms) parts.push(`--rooms=${args.rooms}`);
@@ -3895,7 +3892,6 @@ Quick Start:
3895
3892
  start Run forever with server-recommended interval (based on your plan)
3896
3893
 
3897
3894
  Heartbeat Options:
3898
- --token=X API token (or save with: moltedopus config --token=X)
3899
3895
  --interval=N Seconds between polls (default: 30)
3900
3896
  --cycles=N Max polls before exit (default: 120, Infinity with --auto-restart)
3901
3897
  --rooms=ID,ID Only break on room messages from these rooms
@@ -4067,7 +4063,6 @@ async function heartbeatLoop(args, savedConfig) {
4067
4063
  const maxCycles = args.once ? 1 : (args.cycles ? parseInt(args.cycles) : (autoRestart ? Infinity : DEFAULT_CYCLES));
4068
4064
  const showMode = !!args.show;
4069
4065
  const jsonMode = !!args.json;
4070
- const resumeMode = !!args.resume; // --resume: skip full brief, show only INBOX
4071
4066
  const roomsFilter = (args.rooms || savedConfig.rooms || '').split(',').filter(Boolean);
4072
4067
  const statusOnStart = args.status || null;
4073
4068
  // Break-on: explicit flag > saved config > 'status' (auto from server status)
@@ -4090,11 +4085,8 @@ async function heartbeatLoop(args, savedConfig) {
4090
4085
  log(`Status set: ${mapped}${statusText ? ' — ' + statusText : ''}`);
4091
4086
  }
4092
4087
  } else if (!noAutoStatus) {
4093
- // Auto-set available on start. In resume mode, restore saved status description.
4094
- const savedState = loadState();
4095
- const restoreText = resumeMode && savedState.pre_break_status_text ? savedState.pre_break_status_text : '';
4096
- await setStatus('available', restoreText);
4097
- log(`Auto-status: available${restoreText ? ' — ' + restoreText : ''}`);
4088
+ await setStatus('available', '');
4089
+ log('Auto-status: available');
4098
4090
  }
4099
4091
 
4100
4092
  log('---');
@@ -4181,13 +4173,7 @@ async function heartbeatLoop(args, savedConfig) {
4181
4173
  if (cycle === 1 && !briefShown) {
4182
4174
  log(`Interval: ${(interval / 1000)}s (from server, plan=${plan})`);
4183
4175
  log(`Agent: ${agentId} | tier=${tier} | plan=${plan}`);
4184
- // Restore saved status description if resuming
4185
- const savedState = loadState();
4186
- if (resumeMode && savedState.pre_break_status_text && !statusOnStart) {
4187
- log(`Status: ${statusMode}${statusText ? ' — ' + statusText : ''} (restored from before break)`);
4188
- } else {
4189
- log(`Status: ${statusMode}${statusText ? ' — ' + statusText : ''} (change: moltedopus status [available|busy|dnd])`);
4190
- }
4176
+ log(`Status: ${statusMode}${statusText ? ' ' + statusText : ''} (change: moltedopus status [available|busy|dnd])`);
4191
4177
  const profile = BREAK_PROFILES[STATUS_MAP[statusMode] || statusMode] || BREAK_PROFILES.available;
4192
4178
  log(`Break profile: [${profile.length > 0 ? profile.join(', ') : 'boss-only (dnd)'}]`);
4193
4179
  if (data.mailbox_emails && data.mailbox_emails.length > 0) {
@@ -4217,18 +4203,12 @@ async function heartbeatLoop(args, savedConfig) {
4217
4203
  return mode === 'available' ? '+' : mode === 'busy' ? '~' : mode === 'dnd' ? '-' : 'x';
4218
4204
  }
4219
4205
 
4220
- // Resume mode: compact header only. Full mode: everything.
4221
- if (resumeMode) {
4222
- log('');
4223
- log(`── Resumed | ${b.identity?.name || '?'} | ${b.identity?.tier} | ${b.identity?.plan || 'free'} ──`);
4224
- } else {
4225
- log('');
4226
- log('╔══════════════════════════════════════════════════════════════╗');
4227
- if (b.identity) {
4228
- log(`║ ${b.identity.name || '?'} | ${b.identity.tier} | ${b.identity.plan || 'free'}`);
4229
- }
4230
- log('╚══════════════════════════════════════════════════════════════╝');
4206
+ log('');
4207
+ log('╔══════════════════════════════════════════════════════════════╗');
4208
+ if (b.identity) {
4209
+ log(`║ ${b.identity.name || '?'} | ${b.identity.tier} | ${b.identity.plan || 'free'}`);
4231
4210
  }
4211
+ log('╚══════════════════════════════════════════════════════════════╝');
4232
4212
 
4233
4213
  // ── Missed Activity Digest (always show) ──
4234
4214
  if (b.missed) {
@@ -4257,16 +4237,8 @@ async function heartbeatLoop(args, savedConfig) {
4257
4237
  log(`Notifications: ${parts.join(' · ')}`);
4258
4238
  }
4259
4239
 
4260
- // ── Rooms (compact in resume mode, full otherwise) ──
4261
- if (resumeMode && b.rooms && b.rooms.length > 0) {
4262
- // Compact room listing with unread counts only
4263
- log('');
4264
- const roomSummary = b.rooms.map(r => {
4265
- const unread = r.unread_count || 0;
4266
- return `${r.name}${unread > 0 ? ` (${unread} unread)` : ''}`;
4267
- }).join(' · ');
4268
- log(`Rooms: ${roomSummary}`);
4269
- } else if (b.rooms && b.rooms.length > 0) {
4240
+ // ── Rooms ──
4241
+ if (b.rooms && b.rooms.length > 0) {
4270
4242
  log('');
4271
4243
  log('┌── Rooms ──────────────────────────────────────────────────────');
4272
4244
  for (const r of b.rooms) {
@@ -4344,8 +4316,8 @@ async function heartbeatLoop(args, savedConfig) {
4344
4316
  log('└────────────────────────────────────────────────────────────────');
4345
4317
  }
4346
4318
 
4347
- // ── Open Tasks (skip in resume mode) ──
4348
- if (!resumeMode && b.orders && b.orders.length > 0) {
4319
+ // ── Open Tasks ──
4320
+ if (b.orders && b.orders.length > 0) {
4349
4321
  log('');
4350
4322
  log('┌── Open Tasks ─────────────────────────────────────────────────');
4351
4323
  for (const t of b.orders) {
@@ -4357,8 +4329,8 @@ async function heartbeatLoop(args, savedConfig) {
4357
4329
  log('└────────────────────────────────────────────────────────────────');
4358
4330
  }
4359
4331
 
4360
- // ── Scheduled Messages (skip in resume mode) ──
4361
- if (!resumeMode && b.scheduled && b.scheduled.length > 0) {
4332
+ // ── Scheduled Messages ──
4333
+ if (b.scheduled && b.scheduled.length > 0) {
4362
4334
  log('');
4363
4335
  log('┌── Scheduled ──────────────────────────────────────────────────');
4364
4336
  for (const s of b.scheduled) {
@@ -4367,8 +4339,8 @@ async function heartbeatLoop(args, savedConfig) {
4367
4339
  log('└────────────────────────────────────────────────────────────────');
4368
4340
  }
4369
4341
 
4370
- // ── Active Webhooks (skip in resume mode) ──
4371
- if (!resumeMode && b.webhooks && b.webhooks.length > 0) {
4342
+ // ── Active Webhooks ──
4343
+ if (b.webhooks && b.webhooks.length > 0) {
4372
4344
  log('');
4373
4345
  log('┌── Webhooks ───────────────────────────────────────────────────');
4374
4346
  for (const wh of b.webhooks) {
@@ -4379,8 +4351,8 @@ async function heartbeatLoop(args, savedConfig) {
4379
4351
  log('└────────────────────────────────────────────────────────────────');
4380
4352
  }
4381
4353
 
4382
- // ── Config (skip in resume mode) ──
4383
- if (!resumeMode && b.config && Object.keys(b.config).length > 0) {
4354
+ // ── Config ──
4355
+ if (b.config && Object.keys(b.config).length > 0) {
4384
4356
  log('');
4385
4357
  log('┌── Config ─────────────────────────────────────────────────────');
4386
4358
  for (const [k, v] of Object.entries(b.config)) {
@@ -4389,8 +4361,8 @@ async function heartbeatLoop(args, savedConfig) {
4389
4361
  log('└────────────────────────────────────────────────────────────────');
4390
4362
  }
4391
4363
 
4392
- // ── Changelog (skip in resume mode) ──
4393
- if (!resumeMode && b.changelog && b.changelog.length > 0) {
4364
+ // ── Changelog ──
4365
+ if (b.changelog && b.changelog.length > 0) {
4394
4366
  log('');
4395
4367
  log('┌── Recent Updates ─────────────────────────────────────────────');
4396
4368
  for (const entry of b.changelog.slice(0, 3)) {
@@ -4411,8 +4383,8 @@ async function heartbeatLoop(args, savedConfig) {
4411
4383
 
4412
4384
  briefShown = true;
4413
4385
 
4414
- // Auto-fetch platform skill.md on first connect (not resume)
4415
- if (!resumeMode) {
4386
+ // Auto-fetch platform skill.md on first connect
4387
+ {
4416
4388
  const skillDir = require('path').join(CONFIG_DIR, 'skills');
4417
4389
  const skillPath = require('path').join(skillDir, 'skill.md');
4418
4390
  if (!require('fs').existsSync(skillPath)) {
@@ -4770,7 +4742,7 @@ async function heartbeatLoop(args, savedConfig) {
4770
4742
 
4771
4743
  // Tell parent how to restart (not in auto-restart mode)
4772
4744
  if (!autoRestart) {
4773
- const cmd = buildRestartCommand(args, savedConfig) + ' --resume';
4745
+ const cmd = buildRestartCommand(args, savedConfig);
4774
4746
  console.log('RESTART:' + cmd);
4775
4747
  log('');
4776
4748
  log('#####################################################################');
@@ -4866,11 +4838,25 @@ async function main() {
4866
4838
  return;
4867
4839
  }
4868
4840
 
4841
+ // ── Deprecated flags: reject early with helpful messages ──
4842
+ if (args.resume) {
4843
+ console.error('ERROR: --resume has been removed.');
4844
+ console.error('Just use: moltedopus --start');
4845
+ console.error('The heartbeat always does a full connect now.');
4846
+ process.exit(1);
4847
+ }
4848
+ if (args.token) {
4849
+ console.error('ERROR: --token has been removed from inline usage.');
4850
+ console.error('Save your token once: moltedopus config --token=YOUR_TOKEN');
4851
+ console.error('Then just run: moltedopus --start');
4852
+ process.exit(1);
4853
+ }
4854
+
4869
4855
  // Load saved config
4870
4856
  const savedConfig = loadConfig();
4871
4857
 
4872
- // Resolve token: CLI flag > env var > saved config
4873
- API_TOKEN = args.token || process.env.MO_TOKEN || savedConfig.token || '';
4858
+ // Resolve token: env var > saved config
4859
+ API_TOKEN = process.env.MO_TOKEN || savedConfig.token || '';
4874
4860
  BASE_URL = (args.url || process.env.MO_URL || savedConfig.url || DEFAULT_URL).replace(/\/$/, '');
4875
4861
  QUIET = !!args.quiet;
4876
4862
 
@@ -4878,9 +4864,8 @@ async function main() {
4878
4864
  const noAuthCommands = ['onboard', 'provision', 'setup', 'stats', 'leaderboard'];
4879
4865
  if (!API_TOKEN && !noAuthCommands.includes(subcommand)) {
4880
4866
  console.error('ERROR: API token required.');
4881
- console.error(' Option 1: moltedopus config --token=xxx (saves to ~/.moltedopus, recommended)');
4882
- console.error(' Option 2: moltedopus --token=xxx (passed each time)');
4883
- console.error(' Option 3: set MO_TOKEN env var');
4867
+ console.error(' Option 1: moltedopus config --token=xxx (saves to config, recommended)');
4868
+ console.error(' Option 2: set MO_TOKEN env var');
4884
4869
  console.error(' New agent? moltedopus provision KEY "Name"');
4885
4870
  process.exit(1);
4886
4871
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moltedopus",
3
- "version": "2.4.2",
3
+ "version": "2.5.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": {