@ducci/jarvis 1.0.51 → 1.0.52

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": "@ducci/jarvis",
3
- "version": "1.0.51",
3
+ "version": "1.0.52",
4
4
  "description": "A fully automated agent system that lives on a server.",
5
5
  "main": "./src/index.js",
6
6
  "type": "module",
@@ -60,8 +60,61 @@ export async function runCron(entry, config) {
60
60
  }
61
61
 
62
62
  let run;
63
+ let handoffCount = 0;
64
+ let previousRemaining = null;
65
+ const failedApproaches = [];
66
+ const checkpointState = {};
67
+
63
68
  try {
64
- run = await runAgentLoop(client, config, session, prepareMessages, usageAccum);
69
+ while (true) {
70
+ const runStartIndex = session.messages.length;
71
+
72
+ try {
73
+ run = await runAgentLoop(client, config, session, prepareMessages, usageAccum);
74
+ } catch (e) {
75
+ run = { status: 'error', response: e.message, logSummary: e.message, runToolCalls: [] };
76
+ break;
77
+ }
78
+
79
+ if (run.status !== 'checkpoint_reached') break;
80
+
81
+ if (run.checkpoint.failedApproaches?.length > 0) {
82
+ failedApproaches.push(...run.checkpoint.failedApproaches);
83
+ }
84
+ if (run.checkpoint.state && Object.keys(run.checkpoint.state).length > 0) {
85
+ Object.assign(checkpointState, run.checkpoint.state);
86
+ }
87
+
88
+ // Zero-progress detection
89
+ const currentRemaining = (run.checkpoint.remaining || '').trim();
90
+ if (previousRemaining !== null && currentRemaining === previousRemaining) {
91
+ run = { ...run, status: 'intervention_required', logSummary: 'Zero progress detected in cron run.' };
92
+ session.messages.splice(runStartIndex, session.messages.length - runStartIndex - 1);
93
+ break;
94
+ }
95
+ previousRemaining = currentRemaining;
96
+
97
+ // Max handoffs
98
+ handoffCount++;
99
+ if (handoffCount > config.maxHandoffs) {
100
+ run = { ...run, status: 'intervention_required', logSummary: 'Max handoffs exceeded in cron run.' };
101
+ session.messages.splice(runStartIndex, session.messages.length - runStartIndex - 1);
102
+ break;
103
+ }
104
+
105
+ // Strip intermediate tool history, keep wrap-up assistant response
106
+ session.messages.splice(runStartIndex, session.messages.length - runStartIndex - 1);
107
+
108
+ // Resume with checkpoint.remaining + accumulated context
109
+ let resumeContent = run.checkpoint.remaining || 'Continue with the task.';
110
+ if (failedApproaches.length > 0) {
111
+ resumeContent += `\n\n[System: The following approaches were tried and failed in previous runs — do not repeat them:\n${failedApproaches.map((a, i) => `${i + 1}. ${a}`).join('\n')}]`;
112
+ }
113
+ if (Object.keys(checkpointState).length > 0) {
114
+ resumeContent += `\n\n[System: Known facts from previous runs:\n${Object.entries(checkpointState).map(([k, v]) => `- ${k}: ${v}`).join('\n')}]`;
115
+ }
116
+ session.messages.push({ role: 'user', content: resumeContent });
117
+ }
65
118
  } catch (e) {
66
119
  run = { status: 'error', response: e.message, logSummary: e.message, runToolCalls: [] };
67
120
  }