@saltcorn/agents 0.3.5 → 0.4.0
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 +104 -7
- package/common.js +48 -12
- package/index.js +10 -2
- package/package.json +1 -1
- package/skills/PreloadData.js +1 -0
package/agent-view.js
CHANGED
|
@@ -17,6 +17,7 @@ const {
|
|
|
17
17
|
code,
|
|
18
18
|
input,
|
|
19
19
|
h4,
|
|
20
|
+
h3,
|
|
20
21
|
style,
|
|
21
22
|
h5,
|
|
22
23
|
button,
|
|
@@ -40,6 +41,7 @@ const {
|
|
|
40
41
|
wrapSegment,
|
|
41
42
|
process_interaction,
|
|
42
43
|
find_image_tool,
|
|
44
|
+
is_debug_mode,
|
|
43
45
|
} = require("./common");
|
|
44
46
|
const MarkdownIt = require("markdown-it"),
|
|
45
47
|
md = new MarkdownIt();
|
|
@@ -112,7 +114,16 @@ const configuration_workflow = (req) =>
|
|
|
112
114
|
],
|
|
113
115
|
});
|
|
114
116
|
|
|
115
|
-
const get_state_fields = () =>
|
|
117
|
+
const get_state_fields = async (table_id) =>
|
|
118
|
+
table_id
|
|
119
|
+
? [
|
|
120
|
+
{
|
|
121
|
+
name: "id",
|
|
122
|
+
type: "Integer",
|
|
123
|
+
primary_key: true,
|
|
124
|
+
},
|
|
125
|
+
]
|
|
126
|
+
: [];
|
|
116
127
|
|
|
117
128
|
const uploadForm = (viewname, req) =>
|
|
118
129
|
span(
|
|
@@ -152,6 +163,14 @@ const run = async (
|
|
|
152
163
|
const cfgMsg = incompleteCfgMsg();
|
|
153
164
|
if (cfgMsg) return cfgMsg;
|
|
154
165
|
let runInteractions = "";
|
|
166
|
+
let triggering_row_id;
|
|
167
|
+
if (table_id) {
|
|
168
|
+
const table = Table.findOne(table_id);
|
|
169
|
+
const pk = table?.pk_name;
|
|
170
|
+
if (table && state[pk])
|
|
171
|
+
//triggering_row = await table.getRow({ [pk]: state[pk] });
|
|
172
|
+
triggering_row_id = state[pk];
|
|
173
|
+
}
|
|
155
174
|
if (state.run_id) {
|
|
156
175
|
const run = prevRuns.find((r) => r.id == state.run_id);
|
|
157
176
|
const interactMarkups = [];
|
|
@@ -187,7 +206,6 @@ const run = async (
|
|
|
187
206
|
break;
|
|
188
207
|
case "assistant":
|
|
189
208
|
case "system":
|
|
190
|
-
|
|
191
209
|
for (const tool_call of interact.tool_calls || []) {
|
|
192
210
|
const toolSkill = find_tool(
|
|
193
211
|
tool_call.function?.name,
|
|
@@ -214,7 +232,6 @@ const run = async (
|
|
|
214
232
|
}
|
|
215
233
|
}
|
|
216
234
|
for (const image_call of interact.content?.image_calls || []) {
|
|
217
|
-
|
|
218
235
|
const toolSkill = find_image_tool(action.configuration);
|
|
219
236
|
if (toolSkill) {
|
|
220
237
|
if (toolSkill.tool.renderToolResponse) {
|
|
@@ -285,6 +302,7 @@ const run = async (
|
|
|
285
302
|
}
|
|
286
303
|
runInteractions = interactMarkups.join("");
|
|
287
304
|
}
|
|
305
|
+
const debugMode = is_debug_mode(action.configuration, req.user);
|
|
288
306
|
const input_form = form(
|
|
289
307
|
{
|
|
290
308
|
onsubmit: `event.preventDefault();spin_send_button();view_post('${viewname}', 'interact', new FormData(this), processCopilotResponse);return false;`,
|
|
@@ -302,6 +320,12 @@ const run = async (
|
|
|
302
320
|
name: "run_id",
|
|
303
321
|
value: state.run_id ? +state.run_id : undefined,
|
|
304
322
|
}),
|
|
323
|
+
input({
|
|
324
|
+
type: "hidden",
|
|
325
|
+
class: "form-control ",
|
|
326
|
+
name: "triggering_row_id",
|
|
327
|
+
value: triggering_row_id || "",
|
|
328
|
+
}),
|
|
305
329
|
div(
|
|
306
330
|
{ class: "copilot-entry" },
|
|
307
331
|
textarea({
|
|
@@ -318,6 +342,11 @@ const run = async (
|
|
|
318
342
|
i({ id: "sendbuttonicon", class: "far fa-paper-plane" })
|
|
319
343
|
),
|
|
320
344
|
image_upload && uploadForm(viewname, req),
|
|
345
|
+
debugMode &&
|
|
346
|
+
i({
|
|
347
|
+
onclick: "press_agent_debug_button()",
|
|
348
|
+
class: "debugicon fas fa-bug",
|
|
349
|
+
}),
|
|
321
350
|
explainer && small({ class: "explainer" }, i(explainer))
|
|
322
351
|
)
|
|
323
352
|
);
|
|
@@ -380,6 +409,12 @@ const run = async (
|
|
|
380
409
|
position: relative;
|
|
381
410
|
top: -1.8rem;
|
|
382
411
|
left: 0.1rem;
|
|
412
|
+
}
|
|
413
|
+
.copilot-entry .debugicon {
|
|
414
|
+
position: relative;
|
|
415
|
+
top: -1.8rem;
|
|
416
|
+
left: 0.1rem;
|
|
417
|
+
cursor: pointer;
|
|
383
418
|
}
|
|
384
419
|
.copilot-entry span.attach_agent_image_wrap {
|
|
385
420
|
position: relative;
|
|
@@ -425,6 +460,21 @@ const run = async (
|
|
|
425
460
|
btn.css({ width: "" }).prop("disabled", false);
|
|
426
461
|
btn.removeData("old-text");
|
|
427
462
|
}
|
|
463
|
+
function press_agent_debug_button() {
|
|
464
|
+
const $runidin= $("input[name=run_id")
|
|
465
|
+
const runid = $runidin.val()
|
|
466
|
+
if(runid)
|
|
467
|
+
view_post('${viewname}', 'debug_info', {run_id:runid, triggering_row_id:$("input[name=triggering_row_id").val()}, show_agent_debug_info)
|
|
468
|
+
}
|
|
469
|
+
function show_agent_debug_info(info) {
|
|
470
|
+
ensure_modal_exists_and_closed();
|
|
471
|
+
$("#scmodal .modal-body").html(info.debug_html);
|
|
472
|
+
$("#scmodal .modal-title").html(decodeURIComponent("Agent session information"));
|
|
473
|
+
$(".modal-dialog").css("min-width", "80%");
|
|
474
|
+
new bootstrap.Modal($("#scmodal"), {
|
|
475
|
+
focus: false,
|
|
476
|
+
}).show();
|
|
477
|
+
}
|
|
428
478
|
function delprevrun(e, runid) {
|
|
429
479
|
e.preventDefault();
|
|
430
480
|
e.stopPropagation();
|
|
@@ -479,8 +529,14 @@ const run = async (
|
|
|
479
529
|
};
|
|
480
530
|
|
|
481
531
|
const interact = async (table_id, viewname, config, body, { req, res }) => {
|
|
482
|
-
const { userinput, run_id } = body;
|
|
532
|
+
const { userinput, run_id, triggering_row_id } = body;
|
|
483
533
|
let run;
|
|
534
|
+
let triggering_row;
|
|
535
|
+
if (table_id && triggering_row_id) {
|
|
536
|
+
const table = Table.findOne(table_id);
|
|
537
|
+
const pk = table?.pk_name;
|
|
538
|
+
if (table) triggering_row = await table.getRow({ [pk]: triggering_row_id });
|
|
539
|
+
}
|
|
484
540
|
if (!run_id || run_id === "undefined")
|
|
485
541
|
run = await WorkflowRun.create({
|
|
486
542
|
status: "Running",
|
|
@@ -490,6 +546,7 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
490
546
|
implemented_fcall_ids: [],
|
|
491
547
|
interactions: [{ role: "user", content: userinput }],
|
|
492
548
|
funcalls: {},
|
|
549
|
+
triggering_row_id,
|
|
493
550
|
},
|
|
494
551
|
});
|
|
495
552
|
else {
|
|
@@ -535,7 +592,14 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
535
592
|
}
|
|
536
593
|
const action = await Trigger.findOne({ id: config.action_id });
|
|
537
594
|
|
|
538
|
-
return await process_interaction(
|
|
595
|
+
return await process_interaction(
|
|
596
|
+
run,
|
|
597
|
+
action.configuration,
|
|
598
|
+
req,
|
|
599
|
+
action.name,
|
|
600
|
+
[],
|
|
601
|
+
triggering_row
|
|
602
|
+
);
|
|
539
603
|
};
|
|
540
604
|
|
|
541
605
|
const delprevrun = async (table_id, viewname, config, body, { req, res }) => {
|
|
@@ -549,6 +613,38 @@ const delprevrun = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
549
613
|
return;
|
|
550
614
|
};
|
|
551
615
|
|
|
616
|
+
const debug_info = async (table_id, viewname, config, body, { req, res }) => {
|
|
617
|
+
const { run_id, triggering_row_id } = body;
|
|
618
|
+
const action = await Trigger.findOne({ id: config.action_id });
|
|
619
|
+
let triggering_row;
|
|
620
|
+
if (table_id && triggering_row_id) {
|
|
621
|
+
const table = Table.findOne(table_id);
|
|
622
|
+
const pk = table?.pk_name;
|
|
623
|
+
if (table) triggering_row = await table.getRow({ [pk]: triggering_row_id });
|
|
624
|
+
}
|
|
625
|
+
const run = await WorkflowRun.findOne({ id: +run_id });
|
|
626
|
+
const complArgs = await getCompletionArguments(
|
|
627
|
+
action.configuration,
|
|
628
|
+
req.user,
|
|
629
|
+
triggering_row
|
|
630
|
+
);
|
|
631
|
+
const debug_html = div(
|
|
632
|
+
div(h4("System prompt"), pre(complArgs.systemPrompt)),
|
|
633
|
+
div(
|
|
634
|
+
h4("API interactions"),
|
|
635
|
+
pre(JSON.stringify(run.context.api_interactions, null, 2))
|
|
636
|
+
)
|
|
637
|
+
);
|
|
638
|
+
if (run && req.user?.role_id === 1)
|
|
639
|
+
return {
|
|
640
|
+
json: {
|
|
641
|
+
success: "ok",
|
|
642
|
+
debug_html,
|
|
643
|
+
},
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
return;
|
|
647
|
+
};
|
|
552
648
|
const wrapAction = (
|
|
553
649
|
inner_markup,
|
|
554
650
|
viewname,
|
|
@@ -585,7 +681,8 @@ module.exports = {
|
|
|
585
681
|
configuration_workflow,
|
|
586
682
|
display_state_form: false,
|
|
587
683
|
get_state_fields,
|
|
588
|
-
tableless: true,
|
|
684
|
+
//tableless: true,
|
|
685
|
+
table_optional: true,
|
|
589
686
|
run,
|
|
590
|
-
routes: { interact, delprevrun },
|
|
687
|
+
routes: { interact, delprevrun, debug_info },
|
|
591
688
|
};
|
package/common.js
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
const { getState } = require("@saltcorn/data/db/state");
|
|
2
2
|
const { div, span } = require("@saltcorn/markup/tags");
|
|
3
3
|
const Trigger = require("@saltcorn/data/models/trigger");
|
|
4
|
+
const { interpolate } = require("@saltcorn/data/utils");
|
|
4
5
|
|
|
5
6
|
const MarkdownIt = require("markdown-it"),
|
|
6
7
|
md = new MarkdownIt();
|
|
7
8
|
|
|
9
|
+
const nubBy = (f, xs) => {
|
|
10
|
+
const vs = new Set();
|
|
11
|
+
return xs.filter((x) => {
|
|
12
|
+
const y = f(x);
|
|
13
|
+
if (vs.has(y)) return false;
|
|
14
|
+
vs.add(y);
|
|
15
|
+
return true;
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
|
|
8
19
|
const get_skills = () => {
|
|
20
|
+
const state = getState();
|
|
21
|
+
const exchange_skills = nubBy(
|
|
22
|
+
(c) => c.constructor.name,
|
|
23
|
+
state.exchange?.agent_skills || []
|
|
24
|
+
);
|
|
25
|
+
|
|
9
26
|
return [
|
|
10
27
|
require("./skills/FTSRetrieval"),
|
|
11
28
|
require("./skills/EmbeddingRetrieval"),
|
|
@@ -15,6 +32,7 @@ const get_skills = () => {
|
|
|
15
32
|
require("./skills/GenerateImage"),
|
|
16
33
|
require("./skills/ModelContextProtocol"),
|
|
17
34
|
//require("./skills/AdaptiveFeedback"),
|
|
35
|
+
...exchange_skills,
|
|
18
36
|
];
|
|
19
37
|
};
|
|
20
38
|
|
|
@@ -61,14 +79,16 @@ const find_image_tool = (config) => {
|
|
|
61
79
|
}
|
|
62
80
|
};
|
|
63
81
|
|
|
64
|
-
const getCompletionArguments = async (config, user) => {
|
|
82
|
+
const getCompletionArguments = async (config, user, triggering_row) => {
|
|
65
83
|
let tools = [];
|
|
66
84
|
|
|
67
|
-
let sysPrompts = [
|
|
85
|
+
let sysPrompts = [
|
|
86
|
+
interpolate(config.sys_prompt, triggering_row || {}, user, "System prompt"),
|
|
87
|
+
];
|
|
68
88
|
|
|
69
89
|
const skills = get_skill_instances(config);
|
|
70
90
|
for (const skill of skills) {
|
|
71
|
-
const sysPr = await skill.systemPrompt?.({ user });
|
|
91
|
+
const sysPr = await skill.systemPrompt?.({ user, triggering_row });
|
|
72
92
|
if (sysPr) sysPrompts.push(sysPr);
|
|
73
93
|
const skillTools = skill.provideTools?.();
|
|
74
94
|
if (skillTools && Array.isArray(skillTools)) tools.push(...skillTools);
|
|
@@ -156,21 +176,32 @@ const only_response_text_if_present = (interact) => {
|
|
|
156
176
|
return interact;
|
|
157
177
|
};
|
|
158
178
|
|
|
179
|
+
const is_debug_mode = (config, user) => user?.role_id === 1;
|
|
180
|
+
|
|
159
181
|
const process_interaction = async (
|
|
160
182
|
run,
|
|
161
183
|
config,
|
|
162
184
|
req,
|
|
163
185
|
agent_label = "Copilot",
|
|
164
|
-
prevResponses = []
|
|
186
|
+
prevResponses = [],
|
|
187
|
+
triggering_row = {}
|
|
165
188
|
) => {
|
|
166
|
-
const complArgs = await getCompletionArguments(
|
|
189
|
+
const complArgs = await getCompletionArguments(
|
|
190
|
+
config,
|
|
191
|
+
req.user,
|
|
192
|
+
triggering_row
|
|
193
|
+
);
|
|
167
194
|
complArgs.chat = run.context.interactions.map(only_response_text_if_present);
|
|
168
195
|
//complArgs.debugResult = true;
|
|
169
196
|
//console.log("complArgs", JSON.stringify(complArgs, null, 2));
|
|
170
|
-
|
|
197
|
+
const debugMode = is_debug_mode(config, req.user);
|
|
198
|
+
const debugCollector = {};
|
|
199
|
+
if (debugMode) complArgs.debugCollector = debugCollector;
|
|
171
200
|
const answer = await getState().functions.llm_generate.run("", complArgs);
|
|
172
|
-
|
|
173
|
-
|
|
201
|
+
if (debugMode)
|
|
202
|
+
await addToContext(run, {
|
|
203
|
+
api_interactions: [debugCollector],
|
|
204
|
+
});
|
|
174
205
|
const responses = [];
|
|
175
206
|
if (answer && typeof answer === "object" && answer.image_calls) {
|
|
176
207
|
for (const image_call of answer.image_calls) {
|
|
@@ -294,10 +325,14 @@ const process_interaction = async (
|
|
|
294
325
|
}
|
|
295
326
|
}
|
|
296
327
|
if (hasResult)
|
|
297
|
-
return await process_interaction(
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
328
|
+
return await process_interaction(
|
|
329
|
+
run,
|
|
330
|
+
config,
|
|
331
|
+
req,
|
|
332
|
+
agent_label,
|
|
333
|
+
[...prevResponses, ...responses],
|
|
334
|
+
triggering_row
|
|
335
|
+
);
|
|
301
336
|
} else if (typeof answer === "string")
|
|
302
337
|
responses.push(wrapSegment(md.render(answer), agent_label));
|
|
303
338
|
|
|
@@ -323,4 +358,5 @@ module.exports = {
|
|
|
323
358
|
wrapSegment,
|
|
324
359
|
process_interaction,
|
|
325
360
|
find_image_tool,
|
|
361
|
+
is_debug_mode,
|
|
326
362
|
};
|
package/index.js
CHANGED
|
@@ -51,7 +51,8 @@ module.exports = {
|
|
|
51
51
|
{
|
|
52
52
|
name: "sys_prompt",
|
|
53
53
|
label: "System prompt",
|
|
54
|
-
sublabel:
|
|
54
|
+
sublabel:
|
|
55
|
+
"Additional information for the system prompt. Use interpolations <code>{{ }}</code> to access triggering row variables or user",
|
|
55
56
|
type: "String",
|
|
56
57
|
fieldview: "textarea",
|
|
57
58
|
},
|
|
@@ -84,7 +85,14 @@ module.exports = {
|
|
|
84
85
|
funcalls: {},
|
|
85
86
|
},
|
|
86
87
|
});
|
|
87
|
-
return await process_interaction(
|
|
88
|
+
return await process_interaction(
|
|
89
|
+
run,
|
|
90
|
+
configuration,
|
|
91
|
+
req,
|
|
92
|
+
undefined,
|
|
93
|
+
[],
|
|
94
|
+
row
|
|
95
|
+
);
|
|
88
96
|
},
|
|
89
97
|
},
|
|
90
98
|
},
|
package/package.json
CHANGED