@saltcorn/agents 0.7.7 → 0.7.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/action.js +2 -1
- package/common.js +105 -76
- package/index.js +2 -2
- package/package.json +1 -1
- package/skills/ExternalSkill.js +38 -0
- package/skills/GenerateAndRunJsCode.js +31 -7
- package/skills/Subagent.js +1 -0
package/action.js
CHANGED
|
@@ -92,6 +92,7 @@ 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);
|
|
@@ -116,7 +117,7 @@ module.exports = {
|
|
|
116
117
|
run,
|
|
117
118
|
configuration,
|
|
118
119
|
req,
|
|
119
|
-
undefined,
|
|
120
|
+
agent_label || undefined,
|
|
120
121
|
[],
|
|
121
122
|
row,
|
|
122
123
|
agent_view_config || { stream: false },
|
package/common.js
CHANGED
|
@@ -40,6 +40,7 @@ const get_skills = () => {
|
|
|
40
40
|
require("./skills/Fetch"),
|
|
41
41
|
require("./skills/WebSearch"),
|
|
42
42
|
require("./skills/Subagent"),
|
|
43
|
+
require("./skills/ExternalSkill"),
|
|
43
44
|
//require("./skills/AdaptiveFeedback"),
|
|
44
45
|
...exchange_skills,
|
|
45
46
|
];
|
|
@@ -234,7 +235,7 @@ const process_interaction = async (
|
|
|
234
235
|
run,
|
|
235
236
|
config,
|
|
236
237
|
req,
|
|
237
|
-
agent_label = "
|
|
238
|
+
agent_label = "Agent",
|
|
238
239
|
prevResponses = [],
|
|
239
240
|
triggering_row = {},
|
|
240
241
|
agentsViewCfg = { stream: false },
|
|
@@ -245,16 +246,16 @@ const process_interaction = async (
|
|
|
245
246
|
const sysState = getState();
|
|
246
247
|
const complArgs = await getCompletionArguments(
|
|
247
248
|
config,
|
|
248
|
-
req
|
|
249
|
+
req?.user,
|
|
249
250
|
triggering_row,
|
|
250
|
-
req
|
|
251
|
+
req?.body,
|
|
251
252
|
);
|
|
252
253
|
complArgs.appendToChat = true;
|
|
253
254
|
complArgs.chat = run.context.interactions;
|
|
254
255
|
const use_alt_config = complArgs.alt_config;
|
|
255
256
|
//complArgs.debugResult = true;
|
|
256
257
|
//console.log("complArgs", JSON.stringify(complArgs, null, 2));
|
|
257
|
-
const debugMode = is_debug_mode(config, req
|
|
258
|
+
const debugMode = is_debug_mode(config, req?.user);
|
|
258
259
|
const debugCollector = {};
|
|
259
260
|
if (debugMode) complArgs.debugCollector = debugCollector;
|
|
260
261
|
if (stream && viewname) {
|
|
@@ -265,10 +266,11 @@ const process_interaction = async (
|
|
|
265
266
|
? response
|
|
266
267
|
: response.choices[0].content || response.choices[0].delta?.content;
|
|
267
268
|
if (content) {
|
|
268
|
-
const pageLoadTag = req
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
269
|
+
const pageLoadTag = req?.body?.page_load_tag;
|
|
270
|
+
if (pageLoadTag)
|
|
271
|
+
view.emitRealTimeEvent(`STREAM_CHUNK?page_load_tag=${pageLoadTag}`, {
|
|
272
|
+
content,
|
|
273
|
+
});
|
|
272
274
|
}
|
|
273
275
|
};
|
|
274
276
|
}
|
|
@@ -303,7 +305,7 @@ const process_interaction = async (
|
|
|
303
305
|
eval_js: `processCopilotResponse({response: ${JSON.stringify(resp)}, run_id: ${run.id}}, true)`,
|
|
304
306
|
page_load_tag: req?.headers?.["page-load-tag"],
|
|
305
307
|
},
|
|
306
|
-
[req
|
|
308
|
+
[req?.user?.id],
|
|
307
309
|
);
|
|
308
310
|
else responses.push(resp);
|
|
309
311
|
await addToContext(run, {
|
|
@@ -342,7 +344,7 @@ const process_interaction = async (
|
|
|
342
344
|
}
|
|
343
345
|
if (answer.content && !answer.tool_calls)
|
|
344
346
|
add_response(
|
|
345
|
-
req
|
|
347
|
+
req?.disable_markdown_render
|
|
346
348
|
? answer
|
|
347
349
|
: wrapSegment(md.render(answer.content), agent_label, false, layout),
|
|
348
350
|
);
|
|
@@ -355,7 +357,7 @@ const process_interaction = async (
|
|
|
355
357
|
) {
|
|
356
358
|
if (answer.content)
|
|
357
359
|
add_response(
|
|
358
|
-
req
|
|
360
|
+
req?.disable_markdown_render
|
|
359
361
|
? answer
|
|
360
362
|
: wrapSegment(md.render(answer.content), agent_label, false, layout),
|
|
361
363
|
);
|
|
@@ -383,14 +385,18 @@ const process_interaction = async (
|
|
|
383
385
|
(tool.skill.skill_label || tool.skill.constructor.skill_name) +
|
|
384
386
|
" ";
|
|
385
387
|
const view = View.findOne({ name: viewname });
|
|
386
|
-
const pageLoadTag = req
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
388
|
+
const pageLoadTag = req?.body?.page_load_tag;
|
|
389
|
+
if (pageLoadTag)
|
|
390
|
+
view.emitRealTimeEvent(
|
|
391
|
+
`STREAM_CHUNK?page_load_tag=${pageLoadTag}`,
|
|
392
|
+
{
|
|
393
|
+
content,
|
|
394
|
+
},
|
|
395
|
+
);
|
|
393
396
|
}
|
|
397
|
+
const response_label = is_sub_agent
|
|
398
|
+
? agent_label
|
|
399
|
+
: tool.skill.skill_label || tool.skill.constructor.skill_name;
|
|
394
400
|
if (tool.tool.renderToolCall) {
|
|
395
401
|
const row = tool_call.input;
|
|
396
402
|
|
|
@@ -400,10 +406,7 @@ const process_interaction = async (
|
|
|
400
406
|
if (rendered)
|
|
401
407
|
add_response(
|
|
402
408
|
wrapSegment(
|
|
403
|
-
wrapCard(
|
|
404
|
-
tool.skill.skill_label || tool.skill.constructor.skill_name,
|
|
405
|
-
rendered,
|
|
406
|
-
),
|
|
409
|
+
wrapCard(response_label, rendered),
|
|
407
410
|
agent_label,
|
|
408
411
|
false,
|
|
409
412
|
layout,
|
|
@@ -411,11 +414,11 @@ const process_interaction = async (
|
|
|
411
414
|
);
|
|
412
415
|
}
|
|
413
416
|
myHasResult = true;
|
|
414
|
-
|
|
417
|
+
let result = await tool.tool.process(tool_call.input, {
|
|
415
418
|
req,
|
|
416
|
-
});
|
|
419
|
+
});
|
|
417
420
|
toolResults[tool_call.tool_call_id] = result;
|
|
418
|
-
if (result
|
|
421
|
+
if (result?.stop) stop = true;
|
|
419
422
|
if (
|
|
420
423
|
(typeof result === "object" && Object.keys(result || {}).length) ||
|
|
421
424
|
typeof result === "string"
|
|
@@ -427,11 +430,7 @@ const process_interaction = async (
|
|
|
427
430
|
if (rendered)
|
|
428
431
|
add_response(
|
|
429
432
|
wrapSegment(
|
|
430
|
-
wrapCard(
|
|
431
|
-
tool.skill.skill_label ||
|
|
432
|
-
tool.skill.constructor.skill_name,
|
|
433
|
-
rendered,
|
|
434
|
-
),
|
|
433
|
+
wrapCard(response_label, rendered),
|
|
435
434
|
agent_label,
|
|
436
435
|
false,
|
|
437
436
|
layout,
|
|
@@ -474,14 +473,16 @@ const process_interaction = async (
|
|
|
474
473
|
myHasResult = false;
|
|
475
474
|
if (tool.tool.postProcess && !stop) {
|
|
476
475
|
let result = toolResults[tool_call.tool_call_id];
|
|
477
|
-
|
|
476
|
+
const response_label = is_sub_agent
|
|
477
|
+
? agent_label
|
|
478
|
+
: tool.skill.skill_label || tool.skill.constructor.skill_name;
|
|
478
479
|
const chat = run.context.interactions;
|
|
479
480
|
let generateUsed = false;
|
|
480
481
|
const systemPrompt = await getSystemPrompt(
|
|
481
482
|
config,
|
|
482
|
-
req
|
|
483
|
+
req?.user,
|
|
483
484
|
triggering_row,
|
|
484
|
-
req
|
|
485
|
+
req?.body,
|
|
485
486
|
);
|
|
486
487
|
const postprocres = await tool.tool.postProcess({
|
|
487
488
|
tool_call,
|
|
@@ -504,13 +505,14 @@ const process_interaction = async (
|
|
|
504
505
|
emit_update(s) {
|
|
505
506
|
if (!stream || !viewname) return;
|
|
506
507
|
const view = View.findOne({ name: viewname });
|
|
507
|
-
const pageLoadTag = req
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
508
|
+
const pageLoadTag = req?.body?.page_load_tag;
|
|
509
|
+
if (pageLoadTag)
|
|
510
|
+
view.emitRealTimeEvent(
|
|
511
|
+
`STREAM_CHUNK?page_load_tag=${pageLoadTag}`,
|
|
512
|
+
{
|
|
513
|
+
content: s + " ",
|
|
514
|
+
},
|
|
515
|
+
);
|
|
514
516
|
},
|
|
515
517
|
});
|
|
516
518
|
if (generateUsed)
|
|
@@ -532,48 +534,75 @@ const process_interaction = async (
|
|
|
532
534
|
}
|
|
533
535
|
|
|
534
536
|
for (const add_resp of postprocres.add_responses || []) {
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
537
|
+
const content =
|
|
538
|
+
add_resp.role && add_resp.content ? add_resp.content : add_resp;
|
|
539
|
+
raw_responses.push(content);
|
|
540
|
+
if (add_resp.md_response !== null) {
|
|
541
|
+
const renderedAddResponse = add_resp.md_response
|
|
542
|
+
? md.render(add_resp.md_response)
|
|
543
|
+
: typeof content === "string"
|
|
544
|
+
? md.render(content)
|
|
545
|
+
: content;
|
|
546
|
+
add_response(
|
|
547
|
+
wrapSegment(
|
|
548
|
+
wrapCard(response_label, renderedAddResponse),
|
|
549
|
+
agent_label,
|
|
550
|
+
false,
|
|
551
|
+
layout,
|
|
543
552
|
),
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
);
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
if (typeof add_resp.md_response !== "undefined")
|
|
556
|
+
delete add_resp.md_response;
|
|
549
557
|
|
|
550
|
-
const result =
|
|
551
|
-
await sysState.functions.llm_add_message.run(
|
|
552
|
-
"assistant",
|
|
558
|
+
const result = content;
|
|
553
559
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
560
|
+
if (add_resp.role && add_resp.content) {
|
|
561
|
+
await sysState.functions.llm_add_message.run(
|
|
562
|
+
add_resp.role,
|
|
563
|
+
add_resp.content,
|
|
564
|
+
{
|
|
565
|
+
chat: run.context.interactions,
|
|
566
|
+
},
|
|
567
|
+
);
|
|
568
|
+
} else
|
|
569
|
+
await sysState.functions.llm_add_message.run(
|
|
570
|
+
"assistant",
|
|
571
|
+
|
|
572
|
+
!result || typeof result === "string"
|
|
573
|
+
? result || "Action run"
|
|
574
|
+
: JSON.stringify(result),
|
|
575
|
+
|
|
576
|
+
{
|
|
577
|
+
chat: run.context.interactions,
|
|
578
|
+
},
|
|
579
|
+
);
|
|
557
580
|
|
|
558
|
-
{
|
|
559
|
-
chat: run.context.interactions,
|
|
560
|
-
},
|
|
561
|
-
);
|
|
562
581
|
await addToContext(run, {
|
|
563
582
|
interactions: run.context.interactions,
|
|
564
583
|
});
|
|
565
584
|
}
|
|
566
585
|
if (!postprocres.stop) {
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
586
|
+
const lastInteract =
|
|
587
|
+
run.context.interactions[run.context.interactions.length - 1];
|
|
588
|
+
|
|
589
|
+
if (
|
|
590
|
+
postprocres.follow_up_prompt ||
|
|
591
|
+
!(
|
|
592
|
+
lastInteract?.role === "user" || lastInteract?.role === "tool"
|
|
593
|
+
)
|
|
594
|
+
) {
|
|
595
|
+
await sysState.functions.llm_add_message.run(
|
|
596
|
+
"user",
|
|
597
|
+
postprocres.follow_up_prompt || "Continue with the query",
|
|
598
|
+
{
|
|
599
|
+
chat: run.context.interactions,
|
|
600
|
+
},
|
|
601
|
+
);
|
|
602
|
+
await addToContext(run, {
|
|
603
|
+
interactions: run.context.interactions,
|
|
604
|
+
});
|
|
605
|
+
}
|
|
577
606
|
myHasResult = true;
|
|
578
607
|
}
|
|
579
608
|
if (postprocres.add_user_action && viewname) {
|
|
@@ -620,18 +649,18 @@ const process_interaction = async (
|
|
|
620
649
|
);
|
|
621
650
|
} else if (typeof answer === "string")
|
|
622
651
|
add_response(
|
|
623
|
-
req
|
|
652
|
+
req?.disable_markdown_render
|
|
624
653
|
? answer
|
|
625
654
|
: wrapSegment(md.render(answer), agent_label, false, layout),
|
|
626
655
|
);
|
|
627
|
-
if (dyn_updates)
|
|
656
|
+
if (dyn_updates && !is_sub_agent)
|
|
628
657
|
getState().emitDynamicUpdate(
|
|
629
658
|
db.getTenantSchema(),
|
|
630
659
|
{
|
|
631
660
|
eval_js: `final_agent_response()`,
|
|
632
661
|
page_load_tag: req?.headers?.["page-load-tag"],
|
|
633
662
|
},
|
|
634
|
-
[req
|
|
663
|
+
[req?.user?.id],
|
|
635
664
|
);
|
|
636
665
|
|
|
637
666
|
return {
|
package/index.js
CHANGED
|
@@ -25,13 +25,13 @@ module.exports = {
|
|
|
25
25
|
script: `/plugins/public/agents@${
|
|
26
26
|
require("./package.json").version
|
|
27
27
|
}/markdown-it.min.js`,
|
|
28
|
-
onlyViews: ["Agent Chat"],
|
|
28
|
+
onlyViews: ["Agent Chat", "Saltcorn Agent copilot"],
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
script: `/plugins/public/agents@${
|
|
32
32
|
require("./package.json").version
|
|
33
33
|
}/jquery.autogrow-textarea.js`,
|
|
34
|
-
onlyViews: ["Agent Chat"],
|
|
34
|
+
onlyViews: ["Agent Chat", "Saltcorn Agent copilot"],
|
|
35
35
|
},
|
|
36
36
|
],
|
|
37
37
|
actions: {
|
package/package.json
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const fs = require("fs").promises;
|
|
3
|
+
|
|
4
|
+
class ExternalSkill {
|
|
5
|
+
static skill_name = "External Skill (SKILL.md)";
|
|
6
|
+
|
|
7
|
+
get skill_label() {
|
|
8
|
+
return "External Skill";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
constructor(cfg) {
|
|
12
|
+
Object.assign(this, cfg);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static async configFields() {
|
|
16
|
+
return [
|
|
17
|
+
{
|
|
18
|
+
name: "skills_dir",
|
|
19
|
+
label: "Skill directory",
|
|
20
|
+
type: "String",
|
|
21
|
+
required: true,
|
|
22
|
+
sublabel: "Path to the directory containing SKILL.md",
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async systemPrompt() {
|
|
28
|
+
if (!this.skills_dir) return;
|
|
29
|
+
const skillMdPath = path.join(this.skills_dir, "SKILL.md");
|
|
30
|
+
try {
|
|
31
|
+
return await fs.readFile(skillMdPath, "utf8");
|
|
32
|
+
} catch (e) {
|
|
33
|
+
return `[ExternalSkill: could not read ${skillMdPath}: ${e.message}]`;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = ExternalSkill;
|
|
@@ -215,13 +215,32 @@ Now generate the JavaScript code required by the user.`,
|
|
|
215
215
|
if (res !== undefined && res !== null && res !== "") return res;
|
|
216
216
|
return "Code executed successfully but returned no output.";
|
|
217
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;
|
|
218
233
|
try {
|
|
219
234
|
const res = await this.runCode(js_code, { user: req.user });
|
|
220
235
|
getState().log(6, "Code answer: " + JSON.stringify(res));
|
|
221
236
|
const effectiveRes = ensureResult(res);
|
|
222
237
|
return {
|
|
223
238
|
stop: typeof res === "string" && !this.follow_up_prompt,
|
|
224
|
-
add_response:
|
|
239
|
+
add_response: {
|
|
240
|
+
role: "user",
|
|
241
|
+
content: `The result of running the code is: ${effectiveRes}`,
|
|
242
|
+
md_response: mkMdResponse(effectiveRes, js_code),
|
|
243
|
+
},
|
|
225
244
|
...(this.follow_up_prompt
|
|
226
245
|
? { follow_up_prompt: this.follow_up_prompt }
|
|
227
246
|
: {}),
|
|
@@ -240,7 +259,7 @@ this code produced the following error:
|
|
|
240
259
|
${err.message}
|
|
241
260
|
\`\`\`
|
|
242
261
|
|
|
243
|
-
Correct this error
|
|
262
|
+
Correct this error and generate the new Javascript code to run
|
|
244
263
|
`);
|
|
245
264
|
try {
|
|
246
265
|
const res = await this.runCode(retry_js_code, {
|
|
@@ -250,7 +269,11 @@ Correct this error.
|
|
|
250
269
|
const effectiveRes = ensureResult(res);
|
|
251
270
|
return {
|
|
252
271
|
stop: typeof res === "string" && !this.follow_up_prompt,
|
|
253
|
-
add_response:
|
|
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
|
+
},
|
|
254
277
|
...(this.follow_up_prompt
|
|
255
278
|
? { follow_up_prompt: this.follow_up_prompt }
|
|
256
279
|
: {}),
|
|
@@ -284,10 +307,11 @@ const getTablePrompt = (read_only) => {
|
|
|
284
307
|
tables.forEach((table) => {
|
|
285
308
|
const fieldLines = table.fields.map(
|
|
286
309
|
(f) =>
|
|
287
|
-
` * ${f.name} with type: ${
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
310
|
+
` * ${f.name} with type: ${
|
|
311
|
+
f?.pretty_type
|
|
312
|
+
? f.pretty_type.replace("Key to", "ForeignKey referencing")
|
|
313
|
+
: "Unknown"
|
|
314
|
+
}.${f?.description ? ` ${f.description}` : ""}`,
|
|
291
315
|
);
|
|
292
316
|
tableLines.push(
|
|
293
317
|
`${table.name}${
|
package/skills/Subagent.js
CHANGED