@saltcorn/agents 0.7.13 → 0.7.15
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 +78 -15
- package/common.js +18 -5
- package/locales/de.json +1 -1
- package/package.json +1 -1
- package/skills/PlanApproval.js +3 -5
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),
|
|
@@ -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,19 +1545,27 @@ 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
|
},
|
|
1503
1552
|
);
|
|
1504
1553
|
await run.update({ context: run.context });
|
|
1505
1554
|
}
|
|
1555
|
+
let row = {};
|
|
1556
|
+
if (run.context.triggering_row_id) {
|
|
1557
|
+
const table = Table.findOne(table_id);
|
|
1558
|
+
const pk = table?.pk_name;
|
|
1559
|
+
if (table)
|
|
1560
|
+
row = await table.getRow({ [pk]: run.context.triggering_row_id });
|
|
1561
|
+
}
|
|
1506
1562
|
await process_interaction(
|
|
1507
1563
|
run,
|
|
1508
1564
|
action.configuration,
|
|
1509
1565
|
req,
|
|
1510
1566
|
action.name,
|
|
1511
1567
|
[],
|
|
1512
|
-
|
|
1568
|
+
row,
|
|
1513
1569
|
config,
|
|
1514
1570
|
dyn_updates,
|
|
1515
1571
|
);
|
|
@@ -1537,6 +1593,13 @@ module.exports = {
|
|
|
1537
1593
|
//tableless: true,
|
|
1538
1594
|
table_optional: true,
|
|
1539
1595
|
run,
|
|
1540
|
-
routes: {
|
|
1596
|
+
routes: {
|
|
1597
|
+
interact,
|
|
1598
|
+
delprevrun,
|
|
1599
|
+
debug_info,
|
|
1600
|
+
skillroute,
|
|
1601
|
+
execute_user_action,
|
|
1602
|
+
cancel,
|
|
1603
|
+
},
|
|
1541
1604
|
mobile_render_server_side: true,
|
|
1542
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">` +
|
|
@@ -407,7 +412,12 @@ const process_interaction = async (
|
|
|
407
412
|
if (rendered)
|
|
408
413
|
add_response(
|
|
409
414
|
wrapSegment(
|
|
410
|
-
wrapCard(
|
|
415
|
+
wrapCard(
|
|
416
|
+
response_label,
|
|
417
|
+
typeof rendered === "string"
|
|
418
|
+
? md.render(rendered)
|
|
419
|
+
: rendered,
|
|
420
|
+
),
|
|
411
421
|
agent_label,
|
|
412
422
|
false,
|
|
413
423
|
layout,
|
|
@@ -668,7 +678,10 @@ const process_interaction = async (
|
|
|
668
678
|
if (myHasResult && !stop) hasResult = true;
|
|
669
679
|
}
|
|
670
680
|
}
|
|
671
|
-
|
|
681
|
+
//await db.commitAndBeginNewTransaction();
|
|
682
|
+
const freshRun = await WorkflowRun.findOne({ id: run.id });
|
|
683
|
+
|
|
684
|
+
if (hasResult && freshRun.status !== "Cancel")
|
|
672
685
|
return await process_interaction(
|
|
673
686
|
run,
|
|
674
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,17 +63,15 @@ class PlanApprovalSkill {
|
|
|
63
63
|
provideTools = () => {
|
|
64
64
|
return {
|
|
65
65
|
type: "function",
|
|
66
|
-
process: async (row) => {
|
|
67
|
-
console.log("process plan row", row);
|
|
68
|
-
|
|
66
|
+
process: async (row, { req }) => {
|
|
69
67
|
return {
|
|
70
68
|
stop: true,
|
|
71
69
|
add_response: row.plan,
|
|
72
70
|
add_user_action: {
|
|
73
71
|
name: "approve_plan",
|
|
74
72
|
type: "button",
|
|
75
|
-
label:
|
|
76
|
-
click_replace_text: "Approved",
|
|
73
|
+
label: req.__("Approve"),
|
|
74
|
+
click_replace_text: req.__("Approved"),
|
|
77
75
|
input: {},
|
|
78
76
|
},
|
|
79
77
|
};
|