@saltcorn/agents 0.7.14 → 0.7.16
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 +74 -18
- package/common.js +12 -4
- package/locales/de.json +1 -1
- package/package.json +1 -1
- package/skills/PlanApproval.js +3 -3
package/agent-view.js
CHANGED
|
@@ -133,6 +133,12 @@ const configuration_workflow = (req) =>
|
|
|
133
133
|
},
|
|
134
134
|
]
|
|
135
135
|
: []),
|
|
136
|
+
{
|
|
137
|
+
name: "shared",
|
|
138
|
+
label: "Shared runs",
|
|
139
|
+
sublabel: "Users can open runs created by other users",
|
|
140
|
+
type: "Bool",
|
|
141
|
+
},
|
|
136
142
|
{
|
|
137
143
|
name: "layout",
|
|
138
144
|
label: "Layout",
|
|
@@ -267,16 +273,31 @@ const run = async (
|
|
|
267
273
|
stream,
|
|
268
274
|
audio_recorder,
|
|
269
275
|
layout,
|
|
276
|
+
shared,
|
|
270
277
|
},
|
|
271
278
|
state,
|
|
272
279
|
{ res, req },
|
|
273
280
|
) => {
|
|
274
281
|
const action = agent_action || (await Trigger.findOne({ id: action_id }));
|
|
275
282
|
if (!action) throw new Error(`Action not found: ${action_id}`);
|
|
283
|
+
let triggering_row_id;
|
|
284
|
+
if (table_id) {
|
|
285
|
+
const table = Table.findOne(table_id);
|
|
286
|
+
const pk = table?.pk_name;
|
|
287
|
+
if (table && state[pk])
|
|
288
|
+
//triggering_row = await table.getRow({ [pk]: state[pk] });
|
|
289
|
+
triggering_row_id = state[pk];
|
|
290
|
+
}
|
|
276
291
|
const prevRuns = show_prev_runs
|
|
277
292
|
? (
|
|
278
293
|
await WorkflowRun.find(
|
|
279
|
-
{
|
|
294
|
+
{
|
|
295
|
+
trigger_id: action.id,
|
|
296
|
+
...(shared ? {} : { started_by: req.user?.id }),
|
|
297
|
+
...(triggering_row_id
|
|
298
|
+
? { context: { json: ["triggering_row_id", triggering_row_id] } }
|
|
299
|
+
: {}),
|
|
300
|
+
},
|
|
280
301
|
{ orderBy: "started_at", orderDesc: true, limit: 30 },
|
|
281
302
|
)
|
|
282
303
|
).filter((r) => r.context.interactions)
|
|
@@ -285,21 +306,14 @@ const run = async (
|
|
|
285
306
|
const cfgMsg = incompleteCfgMsg();
|
|
286
307
|
if (cfgMsg) return cfgMsg;
|
|
287
308
|
let runInteractions = "";
|
|
288
|
-
|
|
289
|
-
if (table_id) {
|
|
290
|
-
const table = Table.findOne(table_id);
|
|
291
|
-
const pk = table?.pk_name;
|
|
292
|
-
if (table && state[pk])
|
|
293
|
-
//triggering_row = await table.getRow({ [pk]: state[pk] });
|
|
294
|
-
triggering_row_id = state[pk];
|
|
295
|
-
}
|
|
309
|
+
|
|
296
310
|
const initial_q = state.run_id ? undefined : state._q;
|
|
297
311
|
if (state.run_id) {
|
|
298
312
|
const run = prevRuns
|
|
299
313
|
? prevRuns.find((r) => r.id == state.run_id)
|
|
300
314
|
: await WorkflowRun.findOne({
|
|
301
315
|
trigger_id: action.id,
|
|
302
|
-
started_by: req.user?.id,
|
|
316
|
+
...(shared ? {} : { started_by: req.user?.id }),
|
|
303
317
|
id: state.run_id,
|
|
304
318
|
});
|
|
305
319
|
const interactMarkups = [];
|
|
@@ -509,6 +523,15 @@ const run = async (
|
|
|
509
523
|
{ id: "audioinputicon", class: "", onclick: "" },
|
|
510
524
|
i({ class: "fas fa-microphone" }),
|
|
511
525
|
),
|
|
526
|
+
button(
|
|
527
|
+
{
|
|
528
|
+
type: "button",
|
|
529
|
+
class: "btn btn-xs btn-sm btn-outline-secondary cancelbtn ms-2",
|
|
530
|
+
onclick: "press_cancel_button()",
|
|
531
|
+
style: { display: "none" },
|
|
532
|
+
},
|
|
533
|
+
i({ class: "fas fa-stop" }),
|
|
534
|
+
),
|
|
512
535
|
explainer && small({ class: "explainer" }, i(explainer)),
|
|
513
536
|
),
|
|
514
537
|
stream && realTimeCollabScript(viewname, rndid, layout),
|
|
@@ -534,7 +557,7 @@ const run = async (
|
|
|
534
557
|
{
|
|
535
558
|
type: "button",
|
|
536
559
|
class: "btn btn-primary btn-sm rounded-pill px-3",
|
|
537
|
-
onclick: "unset_state_field('run_id')",
|
|
560
|
+
onclick: "unset_state_field('run_id', this)",
|
|
538
561
|
title: "New chat",
|
|
539
562
|
},
|
|
540
563
|
i({ class: "fas fa-plus me-1" }),
|
|
@@ -559,7 +582,7 @@ const run = async (
|
|
|
559
582
|
type: "button",
|
|
560
583
|
class: "btn btn-secondary btn-sm pt-0 pb-1",
|
|
561
584
|
style: "font-size: 0.9em;height:1.5em",
|
|
562
|
-
onclick: "unset_state_field('run_id')",
|
|
585
|
+
onclick: "unset_state_field('run_id', this)",
|
|
563
586
|
title: "New session",
|
|
564
587
|
},
|
|
565
588
|
i({ class: "fas fa-redo fa-sm" }),
|
|
@@ -575,7 +598,7 @@ const run = async (
|
|
|
575
598
|
return isModernSidebar
|
|
576
599
|
? div(
|
|
577
600
|
{
|
|
578
|
-
onclick: `set_state_field('run_id',${run.id})`,
|
|
601
|
+
onclick: `set_state_field('run_id',${run.id}, this)`,
|
|
579
602
|
class:
|
|
580
603
|
"prevcopilotrun modern-session-item" +
|
|
581
604
|
(isActive ? " active-session" : ""),
|
|
@@ -598,7 +621,7 @@ const run = async (
|
|
|
598
621
|
)
|
|
599
622
|
: div(
|
|
600
623
|
{
|
|
601
|
-
onclick: `set_state_field('run_id',${run.id})`,
|
|
624
|
+
onclick: `set_state_field('run_id',${run.id}, this)`,
|
|
602
625
|
class: "prevcopilotrun border p-2",
|
|
603
626
|
},
|
|
604
627
|
div(
|
|
@@ -670,6 +693,12 @@ const run = async (
|
|
|
670
693
|
left: 0.1rem;
|
|
671
694
|
cursor: pointer;
|
|
672
695
|
}
|
|
696
|
+
.copilot-entry .cancelbtn {
|
|
697
|
+
position: relative;
|
|
698
|
+
top: -1.8rem;
|
|
699
|
+
left: 0.1rem;
|
|
700
|
+
cursor: pointer;
|
|
701
|
+
}
|
|
673
702
|
.copilot-entry .skill-form-widget {
|
|
674
703
|
position: relative;
|
|
675
704
|
top: -2rem;
|
|
@@ -957,7 +986,10 @@ const run = async (
|
|
|
957
986
|
$("span.filename-label").text("").removeClass("me-2");
|
|
958
987
|
window._agentDT.items.clear();
|
|
959
988
|
$("input#attach_agent_image").val(null);
|
|
960
|
-
if(!not_final || (!${JSON.stringify(dyn_updates)}))
|
|
989
|
+
if(!not_final || (!${JSON.stringify(dyn_updates)})) {
|
|
990
|
+
$("#sendbuttonicon").attr("class","far fa-paper-plane");
|
|
991
|
+
$(".cancelbtn").hide();
|
|
992
|
+
}
|
|
961
993
|
const $runidin= $("input[name=run_id")
|
|
962
994
|
if(res.run_id && (!$runidin.val() || $runidin.val()=="undefined"))
|
|
963
995
|
$runidin.val(res.run_id);
|
|
@@ -983,6 +1015,7 @@ const run = async (
|
|
|
983
1015
|
$(".agent-waiting-indicator").remove();
|
|
984
1016
|
$("textarea[name=userinput]").prop("disabled", false).attr("placeholder", ${JSON.stringify(placeholder || "How can I help you?")}).focus();
|
|
985
1017
|
$(".copilot-entry .submit-button").css("pointer-events", "");
|
|
1018
|
+
$(".cancelbtn").hide();
|
|
986
1019
|
scrollAgentToBottom();
|
|
987
1020
|
}
|
|
988
1021
|
window._agentDT = new DataTransfer();
|
|
@@ -1028,6 +1061,12 @@ const run = async (
|
|
|
1028
1061
|
if(runid)
|
|
1029
1062
|
view_post('${viewname}', 'debug_info', {run_id:runid, triggering_row_id:$("input[name=triggering_row_id").val()}, show_agent_debug_info)
|
|
1030
1063
|
}
|
|
1064
|
+
function press_cancel_button() {
|
|
1065
|
+
const $runidin= $("input[name=run_id")
|
|
1066
|
+
const runid = $runidin.val()
|
|
1067
|
+
if(runid)
|
|
1068
|
+
view_post('${viewname}', 'cancel', {run_id:runid})
|
|
1069
|
+
}
|
|
1031
1070
|
function show_agent_debug_info(info) {
|
|
1032
1071
|
ensure_modal_exists_and_closed();
|
|
1033
1072
|
$("#scmodal .modal-body").html(info.debug_html);
|
|
@@ -1106,6 +1145,7 @@ const run = async (
|
|
|
1106
1145
|
}
|
|
1107
1146
|
function spin_send_button() {
|
|
1108
1147
|
$("#sendbuttonicon").attr("class","fas fa-spinner fa-spin");
|
|
1148
|
+
$(".cancelbtn").show()
|
|
1109
1149
|
$("textarea[name=userinput]").prop("disabled", true).attr("placeholder", "Waiting for response...");
|
|
1110
1150
|
$(".copilot-entry .submit-button").css("pointer-events", "none");
|
|
1111
1151
|
const isModernLayout = ${JSON.stringify((layout || "").startsWith("Modern chat"))};
|
|
@@ -1235,14 +1275,15 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
1235
1275
|
"You",
|
|
1236
1276
|
true,
|
|
1237
1277
|
config.layout,
|
|
1278
|
+
req?.user,
|
|
1238
1279
|
);
|
|
1239
|
-
|
|
1240
1280
|
await addToContext(run, {
|
|
1241
1281
|
interactions: [
|
|
1242
1282
|
...(run.context.interactions || []),
|
|
1243
1283
|
{ role: "user", content: userinput },
|
|
1244
1284
|
],
|
|
1245
1285
|
html_interactions: [userInteractions],
|
|
1286
|
+
status: "Running",
|
|
1246
1287
|
});
|
|
1247
1288
|
const dyn_updates = getState().getConfig("enable_dynamic_updates", true);
|
|
1248
1289
|
if (dyn_updates) {
|
|
@@ -1292,6 +1333,13 @@ const delprevrun = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
1292
1333
|
return;
|
|
1293
1334
|
};
|
|
1294
1335
|
|
|
1336
|
+
const cancel = async (table_id, viewname, config, body, { req, res }) => {
|
|
1337
|
+
const { run_id } = body;
|
|
1338
|
+
const run = await WorkflowRun.findOne({ id: +run_id });
|
|
1339
|
+
await run.update({ status: "Cancel" });
|
|
1340
|
+
return;
|
|
1341
|
+
};
|
|
1342
|
+
|
|
1295
1343
|
const debug_info = async (table_id, viewname, config, body, { req, res }) => {
|
|
1296
1344
|
const { run_id, triggering_row_id } = body;
|
|
1297
1345
|
const action =
|
|
@@ -1478,7 +1526,7 @@ const execute_user_action = async (
|
|
|
1478
1526
|
const { layout } = config;
|
|
1479
1527
|
|
|
1480
1528
|
const resp = JSON.stringify(
|
|
1481
|
-
wrapSegment(uadata.click_replace_text, "You", true, layout),
|
|
1529
|
+
wrapSegment(uadata.click_replace_text, "You", true, layout, req?.user),
|
|
1482
1530
|
);
|
|
1483
1531
|
getState().emitDynamicUpdate(
|
|
1484
1532
|
db.getTenantSchema(),
|
|
@@ -1497,6 +1545,7 @@ const execute_user_action = async (
|
|
|
1497
1545
|
"You",
|
|
1498
1546
|
true,
|
|
1499
1547
|
config.layout,
|
|
1548
|
+
req?.user,
|
|
1500
1549
|
);
|
|
1501
1550
|
return hi;
|
|
1502
1551
|
},
|
|
@@ -1544,6 +1593,13 @@ module.exports = {
|
|
|
1544
1593
|
//tableless: true,
|
|
1545
1594
|
table_optional: true,
|
|
1546
1595
|
run,
|
|
1547
|
-
routes: {
|
|
1596
|
+
routes: {
|
|
1597
|
+
interact,
|
|
1598
|
+
delprevrun,
|
|
1599
|
+
debug_info,
|
|
1600
|
+
skillroute,
|
|
1601
|
+
execute_user_action,
|
|
1602
|
+
cancel,
|
|
1603
|
+
},
|
|
1548
1604
|
mobile_render_server_side: true,
|
|
1549
1605
|
};
|
package/common.js
CHANGED
|
@@ -4,6 +4,7 @@ const Trigger = require("@saltcorn/data/models/trigger");
|
|
|
4
4
|
const View = require("@saltcorn/data/models/view");
|
|
5
5
|
const { interpolate } = require("@saltcorn/data/utils");
|
|
6
6
|
const db = require("@saltcorn/data/db");
|
|
7
|
+
const WorkflowRun = require("@saltcorn/data/models/workflow_run");
|
|
7
8
|
|
|
8
9
|
const MarkdownIt = require("markdown-it"),
|
|
9
10
|
md = new MarkdownIt({ html: true, breaks: true, linkify: true });
|
|
@@ -183,6 +184,7 @@ const addToContext = async (run, newCtx) => {
|
|
|
183
184
|
if (!run) return;
|
|
184
185
|
if (run.addToContext) return await run.addToContext(newCtx);
|
|
185
186
|
let changed = true;
|
|
187
|
+
let extraRunSet = {};
|
|
186
188
|
Object.keys(newCtx).forEach((k) => {
|
|
187
189
|
if (Array.isArray(run.context[k])) {
|
|
188
190
|
if (!Array.isArray(newCtx[k]))
|
|
@@ -195,12 +197,15 @@ const addToContext = async (run, newCtx) => {
|
|
|
195
197
|
throw new Error("Must be object to append to object");
|
|
196
198
|
Object.assign(run.context[k], newCtx[k]);
|
|
197
199
|
changed = true;
|
|
200
|
+
} else if (k === "status") {
|
|
201
|
+
extraRunSet.status = newCtx[k];
|
|
198
202
|
} else {
|
|
199
203
|
run.context[k] = newCtx[k];
|
|
200
204
|
changed = true;
|
|
201
205
|
}
|
|
202
206
|
});
|
|
203
|
-
if (changed && run.update)
|
|
207
|
+
if (changed && run.update)
|
|
208
|
+
await run.update({ context: run.context, ...extraRunSet });
|
|
204
209
|
};
|
|
205
210
|
|
|
206
211
|
const saveInteractions = async (run) => {
|
|
@@ -209,12 +214,12 @@ const saveInteractions = async (run) => {
|
|
|
209
214
|
});
|
|
210
215
|
};
|
|
211
216
|
|
|
212
|
-
const wrapSegment = (html, who, to_right, layout) =>
|
|
217
|
+
const wrapSegment = (html, who, to_right, layout, user) =>
|
|
213
218
|
who === null
|
|
214
219
|
? html
|
|
215
220
|
: layout && layout.startsWith("Modern chat")
|
|
216
221
|
? `<div class="chat-message ${to_right ? "chat-user" : "chat-assistant"}">` +
|
|
217
|
-
`<div class="chat-avatar"><i class="fas ${to_right ? "fa-user" : "fa-robot"}"></i></div>` +
|
|
222
|
+
`<div class="chat-avatar"${user ? ` title="${user.email} at ${new Date().toString()}"` : ""}><i class="fas ${to_right ? "fa-user" : "fa-robot"}"></i></div>` +
|
|
218
223
|
`<div class="chat-bubble">${html}</div>` +
|
|
219
224
|
`</div>`
|
|
220
225
|
: `<div class="interaction-segment ${to_right ? "to-right" : ""}"><div><div class="badgewrap"><span class="badge bg-secondary">` +
|
|
@@ -673,7 +678,10 @@ const process_interaction = async (
|
|
|
673
678
|
if (myHasResult && !stop) hasResult = true;
|
|
674
679
|
}
|
|
675
680
|
}
|
|
676
|
-
|
|
681
|
+
//await db.commitAndBeginNewTransaction();
|
|
682
|
+
const freshRun = await WorkflowRun.findOne({ id: run.id });
|
|
683
|
+
|
|
684
|
+
if (hasResult && freshRun.status !== "Cancel")
|
|
677
685
|
return await process_interaction(
|
|
678
686
|
run,
|
|
679
687
|
config,
|
package/locales/de.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{ "Sessions": "Sitzungen" }
|
|
1
|
+
{ "Sessions": "Sitzungen", "Approve": "Freigeben", "Approved": "Freigegeben" }
|
package/package.json
CHANGED
package/skills/PlanApproval.js
CHANGED
|
@@ -63,15 +63,15 @@ class PlanApprovalSkill {
|
|
|
63
63
|
provideTools = () => {
|
|
64
64
|
return {
|
|
65
65
|
type: "function",
|
|
66
|
-
process: async (row) => {
|
|
66
|
+
process: async (row, { req }) => {
|
|
67
67
|
return {
|
|
68
68
|
stop: true,
|
|
69
69
|
add_response: row.plan,
|
|
70
70
|
add_user_action: {
|
|
71
71
|
name: "approve_plan",
|
|
72
72
|
type: "button",
|
|
73
|
-
label:
|
|
74
|
-
click_replace_text: "Approved",
|
|
73
|
+
label: req.__("Approve"),
|
|
74
|
+
click_replace_text: req.__("Approved"),
|
|
75
75
|
input: {},
|
|
76
76
|
},
|
|
77
77
|
};
|