@myvillage/cli 1.31.0 → 1.32.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myvillage/cli",
3
- "version": "1.31.0",
3
+ "version": "1.32.0",
4
4
  "description": "MyVillageOS CLI for community developers",
5
5
  "type": "module",
6
6
  "bin": {
@@ -431,11 +431,17 @@ Guidelines:
431
431
  durationMs: Date.now() - loopStart,
432
432
  activitySummary: { feedItemsRead, mentionsFound },
433
433
  });
434
- } catch {
434
+ } catch (err) {
435
+ if (isPausedResponse(err)) throw new AgentPausedError();
435
436
  logActivity(agentDir, { type: 'error', error: 'Failed to send server heartbeat' });
436
437
  }
437
438
  }
438
439
  } catch (err) {
440
+ if (err instanceof AgentPausedError) {
441
+ logActivity(agentDir, { type: 'agent_paused', message: err.message });
442
+ console.log('\n[MyVillage] This agent has been paused by an admin. Exiting.\n');
443
+ break;
444
+ }
439
445
  logActivity(agentDir, {
440
446
  type: 'error',
441
447
  error: err.message,
@@ -583,9 +589,23 @@ function summarizeToolResult(tr) {
583
589
  return text.slice(0, 200);
584
590
  }
585
591
 
592
+ class AgentPausedError extends Error {
593
+ constructor(message = 'Agent is paused by an admin') {
594
+ super(message);
595
+ this.name = 'AgentPausedError';
596
+ this.code = 'AGENT_PAUSED';
597
+ }
598
+ }
599
+
600
+ function isPausedResponse(err) {
601
+ return err?.response?.status === 409 && err?.response?.data?.code === 'AGENT_PAUSED';
602
+ }
603
+
586
604
  // Pull up to 5 pending tasks and claim the first one we can win the race for.
587
605
  // Returns the claimed task or null. Errors are swallowed and logged — the loop
588
- // should keep running on transient backend issues.
606
+ // should keep running on transient backend issues. A pause response (409
607
+ // AGENT_PAUSED) is the one exception: rethrown as AgentPausedError so the
608
+ // outer loop can shut down cleanly.
589
609
  async function pollAndClaim(villageAgentId, agentDir) {
590
610
  try {
591
611
  const result = await listAgentTasks(villageAgentId, { status: 'PENDING', limit: 5 });
@@ -595,12 +615,15 @@ async function pollAndClaim(villageAgentId, agentDir) {
595
615
  try {
596
616
  const claim = await claimAgentTask(villageAgentId, task.id);
597
617
  return claim.data || task;
598
- } catch {
599
- // Race lost (409) or transient — try the next task
618
+ } catch (err) {
619
+ if (isPausedResponse(err)) throw new AgentPausedError();
620
+ // Race lost (409 not-paused) or transient — try the next task
600
621
  }
601
622
  }
602
623
  return null;
603
624
  } catch (err) {
625
+ if (err instanceof AgentPausedError) throw err;
626
+ if (isPausedResponse(err)) throw new AgentPausedError();
604
627
  logActivity(agentDir, { type: 'error', error: `Task poll failed: ${err.message}` });
605
628
  return null;
606
629
  }