@ducci/jarvis 1.0.8 → 1.0.9
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 +2 -2
- package/src/server/agent.js +94 -52
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ducci/jarvis",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "A fully automated agent system that lives on a server.",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"setup": "node ./src/scripts/onboarding.js",
|
|
21
21
|
"dev": "nodemon ./src/server/app.js",
|
|
22
22
|
"prepare": "cd ui && npm install && npm run build",
|
|
23
|
-
"
|
|
23
|
+
"release": "node scripts/publish.js",
|
|
24
24
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
25
25
|
},
|
|
26
26
|
"keywords": [
|
package/src/server/agent.js
CHANGED
|
@@ -85,7 +85,20 @@ async function runAgentLoop(client, config, session, tools, toolDefs, prepareMes
|
|
|
85
85
|
status: 'model_error',
|
|
86
86
|
runToolCalls,
|
|
87
87
|
checkpoint: null,
|
|
88
|
-
errorDetail: e.apiErrors ?? { message: e.message },
|
|
88
|
+
errorDetail: e.apiErrors ?? { message: e.message, stack: e.stack },
|
|
89
|
+
contextInfo: { messageCount: preparedMessages.length },
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (!modelResult.choices || modelResult.choices.length === 0) {
|
|
94
|
+
return {
|
|
95
|
+
iteration,
|
|
96
|
+
response: 'Model returned an empty response.',
|
|
97
|
+
logSummary: `Model error on iteration ${iteration}: Empty choices array.`,
|
|
98
|
+
status: 'model_error',
|
|
99
|
+
runToolCalls,
|
|
100
|
+
checkpoint: null,
|
|
101
|
+
errorDetail: { message: 'Empty choices array from LLM' },
|
|
89
102
|
contextInfo: { messageCount: preparedMessages.length },
|
|
90
103
|
};
|
|
91
104
|
}
|
|
@@ -168,7 +181,20 @@ async function runAgentLoop(client, config, session, tools, toolDefs, prepareMes
|
|
|
168
181
|
status: 'model_error',
|
|
169
182
|
runToolCalls,
|
|
170
183
|
checkpoint: null,
|
|
171
|
-
errorDetail: e.apiErrors ?? { message: e.message },
|
|
184
|
+
errorDetail: e.apiErrors ?? { message: e.message, stack: e.stack },
|
|
185
|
+
contextInfo: { messageCount: wrapUpMessages.length },
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (!wrapUpResult.choices || wrapUpResult.choices.length === 0) {
|
|
190
|
+
return {
|
|
191
|
+
iteration,
|
|
192
|
+
response: 'Wrap-up call returned an empty response.',
|
|
193
|
+
logSummary: 'Iteration limit reached. Wrap-up returned empty choices.',
|
|
194
|
+
status: 'model_error',
|
|
195
|
+
runToolCalls,
|
|
196
|
+
checkpoint: null,
|
|
197
|
+
errorDetail: { message: 'Empty choices array in wrap-up' },
|
|
172
198
|
contextInfo: { messageCount: wrapUpMessages.length },
|
|
173
199
|
};
|
|
174
200
|
}
|
|
@@ -244,63 +270,79 @@ export async function handleChat(config, requestSessionId, userMessage) {
|
|
|
244
270
|
let finalStatus = 'ok';
|
|
245
271
|
|
|
246
272
|
// Handoff loop
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
273
|
+
try {
|
|
274
|
+
while (true) {
|
|
275
|
+
const run = await runAgentLoop(client, config, session, tools, toolDefs, prepareMessages);
|
|
276
|
+
allToolCalls.push(...run.runToolCalls);
|
|
277
|
+
|
|
278
|
+
if (run.status !== 'checkpoint_reached') {
|
|
279
|
+
finalResponse = run.response;
|
|
280
|
+
finalLogSummary = run.logSummary;
|
|
281
|
+
finalStatus = run.status;
|
|
282
|
+
|
|
283
|
+
const logEntry = {
|
|
284
|
+
iteration: run.iteration,
|
|
285
|
+
model: config.selectedModel,
|
|
286
|
+
userInput: userMessage,
|
|
287
|
+
toolCalls: allToolCalls,
|
|
288
|
+
response: finalResponse,
|
|
289
|
+
logSummary: finalLogSummary,
|
|
290
|
+
status: finalStatus,
|
|
291
|
+
};
|
|
292
|
+
if (run.errorDetail) logEntry.errorDetail = run.errorDetail;
|
|
293
|
+
if (run.contextInfo) logEntry.contextInfo = run.contextInfo;
|
|
294
|
+
if (run.rawResponse) logEntry.rawResponse = run.rawResponse;
|
|
295
|
+
appendLog(sessionId, logEntry);
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
255
298
|
|
|
256
|
-
|
|
299
|
+
// Checkpoint reached — log this run
|
|
300
|
+
appendLog(sessionId, {
|
|
257
301
|
iteration: run.iteration,
|
|
258
302
|
model: config.selectedModel,
|
|
259
303
|
userInput: userMessage,
|
|
260
|
-
toolCalls:
|
|
261
|
-
response:
|
|
262
|
-
logSummary:
|
|
263
|
-
status:
|
|
264
|
-
};
|
|
265
|
-
if (run.errorDetail) logEntry.errorDetail = run.errorDetail;
|
|
266
|
-
if (run.contextInfo) logEntry.contextInfo = run.contextInfo;
|
|
267
|
-
if (run.rawResponse) logEntry.rawResponse = run.rawResponse;
|
|
268
|
-
appendLog(sessionId, logEntry);
|
|
269
|
-
break;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Checkpoint reached — log this run
|
|
273
|
-
appendLog(sessionId, {
|
|
274
|
-
iteration: run.iteration,
|
|
275
|
-
model: config.selectedModel,
|
|
276
|
-
userInput: userMessage,
|
|
277
|
-
toolCalls: run.runToolCalls,
|
|
278
|
-
response: run.response,
|
|
279
|
-
logSummary: run.logSummary,
|
|
280
|
-
status: 'checkpoint_reached',
|
|
281
|
-
});
|
|
304
|
+
toolCalls: run.runToolCalls,
|
|
305
|
+
response: run.response,
|
|
306
|
+
logSummary: run.logSummary,
|
|
307
|
+
status: 'checkpoint_reached',
|
|
308
|
+
});
|
|
282
309
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
310
|
+
// Check handoff limit
|
|
311
|
+
session.metadata.handoffCount++;
|
|
312
|
+
if (session.metadata.handoffCount > config.maxHandoffs) {
|
|
313
|
+
finalResponse = run.response;
|
|
314
|
+
finalLogSummary = run.logSummary;
|
|
315
|
+
finalStatus = 'intervention_required';
|
|
316
|
+
|
|
317
|
+
appendLog(sessionId, {
|
|
318
|
+
iteration: 0,
|
|
319
|
+
model: config.selectedModel,
|
|
320
|
+
userInput: userMessage,
|
|
321
|
+
toolCalls: [],
|
|
322
|
+
response: finalResponse,
|
|
323
|
+
logSummary: 'Max handoffs exceeded. Human intervention required.',
|
|
324
|
+
status: 'intervention_required',
|
|
325
|
+
});
|
|
326
|
+
break;
|
|
327
|
+
}
|
|
289
328
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
model: config.selectedModel,
|
|
293
|
-
userInput: userMessage,
|
|
294
|
-
toolCalls: [],
|
|
295
|
-
response: finalResponse,
|
|
296
|
-
logSummary: 'Max handoffs exceeded. Human intervention required.',
|
|
297
|
-
status: 'intervention_required',
|
|
298
|
-
});
|
|
299
|
-
break;
|
|
329
|
+
// Resume with checkpoint.remaining as new prompt
|
|
330
|
+
session.messages.push({ role: 'user', content: run.checkpoint.remaining });
|
|
300
331
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
332
|
+
} catch (e) {
|
|
333
|
+
const errorLog = {
|
|
334
|
+
iteration: 0,
|
|
335
|
+
model: config.selectedModel,
|
|
336
|
+
userInput: userMessage,
|
|
337
|
+
toolCalls: allToolCalls,
|
|
338
|
+
response: `An unexpected server error occurred: ${e.message}`,
|
|
339
|
+
logSummary: `Critical error: ${e.message}`,
|
|
340
|
+
status: 'error',
|
|
341
|
+
errorDetail: { message: e.message, stack: e.stack },
|
|
342
|
+
};
|
|
343
|
+
appendLog(sessionId, errorLog);
|
|
344
|
+
// Re-throw to let app.js handle the HTTP response
|
|
345
|
+
throw e;
|
|
304
346
|
}
|
|
305
347
|
|
|
306
348
|
saveSession(sessionId, session);
|