@saltcorn/agents 0.6.3 → 0.6.5
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/agent-view.js +60 -21
- package/common.js +23 -6
- package/index.js +21 -0
- package/package.json +1 -1
package/agent-view.js
CHANGED
|
@@ -31,6 +31,7 @@ const {
|
|
|
31
31
|
label,
|
|
32
32
|
a,
|
|
33
33
|
br,
|
|
34
|
+
img,
|
|
34
35
|
} = require("@saltcorn/markup/tags");
|
|
35
36
|
const { getState } = require("@saltcorn/data/db/state");
|
|
36
37
|
const {
|
|
@@ -45,9 +46,12 @@ const {
|
|
|
45
46
|
is_debug_mode,
|
|
46
47
|
get_initial_interactions,
|
|
47
48
|
get_skill_instances,
|
|
49
|
+
saveInteractions,
|
|
48
50
|
} = require("./common");
|
|
49
51
|
const MarkdownIt = require("markdown-it"),
|
|
50
52
|
md = new MarkdownIt();
|
|
53
|
+
const { isWeb } = require("@saltcorn/data/utils");
|
|
54
|
+
const path = require("path");
|
|
51
55
|
|
|
52
56
|
const configuration_workflow = (req) =>
|
|
53
57
|
new Workflow({
|
|
@@ -223,6 +227,7 @@ const run = async (
|
|
|
223
227
|
viewname,
|
|
224
228
|
{
|
|
225
229
|
action_id,
|
|
230
|
+
agent_action,
|
|
226
231
|
show_prev_runs,
|
|
227
232
|
prev_runs_closed,
|
|
228
233
|
placeholder,
|
|
@@ -235,7 +240,7 @@ const run = async (
|
|
|
235
240
|
state,
|
|
236
241
|
{ res, req },
|
|
237
242
|
) => {
|
|
238
|
-
const action = await Trigger.findOne({ id: action_id });
|
|
243
|
+
const action = agent_action || await Trigger.findOne({ id: action_id });
|
|
239
244
|
if (!action) throw new Error(`Action not found: ${action_id}`);
|
|
240
245
|
const prevRuns = show_prev_runs
|
|
241
246
|
? (
|
|
@@ -271,6 +276,7 @@ const run = async (
|
|
|
271
276
|
interactMarkups.push(...run.context.html_interactions);
|
|
272
277
|
} else
|
|
273
278
|
for (const interact of run.context.interactions) {
|
|
279
|
+
//legacy
|
|
274
280
|
switch (interact.role) {
|
|
275
281
|
case "user":
|
|
276
282
|
if (interact.content?.[0]?.type === "image_url") {
|
|
@@ -485,7 +491,7 @@ const run = async (
|
|
|
485
491
|
? div(
|
|
486
492
|
div(
|
|
487
493
|
{
|
|
488
|
-
class: "d-flex justify-content-between align-middle mb-2",
|
|
494
|
+
class: "d-flex flex-wrap justify-content-between align-middle mb-2",
|
|
489
495
|
},
|
|
490
496
|
div(
|
|
491
497
|
{ class: "d-flex" },
|
|
@@ -498,7 +504,7 @@ const run = async (
|
|
|
498
504
|
button(
|
|
499
505
|
{
|
|
500
506
|
type: "button",
|
|
501
|
-
class: "btn btn-secondary btn-sm
|
|
507
|
+
class: "btn btn-secondary btn-sm pt-0 pb-1",
|
|
502
508
|
style: "font-size: 0.9em;height:1.5em",
|
|
503
509
|
onclick: "unset_state_field('run_id')",
|
|
504
510
|
title: "New session",
|
|
@@ -514,7 +520,10 @@ const run = async (
|
|
|
514
520
|
},
|
|
515
521
|
div(
|
|
516
522
|
{ class: "d-flex justify-content-between" },
|
|
517
|
-
|
|
523
|
+
span(
|
|
524
|
+
{ class: "text-truncate", style: "min-width:0" },
|
|
525
|
+
localeDateTime(run.started_at),
|
|
526
|
+
),
|
|
518
527
|
i({
|
|
519
528
|
class: "far fa-trash-alt",
|
|
520
529
|
onclick: `delprevrun(event, ${run.id})`,
|
|
@@ -550,7 +559,15 @@ const run = async (
|
|
|
550
559
|
`div.interaction-segment:not(:first-child) {border-top: 1px solid #e7e7e7; }
|
|
551
560
|
div.interaction-segment {padding-top: 5px;padding-bottom: 5px;}
|
|
552
561
|
div.interaction-segment p {margin-bottom: 0px;}
|
|
553
|
-
div.interaction-segment div.card {margin-top: 0.5rem;}
|
|
562
|
+
div.interaction-segment div.card {margin-top: 0.5rem;}
|
|
563
|
+
div.interaction-segment.to-right {
|
|
564
|
+
display: flex;
|
|
565
|
+
flex-direction: row-reverse;
|
|
566
|
+
}
|
|
567
|
+
div.interaction-segment.to-right div.badgewrap {
|
|
568
|
+
display: flex;
|
|
569
|
+
flex-direction: row-reverse;
|
|
570
|
+
}
|
|
554
571
|
div.prevcopilotrun:hover {cursor: pointer; background-color: var(--tblr-secondary-bg-subtle, var(--bs-secondary-bg-subtle, gray));}
|
|
555
572
|
div.prevcopilotrun i.fa-trash-alt {display: none;}
|
|
556
573
|
div.prevcopilotrun:hover i.fa-trash-alt {display: block;}
|
|
@@ -625,7 +642,7 @@ const run = async (
|
|
|
625
642
|
function get_run_id(elem) {
|
|
626
643
|
return $("input[name=run_id").val()
|
|
627
644
|
}
|
|
628
|
-
function processCopilotResponse(res) {
|
|
645
|
+
function processCopilotResponse(res, not_final) {
|
|
629
646
|
console.log("processCopilotResponse", res)
|
|
630
647
|
const fileInput = $("input#attach_agent_image")[0];
|
|
631
648
|
let fileBadge = "";
|
|
@@ -637,13 +654,13 @@ const run = async (
|
|
|
637
654
|
$("span.filename-label").text("").removeClass("me-2");
|
|
638
655
|
_agentDT.items.clear();
|
|
639
656
|
$("input#attach_agent_image").val(null);
|
|
640
|
-
$("#sendbuttonicon").attr("class","far fa-paper-plane");
|
|
657
|
+
if(!not_final || (!${JSON.stringify(dyn_updates)})) $("#sendbuttonicon").attr("class","far fa-paper-plane");
|
|
641
658
|
const $runidin= $("input[name=run_id")
|
|
642
659
|
if(res.run_id && (!$runidin.val() || $runidin.val()=="undefined"))
|
|
643
660
|
$runidin.val(res.run_id);
|
|
644
661
|
const wrapSegment = (html, who) => '<div class="interaction-segment"><span class="badge bg-secondary">'+who+'</span>'+html+'</div>'
|
|
645
662
|
const user_input = $("textarea[name=userinput]").val()
|
|
646
|
-
if(user_input)
|
|
663
|
+
if(user_input && (!${JSON.stringify(dyn_updates)}))
|
|
647
664
|
$("#copilotinteractions").append(wrapSegment('<p>'+user_input+'</p>'+fileBadge, "You"))
|
|
648
665
|
$("textarea[name=userinput]").val("")
|
|
649
666
|
$('form.agent-view div.next_response_scratch').html("")
|
|
@@ -652,6 +669,9 @@ const run = async (
|
|
|
652
669
|
$("#copilotinteractions").append(res.response)
|
|
653
670
|
}
|
|
654
671
|
window.processCopilotResponse = processCopilotResponse;
|
|
672
|
+
window.final_agent_response = () => {
|
|
673
|
+
$("#sendbuttonicon").attr("class","far fa-paper-plane");
|
|
674
|
+
}
|
|
655
675
|
const _agentDT = new DataTransfer();
|
|
656
676
|
function setAgentFiles(files) {
|
|
657
677
|
for (const f of files) _agentDT.items.add(f);
|
|
@@ -666,7 +686,11 @@ const run = async (
|
|
|
666
686
|
} else {
|
|
667
687
|
$label.addClass("me-2");
|
|
668
688
|
const text = n === 1 ? _agentDT.files[0].name : n + " files";
|
|
669
|
-
$label.html(
|
|
689
|
+
$label.html(${
|
|
690
|
+
isWeb(req)
|
|
691
|
+
? `text + ' <span class="badge text-bg-secondary" style="cursor:pointer;font-size:.65em;vertical-align:middle" onclick="clearAgentFiles()" title="Remove files">×</span>'`
|
|
692
|
+
: `'<span style="max-width:8em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-block;vertical-align:middle">' + text + '</span> <span class="badge text-bg-secondary" style="cursor:pointer;font-size:.65em;vertical-align:middle" onclick="clearAgentFiles()" title="Remove files">×</span>'`
|
|
693
|
+
});
|
|
670
694
|
}
|
|
671
695
|
}
|
|
672
696
|
function clearAgentFiles() {
|
|
@@ -796,7 +820,7 @@ const run = async (
|
|
|
796
820
|
|
|
797
821
|
const interact = async (table_id, viewname, config, body, { req, res }) => {
|
|
798
822
|
const { userinput, run_id, triggering_row_id } = body;
|
|
799
|
-
const action = await Trigger.findOne({ id: config.action_id });
|
|
823
|
+
const action = config.agent_action || await Trigger.findOne({ id: config.action_id });
|
|
800
824
|
|
|
801
825
|
let run;
|
|
802
826
|
let triggering_row;
|
|
@@ -839,9 +863,13 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
839
863
|
100,
|
|
840
864
|
);
|
|
841
865
|
badges.push(
|
|
842
|
-
|
|
843
|
-
{ class: "
|
|
844
|
-
|
|
866
|
+
div(
|
|
867
|
+
{ class: "bg-secondary-subtle p-2 m-2 rounded-2" },
|
|
868
|
+
img({
|
|
869
|
+
src: `/files/resize/${50}/${50}/${file.path_to_serve}`,
|
|
870
|
+
class: "d-block",
|
|
871
|
+
onclick: `expand_thumbnail('${file.path_to_serve}', '${path.basename(file.path_to_serve)}')`,
|
|
872
|
+
}),
|
|
845
873
|
file.filename,
|
|
846
874
|
),
|
|
847
875
|
);
|
|
@@ -860,20 +888,30 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
860
888
|
await getState().functions.llm_add_message.run("image", imageurl, {
|
|
861
889
|
chat: run.context.interactions || [],
|
|
862
890
|
});
|
|
863
|
-
await addToContext(run, {
|
|
864
|
-
interactions: run.context.interactions || [],
|
|
865
|
-
});
|
|
866
891
|
}
|
|
867
|
-
|
|
892
|
+
await saveInteractions(run);
|
|
893
|
+
fileBadges = div({ class: "d-flex" }, badges);
|
|
868
894
|
}
|
|
895
|
+
const userInteractions = wrapSegment(p(userinput) + fileBadges, "You", true);
|
|
896
|
+
|
|
869
897
|
await addToContext(run, {
|
|
870
898
|
interactions: [
|
|
871
899
|
...(run.context.interactions || []),
|
|
872
900
|
{ role: "user", content: userinput },
|
|
873
901
|
],
|
|
874
|
-
html_interactions: [
|
|
902
|
+
html_interactions: [userInteractions],
|
|
875
903
|
});
|
|
876
904
|
const dyn_updates = getState().getConfig("enable_dynamic_updates", true);
|
|
905
|
+
if (dyn_updates) {
|
|
906
|
+
getState().emitDynamicUpdate(
|
|
907
|
+
db.getTenantSchema(),
|
|
908
|
+
{
|
|
909
|
+
eval_js: `processCopilotResponse({response: ${JSON.stringify(userInteractions)}, run_id: ${run.id}}, true)`,
|
|
910
|
+
page_load_tag: req?.headers?.["page-load-tag"],
|
|
911
|
+
},
|
|
912
|
+
[req.user.id],
|
|
913
|
+
);
|
|
914
|
+
}
|
|
877
915
|
const process_promise = process_interaction(
|
|
878
916
|
run,
|
|
879
917
|
action.configuration,
|
|
@@ -913,7 +951,7 @@ const delprevrun = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
913
951
|
|
|
914
952
|
const debug_info = async (table_id, viewname, config, body, { req, res }) => {
|
|
915
953
|
const { run_id, triggering_row_id } = body;
|
|
916
|
-
const action = await Trigger.findOne({ id: config.action_id });
|
|
954
|
+
const action = config.agent_action || await Trigger.findOne({ id: config.action_id });
|
|
917
955
|
let triggering_row;
|
|
918
956
|
if (table_id && triggering_row_id) {
|
|
919
957
|
const table = Table.findOne(table_id);
|
|
@@ -955,7 +993,7 @@ const debug_info = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
955
993
|
|
|
956
994
|
const skillroute = async (table_id, viewname, config, body, { req, res }) => {
|
|
957
995
|
const { run_id, triggering_row_id, skillid } = body;
|
|
958
|
-
const action = await Trigger.findOne({ id: config.action_id });
|
|
996
|
+
const action = config.agent_action || await Trigger.findOne({ id: config.action_id });
|
|
959
997
|
let triggering_row;
|
|
960
998
|
if (table_id && triggering_row_id) {
|
|
961
999
|
const table = Table.findOne(table_id);
|
|
@@ -992,7 +1030,7 @@ const execute_user_action = async (
|
|
|
992
1030
|
) => {
|
|
993
1031
|
const { run_id, rndid, uaname } = body;
|
|
994
1032
|
|
|
995
|
-
const action = await Trigger.findOne({ id: config.action_id });
|
|
1033
|
+
const action = config.agent_action || await Trigger.findOne({ id: config.action_id });
|
|
996
1034
|
const run = await WorkflowRun.findOne({ id: +run_id });
|
|
997
1035
|
//console.log("run uas",run.context.user_actions );
|
|
998
1036
|
|
|
@@ -1028,4 +1066,5 @@ module.exports = {
|
|
|
1028
1066
|
table_optional: true,
|
|
1029
1067
|
run,
|
|
1030
1068
|
routes: { interact, delprevrun, debug_info, skillroute, execute_user_action },
|
|
1069
|
+
mobile_render_server_side: true,
|
|
1031
1070
|
};
|
package/common.js
CHANGED
|
@@ -166,14 +166,20 @@ const addToContext = async (run, newCtx) => {
|
|
|
166
166
|
if (changed && run.update) await run.update({ context: run.context });
|
|
167
167
|
};
|
|
168
168
|
|
|
169
|
-
const
|
|
169
|
+
const saveInteractions = async (run) => {
|
|
170
|
+
await addToContext(run, {
|
|
171
|
+
interactions: run.context.interactions || [],
|
|
172
|
+
});
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const wrapSegment = (html, who, to_right) =>
|
|
170
176
|
who === null
|
|
171
177
|
? html
|
|
172
|
-
:
|
|
178
|
+
: `<div class="interaction-segment ${to_right ? "to-right" : ""}"><div><div class="badgewrap"><span class="badge bg-secondary">` +
|
|
173
179
|
who +
|
|
174
|
-
"</span>" +
|
|
180
|
+
"</span></div>" +
|
|
175
181
|
html +
|
|
176
|
-
"</div>";
|
|
182
|
+
"</div></div>";
|
|
177
183
|
|
|
178
184
|
const wrapCard = (title, ...inners) =>
|
|
179
185
|
span({ class: "badge bg-info ms-1" }, title) +
|
|
@@ -236,12 +242,13 @@ const process_interaction = async (
|
|
|
236
242
|
interactions: complArgs.chat,
|
|
237
243
|
});
|
|
238
244
|
const responses = [];
|
|
239
|
-
|
|
245
|
+
|
|
246
|
+
const add_response = async (resp, not_final) => {
|
|
240
247
|
if (dyn_updates)
|
|
241
248
|
getState().emitDynamicUpdate(
|
|
242
249
|
db.getTenantSchema(),
|
|
243
250
|
{
|
|
244
|
-
eval_js: `processCopilotResponse({response: ${JSON.stringify(resp)}, run_id: ${run.id}})`,
|
|
251
|
+
eval_js: `processCopilotResponse({response: ${JSON.stringify(resp)}, run_id: ${run.id}}, true)`,
|
|
245
252
|
page_load_tag: req?.headers?.["page-load-tag"],
|
|
246
253
|
},
|
|
247
254
|
[req.user.id],
|
|
@@ -479,6 +486,15 @@ const process_interaction = async (
|
|
|
479
486
|
? answer
|
|
480
487
|
: wrapSegment(md.render(answer), agent_label),
|
|
481
488
|
);
|
|
489
|
+
if (dyn_updates)
|
|
490
|
+
getState().emitDynamicUpdate(
|
|
491
|
+
db.getTenantSchema(),
|
|
492
|
+
{
|
|
493
|
+
eval_js: `final_agent_response()`,
|
|
494
|
+
page_load_tag: req?.headers?.["page-load-tag"],
|
|
495
|
+
},
|
|
496
|
+
[req.user.id],
|
|
497
|
+
);
|
|
482
498
|
|
|
483
499
|
return {
|
|
484
500
|
json: {
|
|
@@ -497,6 +513,7 @@ module.exports = {
|
|
|
497
513
|
get_skill_instances,
|
|
498
514
|
getCompletionArguments,
|
|
499
515
|
addToContext,
|
|
516
|
+
saveInteractions,
|
|
500
517
|
wrapCard,
|
|
501
518
|
wrapSegment,
|
|
502
519
|
process_interaction,
|
package/index.js
CHANGED
|
@@ -18,6 +18,7 @@ module.exports = {
|
|
|
18
18
|
dependencies: ["@saltcorn/large-language-model"],
|
|
19
19
|
viewtemplates: [require("./agent-view")],
|
|
20
20
|
plugin_name: "agents",
|
|
21
|
+
ready_for_mobile: true,
|
|
21
22
|
headers: [
|
|
22
23
|
{
|
|
23
24
|
script: `/plugins/public/agents@${
|
|
@@ -36,6 +37,26 @@ module.exports = {
|
|
|
36
37
|
Agent: require("./action"),
|
|
37
38
|
},
|
|
38
39
|
functions: {
|
|
40
|
+
inspect_agent: {
|
|
41
|
+
run: async (agent, user, row) => {
|
|
42
|
+
const action = agent.runWithoutRow
|
|
43
|
+
? agent
|
|
44
|
+
: await Trigger.findOne(
|
|
45
|
+
typeof agent == "number" ? { id: agent } : { name: agent },
|
|
46
|
+
);
|
|
47
|
+
const complArgs = await getCompletionArguments(
|
|
48
|
+
action.configuration,
|
|
49
|
+
user,
|
|
50
|
+
row,
|
|
51
|
+
);
|
|
52
|
+
return {
|
|
53
|
+
...complArgs,
|
|
54
|
+
action,
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
isAsync: true,
|
|
58
|
+
description: "Return system prompt, tools and action of an agent",
|
|
59
|
+
},
|
|
39
60
|
agent_generate: {
|
|
40
61
|
run: async (agent_name, prompt, opts = {}) => {
|
|
41
62
|
const action = await Trigger.findOne({ name: agent_name });
|