@saltcorn/agents 0.7.6 → 0.7.8
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/action.js +18 -15
- package/agent-view.js +88 -4
- package/common.js +74 -49
- package/package.json +1 -1
- package/skills/GenerateAndRunJsCode.js +85 -14
- package/skills/Subagent.js +15 -9
- package/tests/action.test.js +14 -3
package/action.js
CHANGED
|
@@ -92,29 +92,32 @@ module.exports = {
|
|
|
92
92
|
is_sub_agent,
|
|
93
93
|
agent_view_config,
|
|
94
94
|
dyn_updates,
|
|
95
|
+
agent_label,
|
|
95
96
|
...rest
|
|
96
97
|
}) => {
|
|
97
98
|
const userinput = interpolate(configuration.prompt, row, user);
|
|
98
99
|
|
|
99
|
-
const run =
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
100
|
+
const run =
|
|
101
|
+
rest.run ||
|
|
102
|
+
(run_id
|
|
103
|
+
? await WorkflowRun.findOne({ id: run_id })
|
|
104
|
+
: await WorkflowRun.create({
|
|
105
|
+
status: "Running",
|
|
106
|
+
started_by: user?.id,
|
|
107
|
+
trigger_id: trigger_id || undefined,
|
|
108
|
+
context: {
|
|
109
|
+
implemented_fcall_ids: [],
|
|
110
|
+
interactions: [],
|
|
111
|
+
funcalls: {},
|
|
112
|
+
},
|
|
113
|
+
}));
|
|
114
|
+
|
|
115
|
+
run.context.interactions.push({ role: "user", content: userinput });
|
|
113
116
|
return await process_interaction(
|
|
114
117
|
run,
|
|
115
118
|
configuration,
|
|
116
119
|
req,
|
|
117
|
-
undefined,
|
|
120
|
+
agent_label || undefined,
|
|
118
121
|
[],
|
|
119
122
|
row,
|
|
120
123
|
agent_view_config || { stream: false },
|
package/agent-view.js
CHANGED
|
@@ -18,6 +18,7 @@ const {
|
|
|
18
18
|
input,
|
|
19
19
|
h4,
|
|
20
20
|
h3,
|
|
21
|
+
h2,
|
|
21
22
|
style,
|
|
22
23
|
h5,
|
|
23
24
|
button,
|
|
@@ -821,6 +822,21 @@ const run = async (
|
|
|
821
822
|
.modern-chat-layout .chat-user .chat-bubble table th {
|
|
822
823
|
background: rgba(255,255,255,0.1);
|
|
823
824
|
}
|
|
825
|
+
/* Skill attribution badge */
|
|
826
|
+
.modern-chat-layout .chat-bubble .badge.bg-info {
|
|
827
|
+
display: inline-block;
|
|
828
|
+
margin-bottom: 6px;
|
|
829
|
+
font-size: 0.7rem;
|
|
830
|
+
font-weight: 600;
|
|
831
|
+
letter-spacing: 0.3px;
|
|
832
|
+
text-transform: uppercase;
|
|
833
|
+
opacity: 0.85;
|
|
834
|
+
}
|
|
835
|
+
.modern-chat-layout .chat-bubble .card.bg-secondary-subtle {
|
|
836
|
+
border: none;
|
|
837
|
+
background-color: rgba(0,0,0,0.03) !important;
|
|
838
|
+
margin-bottom: 0.5rem;
|
|
839
|
+
}
|
|
824
840
|
/* Input area for modern chat */
|
|
825
841
|
.modern-chat-layout .copilot-entry {
|
|
826
842
|
border-top: 1px solid var(--tblr-border-color, var(--bs-border-color, #dee2e6));
|
|
@@ -1273,12 +1289,80 @@ const debug_info = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
1273
1289
|
);
|
|
1274
1290
|
sysPrompt = complArgs.systemPrompt;
|
|
1275
1291
|
}
|
|
1292
|
+
const apiJson = JSON.stringify(run.context.api_interactions, null, 2);
|
|
1276
1293
|
const debug_html = div(
|
|
1277
|
-
|
|
1294
|
+
{ class: "accordion", id: "debugAccordion" },
|
|
1278
1295
|
div(
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1296
|
+
{ class: "accordion-item" },
|
|
1297
|
+
h2(
|
|
1298
|
+
{ class: "accordion-header", id: "debugHeadPrompt" },
|
|
1299
|
+
button(
|
|
1300
|
+
{
|
|
1301
|
+
class: "accordion-button collapsed",
|
|
1302
|
+
type: "button",
|
|
1303
|
+
"data-bs-toggle": "collapse",
|
|
1304
|
+
"data-bs-target": "#debugCollapsePrompt",
|
|
1305
|
+
"aria-expanded": "false",
|
|
1306
|
+
"aria-controls": "debugCollapsePrompt",
|
|
1307
|
+
},
|
|
1308
|
+
"System prompt",
|
|
1309
|
+
),
|
|
1310
|
+
),
|
|
1311
|
+
div(
|
|
1312
|
+
{
|
|
1313
|
+
id: "debugCollapsePrompt",
|
|
1314
|
+
class: "accordion-collapse collapse",
|
|
1315
|
+
"aria-labelledby": "debugHeadPrompt",
|
|
1316
|
+
"data-bs-parent": "#debugAccordion",
|
|
1317
|
+
},
|
|
1318
|
+
div(
|
|
1319
|
+
{ class: "accordion-body" },
|
|
1320
|
+
pre({ style: "white-space:pre-wrap" }, text(escapeHtml(sysPrompt))),
|
|
1321
|
+
),
|
|
1322
|
+
),
|
|
1323
|
+
),
|
|
1324
|
+
div(
|
|
1325
|
+
{ class: "accordion-item" },
|
|
1326
|
+
h2(
|
|
1327
|
+
{ class: "accordion-header", id: "debugHeadAPI" },
|
|
1328
|
+
button(
|
|
1329
|
+
{
|
|
1330
|
+
class: "accordion-button",
|
|
1331
|
+
type: "button",
|
|
1332
|
+
"data-bs-toggle": "collapse",
|
|
1333
|
+
"data-bs-target": "#debugCollapseAPI",
|
|
1334
|
+
"aria-expanded": "true",
|
|
1335
|
+
"aria-controls": "debugCollapseAPI",
|
|
1336
|
+
},
|
|
1337
|
+
"API interactions",
|
|
1338
|
+
),
|
|
1339
|
+
),
|
|
1340
|
+
div(
|
|
1341
|
+
{
|
|
1342
|
+
id: "debugCollapseAPI",
|
|
1343
|
+
class: "accordion-collapse collapse show",
|
|
1344
|
+
"aria-labelledby": "debugHeadAPI",
|
|
1345
|
+
"data-bs-parent": "#debugAccordion",
|
|
1346
|
+
},
|
|
1347
|
+
div(
|
|
1348
|
+
{ class: "accordion-body" },
|
|
1349
|
+
button(
|
|
1350
|
+
{
|
|
1351
|
+
class: "btn btn-sm btn-outline-secondary mb-2",
|
|
1352
|
+
onclick: `
|
|
1353
|
+
var t=document.getElementById('debugApiPre').textContent;
|
|
1354
|
+
navigator.clipboard.writeText(t).then(function(){
|
|
1355
|
+
var b=event.target;b.textContent='Copied!';
|
|
1356
|
+
setTimeout(function(){b.textContent='Copy to clipboard'},1500)
|
|
1357
|
+
})`,
|
|
1358
|
+
},
|
|
1359
|
+
"Copy to clipboard",
|
|
1360
|
+
),
|
|
1361
|
+
pre(
|
|
1362
|
+
{ id: "debugApiPre", style: "white-space:pre-wrap" },
|
|
1363
|
+
text(escapeHtml(apiJson)),
|
|
1364
|
+
),
|
|
1365
|
+
),
|
|
1282
1366
|
),
|
|
1283
1367
|
),
|
|
1284
1368
|
);
|
package/common.js
CHANGED
|
@@ -234,7 +234,7 @@ const process_interaction = async (
|
|
|
234
234
|
run,
|
|
235
235
|
config,
|
|
236
236
|
req,
|
|
237
|
-
agent_label = "
|
|
237
|
+
agent_label = "Agent",
|
|
238
238
|
prevResponses = [],
|
|
239
239
|
triggering_row = {},
|
|
240
240
|
agentsViewCfg = { stream: false },
|
|
@@ -391,6 +391,9 @@ const process_interaction = async (
|
|
|
391
391
|
},
|
|
392
392
|
);
|
|
393
393
|
}
|
|
394
|
+
const response_label = is_sub_agent
|
|
395
|
+
? agent_label
|
|
396
|
+
: tool.skill.skill_label || tool.skill.constructor.skill_name;
|
|
394
397
|
if (tool.tool.renderToolCall) {
|
|
395
398
|
const row = tool_call.input;
|
|
396
399
|
|
|
@@ -400,10 +403,7 @@ const process_interaction = async (
|
|
|
400
403
|
if (rendered)
|
|
401
404
|
add_response(
|
|
402
405
|
wrapSegment(
|
|
403
|
-
wrapCard(
|
|
404
|
-
tool.skill.skill_label || tool.skill.constructor.skill_name,
|
|
405
|
-
rendered,
|
|
406
|
-
),
|
|
406
|
+
wrapCard(response_label, rendered),
|
|
407
407
|
agent_label,
|
|
408
408
|
false,
|
|
409
409
|
layout,
|
|
@@ -427,11 +427,7 @@ const process_interaction = async (
|
|
|
427
427
|
if (rendered)
|
|
428
428
|
add_response(
|
|
429
429
|
wrapSegment(
|
|
430
|
-
wrapCard(
|
|
431
|
-
tool.skill.skill_label ||
|
|
432
|
-
tool.skill.constructor.skill_name,
|
|
433
|
-
rendered,
|
|
434
|
-
),
|
|
430
|
+
wrapCard(response_label, rendered),
|
|
435
431
|
agent_label,
|
|
436
432
|
false,
|
|
437
433
|
layout,
|
|
@@ -473,8 +469,10 @@ const process_interaction = async (
|
|
|
473
469
|
let stop = false,
|
|
474
470
|
myHasResult = false;
|
|
475
471
|
if (tool.tool.postProcess && !stop) {
|
|
476
|
-
let result = toolResults[tool_call.tool_call_id];
|
|
477
|
-
|
|
472
|
+
let result = toolResults[tool_call.tool_call_id];
|
|
473
|
+
const response_label = is_sub_agent
|
|
474
|
+
? agent_label
|
|
475
|
+
: tool.skill.skill_label || tool.skill.constructor.skill_name;
|
|
478
476
|
const chat = run.context.interactions;
|
|
479
477
|
let generateUsed = false;
|
|
480
478
|
const systemPrompt = await getSystemPrompt(
|
|
@@ -515,7 +513,7 @@ const process_interaction = async (
|
|
|
515
513
|
});
|
|
516
514
|
if (generateUsed)
|
|
517
515
|
await addToContext(run, {
|
|
518
|
-
interactions:
|
|
516
|
+
interactions: run.context.interactions,
|
|
519
517
|
});
|
|
520
518
|
if (postprocres.stop) stop = true;
|
|
521
519
|
if (postprocres.add_system_prompt)
|
|
@@ -532,49 +530,76 @@ const process_interaction = async (
|
|
|
532
530
|
}
|
|
533
531
|
|
|
534
532
|
for (const add_resp of postprocres.add_responses || []) {
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
533
|
+
const content =
|
|
534
|
+
add_resp.role && add_resp.content ? add_resp.content : add_resp;
|
|
535
|
+
raw_responses.push(content);
|
|
536
|
+
if (add_resp.md_response !== null) {
|
|
537
|
+
const renderedAddResponse = add_resp.md_response
|
|
538
|
+
? md.render(add_resp.md_response)
|
|
539
|
+
: typeof content === "string"
|
|
540
|
+
? md.render(content)
|
|
541
|
+
: content;
|
|
542
|
+
add_response(
|
|
543
|
+
wrapSegment(
|
|
544
|
+
wrapCard(response_label, renderedAddResponse),
|
|
545
|
+
agent_label,
|
|
546
|
+
false,
|
|
547
|
+
layout,
|
|
543
548
|
),
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
await sysState.functions.llm_add_message.run(
|
|
553
|
-
"assistant",
|
|
554
|
-
!result || typeof result === "string"
|
|
555
|
-
? {
|
|
556
|
-
type: "text",
|
|
557
|
-
value: result || "Action run",
|
|
558
|
-
}
|
|
559
|
-
: {
|
|
560
|
-
type: "json",
|
|
561
|
-
value: JSON.parse(JSON.stringify(result)),
|
|
562
|
-
},
|
|
563
|
-
{
|
|
564
|
-
chat: run.context.interactions,
|
|
565
|
-
},
|
|
566
|
-
);
|
|
567
|
-
if (!postprocres.stop)
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
if (typeof add_resp.md_response !== "undefined")
|
|
552
|
+
delete add_resp.md_response;
|
|
553
|
+
|
|
554
|
+
const result = content;
|
|
555
|
+
|
|
556
|
+
if (add_resp.role && add_resp.content) {
|
|
568
557
|
await sysState.functions.llm_add_message.run(
|
|
569
|
-
|
|
558
|
+
add_resp.role,
|
|
559
|
+
add_resp.content,
|
|
570
560
|
{
|
|
571
|
-
|
|
572
|
-
value: "Continue",
|
|
561
|
+
chat: run.context.interactions,
|
|
573
562
|
},
|
|
563
|
+
);
|
|
564
|
+
} else
|
|
565
|
+
await sysState.functions.llm_add_message.run(
|
|
566
|
+
"assistant",
|
|
567
|
+
|
|
568
|
+
!result || typeof result === "string"
|
|
569
|
+
? result || "Action run"
|
|
570
|
+
: JSON.stringify(result),
|
|
571
|
+
|
|
574
572
|
{
|
|
575
573
|
chat: run.context.interactions,
|
|
576
574
|
},
|
|
577
575
|
);
|
|
576
|
+
|
|
577
|
+
await addToContext(run, {
|
|
578
|
+
interactions: run.context.interactions,
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
if (!postprocres.stop) {
|
|
582
|
+
const lastInteract =
|
|
583
|
+
run.context.interactions[run.context.interactions.length - 1];
|
|
584
|
+
|
|
585
|
+
if (
|
|
586
|
+
postprocres.follow_up_prompt ||
|
|
587
|
+
!(
|
|
588
|
+
lastInteract?.role === "user" || lastInteract?.role === "tool"
|
|
589
|
+
)
|
|
590
|
+
) {
|
|
591
|
+
await sysState.functions.llm_add_message.run(
|
|
592
|
+
"user",
|
|
593
|
+
postprocres.follow_up_prompt || "Continue with the query",
|
|
594
|
+
{
|
|
595
|
+
chat: run.context.interactions,
|
|
596
|
+
},
|
|
597
|
+
);
|
|
598
|
+
await addToContext(run, {
|
|
599
|
+
interactions: run.context.interactions,
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
myHasResult = true;
|
|
578
603
|
}
|
|
579
604
|
if (postprocres.add_user_action && viewname) {
|
|
580
605
|
const user_actions = Array.isArray()
|
|
@@ -624,7 +649,7 @@ const process_interaction = async (
|
|
|
624
649
|
? answer
|
|
625
650
|
: wrapSegment(md.render(answer), agent_label, false, layout),
|
|
626
651
|
);
|
|
627
|
-
if (dyn_updates)
|
|
652
|
+
if (dyn_updates && !is_sub_agent)
|
|
628
653
|
getState().emitDynamicUpdate(
|
|
629
654
|
db.getTenantSchema(),
|
|
630
655
|
{
|
package/package.json
CHANGED
|
@@ -18,6 +18,24 @@ const { validID } = require("@saltcorn/markup/layout_utils");
|
|
|
18
18
|
const vm = require("vm");
|
|
19
19
|
const { replaceUserContinue } = require("../common");
|
|
20
20
|
|
|
21
|
+
function extractCode(str) {
|
|
22
|
+
// Try ```javascript fence
|
|
23
|
+
if (str.includes("```javascript")) {
|
|
24
|
+
return str.split("```javascript")[1].split("```")[0];
|
|
25
|
+
}
|
|
26
|
+
// Try ```js fence
|
|
27
|
+
if (str.includes("```js\n") || str.includes("```js\r")) {
|
|
28
|
+
return str.split(/```js\s/)[1].split("```")[0];
|
|
29
|
+
}
|
|
30
|
+
// Try generic ``` fence (code is between first and second ```)
|
|
31
|
+
const fenceMatch = str.match(/```\s*\n([\s\S]*?)```/);
|
|
32
|
+
if (fenceMatch) {
|
|
33
|
+
return fenceMatch[1];
|
|
34
|
+
}
|
|
35
|
+
// No fences found - return raw string
|
|
36
|
+
return str;
|
|
37
|
+
}
|
|
38
|
+
|
|
21
39
|
//const { fieldProperties } = require("./helpers");
|
|
22
40
|
|
|
23
41
|
class GenerateAndRunJsCodeSkill {
|
|
@@ -105,6 +123,14 @@ class GenerateAndRunJsCodeSkill {
|
|
|
105
123
|
sublabel: "Allow calls to functions from codepages and modules",
|
|
106
124
|
type: "Bool",
|
|
107
125
|
},
|
|
126
|
+
{
|
|
127
|
+
name: "follow_up_prompt",
|
|
128
|
+
label: "Follow-up prompt",
|
|
129
|
+
sublabel:
|
|
130
|
+
"If set, the agent will continue processing after code execution with this prompt. Leave empty to stop after code result.",
|
|
131
|
+
type: "String",
|
|
132
|
+
fieldview: "textarea",
|
|
133
|
+
},
|
|
108
134
|
...(Table.subClass
|
|
109
135
|
? [
|
|
110
136
|
{
|
|
@@ -171,26 +197,53 @@ return { x, y }
|
|
|
171
197
|
|
|
172
198
|
${extra || ""}
|
|
173
199
|
|
|
200
|
+
CRITICAL: Your response must contain ONLY a single JavaScript code block wrapped in \`\`\`javascript ... \`\`\` fences. Do not include any text, explanation, or commentary before or after the code block.
|
|
201
|
+
|
|
174
202
|
Now generate the JavaScript code required by the user.`,
|
|
175
203
|
);
|
|
176
204
|
getState().log(
|
|
177
205
|
6,
|
|
178
206
|
"Generated code:\n--BEGIN CODE--\n" + str + "\n--END CODE--\n",
|
|
179
207
|
);
|
|
180
|
-
const js_code = str
|
|
181
|
-
? str.split("```javascript")[1].split("```")[0]
|
|
182
|
-
: str;
|
|
208
|
+
const js_code = extractCode(str);
|
|
183
209
|
return js_code;
|
|
184
210
|
};
|
|
185
211
|
const js_code = await gen_the_code();
|
|
186
212
|
emit_update("Running code");
|
|
213
|
+
const ensureResult = (res) => {
|
|
214
|
+
if (res && typeof res === "object") return JSON.stringify(res);
|
|
215
|
+
if (res !== undefined && res !== null && res !== "") return res;
|
|
216
|
+
return "Code executed successfully but returned no output.";
|
|
217
|
+
};
|
|
218
|
+
const mkMdResponse = (result, code) =>
|
|
219
|
+
req?.user?.role_id === 1
|
|
220
|
+
? `<details>
|
|
221
|
+
|
|
222
|
+
<summary>Show code</summary>
|
|
223
|
+
|
|
224
|
+
\`\`\`javascript
|
|
225
|
+
${code}
|
|
226
|
+
\`\`\`
|
|
227
|
+
|
|
228
|
+
⇒
|
|
229
|
+
</details>
|
|
230
|
+
|
|
231
|
+
${result}`
|
|
232
|
+
: result;
|
|
187
233
|
try {
|
|
188
234
|
const res = await this.runCode(js_code, { user: req.user });
|
|
189
|
-
//console.log("code response", res);
|
|
190
235
|
getState().log(6, "Code answer: " + JSON.stringify(res));
|
|
236
|
+
const effectiveRes = ensureResult(res);
|
|
191
237
|
return {
|
|
192
|
-
stop: typeof res === "string",
|
|
193
|
-
add_response:
|
|
238
|
+
stop: typeof res === "string" && !this.follow_up_prompt,
|
|
239
|
+
add_response: {
|
|
240
|
+
role: "user",
|
|
241
|
+
content: `The result of running the code is: ${effectiveRes}`,
|
|
242
|
+
md_response: mkMdResponse(effectiveRes, js_code),
|
|
243
|
+
},
|
|
244
|
+
...(this.follow_up_prompt
|
|
245
|
+
? { follow_up_prompt: this.follow_up_prompt }
|
|
246
|
+
: {}),
|
|
194
247
|
};
|
|
195
248
|
} catch (err) {
|
|
196
249
|
console.error(err);
|
|
@@ -206,15 +259,33 @@ this code produced the following error:
|
|
|
206
259
|
${err.message}
|
|
207
260
|
\`\`\`
|
|
208
261
|
|
|
209
|
-
Correct this error
|
|
262
|
+
Correct this error and generate the new Javascript code to run
|
|
210
263
|
`);
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
264
|
+
try {
|
|
265
|
+
const res = await this.runCode(retry_js_code, {
|
|
266
|
+
user: req.user,
|
|
267
|
+
});
|
|
268
|
+
getState().log(6, "Code retry answer: " + JSON.stringify(res));
|
|
269
|
+
const effectiveRes = ensureResult(res);
|
|
270
|
+
return {
|
|
271
|
+
stop: typeof res === "string" && !this.follow_up_prompt,
|
|
272
|
+
add_response: {
|
|
273
|
+
role: "user",
|
|
274
|
+
content: `The result of running the code is: ${effectiveRes}`,
|
|
275
|
+
md_response: mkMdResponse(effectiveRes, retry_js_code),
|
|
276
|
+
},
|
|
277
|
+
...(this.follow_up_prompt
|
|
278
|
+
? { follow_up_prompt: this.follow_up_prompt }
|
|
279
|
+
: {}),
|
|
280
|
+
};
|
|
281
|
+
} catch (retryErr) {
|
|
282
|
+
console.error(retryErr);
|
|
283
|
+
return {
|
|
284
|
+
add_response:
|
|
285
|
+
"Error: code generation failed after retry: " +
|
|
286
|
+
retryErr.message,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
218
289
|
}
|
|
219
290
|
},
|
|
220
291
|
function: {
|
package/skills/Subagent.js
CHANGED
|
@@ -52,6 +52,12 @@ class SubagentToSkill {
|
|
|
52
52
|
sublabel: `Optional. The prompt initialising the subagent. Example: "Continue answering my query using the tool now at you disposal"`,
|
|
53
53
|
type: "String",
|
|
54
54
|
},
|
|
55
|
+
{
|
|
56
|
+
name: "handoff_prompt",
|
|
57
|
+
label: "Handoff prompt",
|
|
58
|
+
sublabel: `Optional. A prompt to process the results of the subagent. Example: "Analyze this response in relation to my query"`,
|
|
59
|
+
type: "String",
|
|
60
|
+
},
|
|
55
61
|
];
|
|
56
62
|
}
|
|
57
63
|
|
|
@@ -91,21 +97,21 @@ class SubagentToSkill {
|
|
|
91
97
|
"Your instructions and tools have changed. Continue answering my query using the instructions and tools at you disposal, if any",
|
|
92
98
|
},
|
|
93
99
|
user: req.user,
|
|
94
|
-
|
|
100
|
+
run,
|
|
95
101
|
is_sub_agent: true,
|
|
96
102
|
agent_view_config,
|
|
97
103
|
dyn_updates,
|
|
98
104
|
req,
|
|
105
|
+
agent_label: this.agent_name,
|
|
99
106
|
});
|
|
100
|
-
getState().log(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
subres?.json?.raw_responses || "No response",
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
if (subres.json.raw_responses)
|
|
107
|
-
return { add_responses: subres.json.raw_responses };
|
|
107
|
+
getState().log(6, "Subagent response", JSON.stringify(subres, null, 2));
|
|
108
|
+
//if (subres.json.raw_responses)
|
|
109
|
+
// return { add_responses: subres.json.raw_responses };
|
|
108
110
|
return {
|
|
111
|
+
...(this.handoff_prompt
|
|
112
|
+
? { follow_up_prompt: this.handoff_prompt }
|
|
113
|
+
: { stop: true }),
|
|
114
|
+
|
|
109
115
|
//stop: true,
|
|
110
116
|
//add_response: result,
|
|
111
117
|
};
|
package/tests/action.test.js
CHANGED
|
@@ -38,7 +38,7 @@ beforeAll(async () => {
|
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
await getState().refresh_triggers(false);
|
|
41
|
-
|
|
41
|
+
await getState().setConfig("log_level", 6);
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
jest.setTimeout(40000);
|
|
@@ -46,6 +46,13 @@ jest.setTimeout(40000);
|
|
|
46
46
|
const user = { id: 1, role_id: 1 };
|
|
47
47
|
const action = require("../action");
|
|
48
48
|
|
|
49
|
+
const getLastInteraction = async ({ run_id }) => {
|
|
50
|
+
const run = await WorkflowRuns.findOne({ id: run_id });
|
|
51
|
+
return JSON.stringify(
|
|
52
|
+
run.context.interactions[run.context.interactions.length - 1],
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
49
56
|
for (const nameconfig of require("./configs")) {
|
|
50
57
|
const { name, ...config } = nameconfig;
|
|
51
58
|
describe("agent action with " + name, () => {
|
|
@@ -114,7 +121,10 @@ for (const nameconfig of require("./configs")) {
|
|
|
114
121
|
user,
|
|
115
122
|
req: { user },
|
|
116
123
|
});
|
|
117
|
-
|
|
124
|
+
|
|
125
|
+
const lastInteraction = await getLastInteraction(result.json);
|
|
126
|
+
|
|
127
|
+
expect(result.json.response || lastInteraction).toContain("987");
|
|
118
128
|
});
|
|
119
129
|
it("run multiple subagents concurrenty", async () => {
|
|
120
130
|
const configuration = { ...require("./agentcfg").agent1 };
|
|
@@ -134,7 +144,8 @@ for (const nameconfig of require("./configs")) {
|
|
|
134
144
|
user,
|
|
135
145
|
req: { user },
|
|
136
146
|
});
|
|
137
|
-
|
|
147
|
+
const lastInteraction = await getLastInteraction(result.json);
|
|
148
|
+
expect(lastInteraction).toContain("987");
|
|
138
149
|
});
|
|
139
150
|
});
|
|
140
151
|
|