@saltcorn/agents 0.5.8 → 0.6.1
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 +109 -0
- package/agent-view.js +296 -239
- package/common.js +195 -164
- package/index.js +8 -90
- package/package.json +9 -2
- package/public/jquery.autogrow-textarea.js +205 -0
- package/skills/EmbeddingRetrieval.js +2 -0
- package/skills/FTSRetrieval.js +1 -0
- package/skills/PreloadData.js +7 -2
- package/skills/Table.js +1 -0
- package/skills/Trigger.js +2 -0
- package/tests/action.test.js +80 -0
- package/tests/agentcfg.js +46 -0
- package/tests/configs.js +34 -0
- package/tests/view.test.js +89 -0
package/agent-view.js
CHANGED
|
@@ -30,6 +30,7 @@ const {
|
|
|
30
30
|
textarea,
|
|
31
31
|
label,
|
|
32
32
|
a,
|
|
33
|
+
br,
|
|
33
34
|
} = require("@saltcorn/markup/tags");
|
|
34
35
|
const { getState } = require("@saltcorn/data/db/state");
|
|
35
36
|
const {
|
|
@@ -107,6 +108,15 @@ const configuration_workflow = (req) =>
|
|
|
107
108
|
sublabel:
|
|
108
109
|
"Appears below the input box. Use for additional instructions.",
|
|
109
110
|
},
|
|
111
|
+
{
|
|
112
|
+
name: "layout",
|
|
113
|
+
label: "Layout",
|
|
114
|
+
type: "String",
|
|
115
|
+
required: true,
|
|
116
|
+
attributes: {
|
|
117
|
+
options: ["Standard", "No card"],
|
|
118
|
+
},
|
|
119
|
+
},
|
|
110
120
|
{
|
|
111
121
|
name: "image_upload",
|
|
112
122
|
label: "Upload images",
|
|
@@ -219,17 +229,21 @@ const run = async (
|
|
|
219
229
|
image_upload,
|
|
220
230
|
stream,
|
|
221
231
|
audio_recorder,
|
|
232
|
+
layout,
|
|
222
233
|
},
|
|
223
234
|
state,
|
|
224
235
|
{ res, req },
|
|
225
236
|
) => {
|
|
226
237
|
const action = await Trigger.findOne({ id: action_id });
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
238
|
+
if (!action) throw new Error(`Action not found: ${action_id}`);
|
|
239
|
+
const prevRuns = show_prev_runs
|
|
240
|
+
? (
|
|
241
|
+
await WorkflowRun.find(
|
|
242
|
+
{ trigger_id: action.id, started_by: req.user?.id },
|
|
243
|
+
{ orderBy: "started_at", orderDesc: true, limit: 30 },
|
|
244
|
+
)
|
|
245
|
+
).filter((r) => r.context.interactions)
|
|
246
|
+
: null;
|
|
233
247
|
|
|
234
248
|
const cfgMsg = incompleteCfgMsg();
|
|
235
249
|
if (cfgMsg) return cfgMsg;
|
|
@@ -244,137 +258,146 @@ const run = async (
|
|
|
244
258
|
}
|
|
245
259
|
const initial_q = state.run_id ? undefined : state._q;
|
|
246
260
|
if (state.run_id) {
|
|
247
|
-
const run = prevRuns
|
|
261
|
+
const run = prevRuns
|
|
262
|
+
? prevRuns.find((r) => r.id == state.run_id)
|
|
263
|
+
: await WorkflowRun.findOne({
|
|
264
|
+
trigger_id: action.id,
|
|
265
|
+
started_by: req.user?.id,
|
|
266
|
+
id: state.run_id,
|
|
267
|
+
});
|
|
248
268
|
const interactMarkups = [];
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
269
|
+
if (run.context.html_interactions) {
|
|
270
|
+
interactMarkups.push(...run.context.html_interactions);
|
|
271
|
+
} else
|
|
272
|
+
for (const interact of run.context.interactions) {
|
|
273
|
+
switch (interact.role) {
|
|
274
|
+
case "user":
|
|
275
|
+
if (interact.content?.[0]?.type === "image_url") {
|
|
276
|
+
const image_url = interact.content[0].image_url.url;
|
|
277
|
+
if (image_url.startsWith("data"))
|
|
278
|
+
interactMarkups.push(
|
|
279
|
+
div(
|
|
280
|
+
{ class: "interaction-segment" },
|
|
281
|
+
span({ class: "badge bg-secondary" }, "You"),
|
|
282
|
+
"File",
|
|
283
|
+
),
|
|
284
|
+
);
|
|
285
|
+
else
|
|
286
|
+
interactMarkups.push(
|
|
287
|
+
div(
|
|
288
|
+
{ class: "interaction-segment" },
|
|
289
|
+
span({ class: "badge bg-secondary" }, "You"),
|
|
290
|
+
a({ href: image_url, target: "_blank" }, "File"),
|
|
291
|
+
),
|
|
292
|
+
);
|
|
293
|
+
} else
|
|
255
294
|
interactMarkups.push(
|
|
256
295
|
div(
|
|
257
296
|
{ class: "interaction-segment" },
|
|
258
297
|
span({ class: "badge bg-secondary" }, "You"),
|
|
259
|
-
|
|
298
|
+
md.render(interact.content),
|
|
260
299
|
),
|
|
261
300
|
);
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
301
|
+
break;
|
|
302
|
+
case "assistant":
|
|
303
|
+
case "system":
|
|
304
|
+
for (const tool_call of interact.tool_calls || []) {
|
|
305
|
+
const toolSkill = find_tool(
|
|
306
|
+
tool_call.function?.name,
|
|
307
|
+
action.configuration,
|
|
269
308
|
);
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
);
|
|
286
|
-
if (toolSkill) {
|
|
287
|
-
const row = JSON.parse(tool_call.function.arguments);
|
|
288
|
-
if (toolSkill.tool.renderToolCall) {
|
|
289
|
-
const rendered = await toolSkill.tool.renderToolCall(row, {
|
|
290
|
-
req,
|
|
291
|
-
});
|
|
292
|
-
if (rendered)
|
|
293
|
-
interactMarkups.push(
|
|
294
|
-
wrapSegment(
|
|
295
|
-
wrapCard(
|
|
296
|
-
toolSkill.skill.skill_label ||
|
|
297
|
-
toolSkill.skill.constructor.skill_name,
|
|
298
|
-
rendered,
|
|
309
|
+
if (toolSkill) {
|
|
310
|
+
const row = JSON.parse(tool_call.function.arguments);
|
|
311
|
+
if (toolSkill.tool.renderToolCall) {
|
|
312
|
+
const rendered = await toolSkill.tool.renderToolCall(row, {
|
|
313
|
+
req,
|
|
314
|
+
});
|
|
315
|
+
if (rendered)
|
|
316
|
+
interactMarkups.push(
|
|
317
|
+
wrapSegment(
|
|
318
|
+
wrapCard(
|
|
319
|
+
toolSkill.skill.skill_label ||
|
|
320
|
+
toolSkill.skill.constructor.skill_name,
|
|
321
|
+
rendered,
|
|
322
|
+
),
|
|
323
|
+
action.name,
|
|
299
324
|
),
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
);
|
|
325
|
+
);
|
|
326
|
+
}
|
|
303
327
|
}
|
|
304
328
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
);
|
|
329
|
+
for (const image_call of interact.content?.image_calls || []) {
|
|
330
|
+
const toolSkill = find_image_tool(action.configuration);
|
|
331
|
+
if (toolSkill) {
|
|
332
|
+
if (toolSkill.tool.renderToolResponse) {
|
|
333
|
+
const rendered = await toolSkill.tool.renderToolResponse(
|
|
334
|
+
image_call,
|
|
335
|
+
{
|
|
336
|
+
req,
|
|
337
|
+
},
|
|
338
|
+
);
|
|
316
339
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
340
|
+
if (rendered)
|
|
341
|
+
interactMarkups.push(
|
|
342
|
+
wrapSegment(
|
|
343
|
+
wrapCard(
|
|
344
|
+
toolSkill.skill.skill_label ||
|
|
345
|
+
toolSkill.skill.constructor.skill_name,
|
|
346
|
+
rendered,
|
|
347
|
+
),
|
|
348
|
+
action.name,
|
|
324
349
|
),
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
);
|
|
350
|
+
);
|
|
351
|
+
}
|
|
328
352
|
}
|
|
329
353
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
)
|
|
335
|
-
interactMarkups.push(
|
|
336
|
-
div(
|
|
337
|
-
{ class: "interaction-segment" },
|
|
338
|
-
span({ class: "badge bg-secondary" }, action.name),
|
|
339
|
-
typeof interact.content === "string"
|
|
340
|
-
? md.render(interact.content)
|
|
341
|
-
: typeof interact.content?.content === "string"
|
|
342
|
-
? md.render(interact.content.content)
|
|
343
|
-
: interact.content,
|
|
344
|
-
),
|
|
345
|
-
);
|
|
346
|
-
break;
|
|
347
|
-
case "tool":
|
|
348
|
-
if (interact.content !== "Action run") {
|
|
349
|
-
let markupContent;
|
|
350
|
-
const toolSkill = find_tool(interact.name, action.configuration);
|
|
351
|
-
try {
|
|
352
|
-
if (toolSkill?.tool?.renderToolResponse)
|
|
353
|
-
markupContent = await toolSkill?.tool?.renderToolResponse?.(
|
|
354
|
-
JSON.parse(interact.content),
|
|
355
|
-
{
|
|
356
|
-
req,
|
|
357
|
-
},
|
|
358
|
-
);
|
|
359
|
-
} catch {
|
|
360
|
-
markupContent = pre(interact.content);
|
|
361
|
-
}
|
|
362
|
-
if (markupContent)
|
|
354
|
+
if (
|
|
355
|
+
typeof interact.content === "string" ||
|
|
356
|
+
typeof interact.content?.content === "string"
|
|
357
|
+
)
|
|
363
358
|
interactMarkups.push(
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
359
|
+
div(
|
|
360
|
+
{ class: "interaction-segment" },
|
|
361
|
+
span({ class: "badge bg-secondary" }, action.name),
|
|
362
|
+
typeof interact.content === "string"
|
|
363
|
+
? md.render(interact.content)
|
|
364
|
+
: typeof interact.content?.content === "string"
|
|
365
|
+
? md.render(interact.content.content)
|
|
366
|
+
: interact.content,
|
|
372
367
|
),
|
|
373
368
|
);
|
|
374
|
-
|
|
375
|
-
|
|
369
|
+
break;
|
|
370
|
+
case "tool":
|
|
371
|
+
if (interact.content !== "Action run") {
|
|
372
|
+
let markupContent;
|
|
373
|
+
const toolSkill = find_tool(interact.name, action.configuration);
|
|
374
|
+
try {
|
|
375
|
+
if (toolSkill?.tool?.renderToolResponse)
|
|
376
|
+
markupContent = await toolSkill?.tool?.renderToolResponse?.(
|
|
377
|
+
JSON.parse(interact.content),
|
|
378
|
+
{
|
|
379
|
+
req,
|
|
380
|
+
},
|
|
381
|
+
);
|
|
382
|
+
} catch {
|
|
383
|
+
markupContent = pre(interact.content);
|
|
384
|
+
}
|
|
385
|
+
if (markupContent)
|
|
386
|
+
interactMarkups.push(
|
|
387
|
+
wrapSegment(
|
|
388
|
+
wrapCard(
|
|
389
|
+
toolSkill?.skill?.skill_label ||
|
|
390
|
+
toolSkill?.skill?.constructor.skill_name ||
|
|
391
|
+
interact.name,
|
|
392
|
+
markupContent,
|
|
393
|
+
),
|
|
394
|
+
action.name,
|
|
395
|
+
),
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
376
400
|
}
|
|
377
|
-
}
|
|
378
401
|
runInteractions = interactMarkups.join("");
|
|
379
402
|
}
|
|
380
403
|
const skill_form_widgets = [];
|
|
@@ -390,10 +413,12 @@ const run = async (
|
|
|
390
413
|
}
|
|
391
414
|
|
|
392
415
|
const debugMode = is_debug_mode(action.configuration, req.user);
|
|
416
|
+
const dyn_updates = getState().getConfig("enable_dynamic_updates", true);
|
|
417
|
+
|
|
393
418
|
const rndid = Math.floor(Math.random() * 16777215).toString(16);
|
|
394
419
|
const input_form = form(
|
|
395
420
|
{
|
|
396
|
-
onsubmit: `event.preventDefault();spin_send_button();view_post('${viewname}', 'interact', new FormData(this), processCopilotResponse);return false;`,
|
|
421
|
+
onsubmit: `event.preventDefault();spin_send_button();view_post('${viewname}', 'interact', new FormData(this), ${dyn_updates ? "null" : "processCopilotResponse"});return false;`,
|
|
397
422
|
class: ["form-namespace copilot mt-2 agent-view"],
|
|
398
423
|
method: "post",
|
|
399
424
|
},
|
|
@@ -455,68 +480,73 @@ const run = async (
|
|
|
455
480
|
div({ class: "next_response_scratch" }),
|
|
456
481
|
);
|
|
457
482
|
|
|
458
|
-
const prev_runs_side_bar =
|
|
459
|
-
div(
|
|
460
|
-
{
|
|
461
|
-
class: "d-flex justify-content-between align-middle mb-2",
|
|
462
|
-
},
|
|
463
|
-
div(
|
|
464
|
-
{ class: "d-flex" },
|
|
465
|
-
i({
|
|
466
|
-
class: "fas fa-caret-down me-1 session-open-sessions",
|
|
467
|
-
onclick: "close_session_list()",
|
|
468
|
-
}),
|
|
469
|
-
h5(req.__("Sessions")),
|
|
470
|
-
),
|
|
471
|
-
button(
|
|
472
|
-
{
|
|
473
|
-
type: "button",
|
|
474
|
-
class: "btn btn-secondary btn-sm py-0",
|
|
475
|
-
style: "font-size: 0.9em;height:1.5em",
|
|
476
|
-
onclick: "unset_state_field('run_id')",
|
|
477
|
-
title: "New session",
|
|
478
|
-
},
|
|
479
|
-
i({ class: "fas fa-redo fa-sm" }),
|
|
480
|
-
),
|
|
481
|
-
),
|
|
482
|
-
prevRuns.map((run) =>
|
|
483
|
-
div(
|
|
484
|
-
{
|
|
485
|
-
onclick: `set_state_field('run_id',${run.id})`,
|
|
486
|
-
class: "prevcopilotrun border p-2",
|
|
487
|
-
},
|
|
483
|
+
const prev_runs_side_bar = show_prev_runs
|
|
484
|
+
? div(
|
|
488
485
|
div(
|
|
489
|
-
{
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
486
|
+
{
|
|
487
|
+
class: "d-flex justify-content-between align-middle mb-2",
|
|
488
|
+
},
|
|
489
|
+
div(
|
|
490
|
+
{ class: "d-flex" },
|
|
491
|
+
i({
|
|
492
|
+
class: "fas fa-caret-down me-1 session-open-sessions",
|
|
493
|
+
onclick: "close_session_list()",
|
|
494
|
+
}),
|
|
495
|
+
h5(req.__("Sessions")),
|
|
496
|
+
),
|
|
497
|
+
button(
|
|
498
|
+
{
|
|
499
|
+
type: "button",
|
|
500
|
+
class: "btn btn-secondary btn-sm py-0",
|
|
501
|
+
style: "font-size: 0.9em;height:1.5em",
|
|
502
|
+
onclick: "unset_state_field('run_id')",
|
|
503
|
+
title: "New session",
|
|
504
|
+
},
|
|
505
|
+
i({ class: "fas fa-redo fa-sm" }),
|
|
506
|
+
),
|
|
495
507
|
),
|
|
508
|
+
prevRuns.map((run) =>
|
|
509
|
+
div(
|
|
510
|
+
{
|
|
511
|
+
onclick: `set_state_field('run_id',${run.id})`,
|
|
512
|
+
class: "prevcopilotrun border p-2",
|
|
513
|
+
},
|
|
514
|
+
div(
|
|
515
|
+
{ class: "d-flex justify-content-between" },
|
|
516
|
+
localeDateTime(run.started_at),
|
|
517
|
+
i({
|
|
518
|
+
class: "far fa-trash-alt",
|
|
519
|
+
onclick: `delprevrun(event, ${run.id})`,
|
|
520
|
+
}),
|
|
521
|
+
),
|
|
496
522
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
523
|
+
p(
|
|
524
|
+
{ class: "prevrun_content" },
|
|
525
|
+
run.context.interactions
|
|
526
|
+
.find((i) => typeof i?.content === "string")
|
|
527
|
+
?.content?.substring?.(0, 80),
|
|
528
|
+
),
|
|
529
|
+
),
|
|
530
|
+
),
|
|
531
|
+
)
|
|
532
|
+
: "";
|
|
533
|
+
|
|
534
|
+
const main_inner = div(
|
|
503
535
|
div(
|
|
504
|
-
{
|
|
505
|
-
|
|
506
|
-
{
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
style(
|
|
519
|
-
`div.interaction-segment:not(:first-child) {border-top: 1px solid #e7e7e7; }
|
|
536
|
+
{
|
|
537
|
+
class: "open-prev-runs",
|
|
538
|
+
style: prev_runs_closed ? {} : { display: "none" },
|
|
539
|
+
onclick: "open_session_list()",
|
|
540
|
+
},
|
|
541
|
+
i({
|
|
542
|
+
class: "fas fa-caret-right me-1",
|
|
543
|
+
}),
|
|
544
|
+
req.__("Sessions"),
|
|
545
|
+
),
|
|
546
|
+
div({ id: "copilotinteractions" }, runInteractions),
|
|
547
|
+
input_form,
|
|
548
|
+
style(
|
|
549
|
+
`div.interaction-segment:not(:first-child) {border-top: 1px solid #e7e7e7; }
|
|
520
550
|
div.interaction-segment {padding-top: 5px;padding-bottom: 5px;}
|
|
521
551
|
div.interaction-segment p {margin-bottom: 0px;}
|
|
522
552
|
div.interaction-segment div.card {margin-top: 0.5rem;}
|
|
@@ -573,9 +603,10 @@ const run = async (
|
|
|
573
603
|
margin-bottom: 0px;
|
|
574
604
|
display: block;
|
|
575
605
|
text-overflow: ellipsis;}`,
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
606
|
+
),
|
|
607
|
+
script(domReady(`$( "#inputuserinput" ).autogrow({paddingBottom: 20});`)),
|
|
608
|
+
script(
|
|
609
|
+
`
|
|
579
610
|
function close_session_list() {
|
|
580
611
|
$("div.prev-runs-list").hide().parents(".col-3").removeClass("col-3").addClass("was-col-3").parent().children(".col-9").removeClass("col-9").addClass("col-12")
|
|
581
612
|
$("div.open-prev-runs").show()
|
|
@@ -587,8 +618,10 @@ const run = async (
|
|
|
587
618
|
function get_run_id(elem) {
|
|
588
619
|
return $("input[name=run_id").val()
|
|
589
620
|
}
|
|
590
|
-
function processCopilotResponse(res) {
|
|
621
|
+
function processCopilotResponse(res) {
|
|
622
|
+
console.log("processCopilotResponse", res)
|
|
591
623
|
const hadFile = $("input#attach_agent_image").val();
|
|
624
|
+
let fileBadge = hadFile ? '<span class="badge text-bg-info"><i class="fas fa-image me-1"></i>'+$("input#attach_agent_image")[0].files?.item?.(0)?.name||"File"+'</span>': ""
|
|
592
625
|
$("span.filename-label").text("");
|
|
593
626
|
$("input#attach_agent_image").val(null);
|
|
594
627
|
$("#sendbuttonicon").attr("class","far fa-paper-plane");
|
|
@@ -596,15 +629,14 @@ const run = async (
|
|
|
596
629
|
if(res.run_id && (!$runidin.val() || $runidin.val()=="undefined"))
|
|
597
630
|
$runidin.val(res.run_id);
|
|
598
631
|
const wrapSegment = (html, who) => '<div class="interaction-segment"><span class="badge bg-secondary">'+who+'</span>'+html+'</div>'
|
|
599
|
-
$("#copilotinteractions").append(wrapSegment('<p>'+$("textarea[name=userinput]").val()+'</p>', "You"))
|
|
600
|
-
if(hadFile)
|
|
601
|
-
$("#copilotinteractions").append(wrapSegment('File', "You"))
|
|
632
|
+
$("#copilotinteractions").append(wrapSegment('<p>'+$("textarea[name=userinput]").val()+'</p>'+fileBadge, "You"))
|
|
602
633
|
$("textarea[name=userinput]").val("")
|
|
603
634
|
$('form.agent-view div.next_response_scratch').html("")
|
|
604
635
|
window['stream scratch ${viewname} ${rndid}'] = []
|
|
605
636
|
if(res.response)
|
|
606
637
|
$("#copilotinteractions").append(res.response)
|
|
607
638
|
}
|
|
639
|
+
window.processCopilotResponse = processCopilotResponse;
|
|
608
640
|
function agent_file_attach(e) {
|
|
609
641
|
$(".attach_agent_image_wrap span.filename-label").text(e.target.files[0].name)
|
|
610
642
|
}
|
|
@@ -648,7 +680,7 @@ const run = async (
|
|
|
648
680
|
}
|
|
649
681
|
}
|
|
650
682
|
function submitOnEnter(event) {
|
|
651
|
-
if (event.which === 13) {
|
|
683
|
+
if (event.which === 13 && !event.shiftKey) {
|
|
652
684
|
if (!event.repeat) {
|
|
653
685
|
const newEvent = new Event("submit", {cancelable: true});
|
|
654
686
|
event.target.form.dispatchEvent(newEvent);
|
|
@@ -661,14 +693,17 @@ const run = async (
|
|
|
661
693
|
function spin_send_button() {
|
|
662
694
|
$("#sendbuttonicon").attr("class","fas fa-spinner fa-spin");
|
|
663
695
|
};`,
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
),
|
|
696
|
+
stream &&
|
|
697
|
+
domReady(
|
|
698
|
+
`$('form.agent-view input[name=page_load_tag]').val(window._sc_pageloadtag)`,
|
|
699
|
+
),
|
|
700
|
+
initial_q && domReady("$('form.copilot').submit()"),
|
|
670
701
|
),
|
|
671
702
|
);
|
|
703
|
+
const main_chat =
|
|
704
|
+
layout === "No card"
|
|
705
|
+
? div({ class: "mx-1" }, main_inner)
|
|
706
|
+
: div({ class: "card" }, div({ class: "card-body" }, main_inner));
|
|
672
707
|
|
|
673
708
|
return show_prev_runs
|
|
674
709
|
? div(
|
|
@@ -705,17 +740,16 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
705
740
|
trigger_id: config.action_id,
|
|
706
741
|
context: {
|
|
707
742
|
implemented_fcall_ids: [],
|
|
708
|
-
interactions: [...ini_interacts
|
|
743
|
+
interactions: [...ini_interacts],
|
|
744
|
+
html_interactions: [],
|
|
709
745
|
funcalls: {},
|
|
710
746
|
triggering_row_id,
|
|
711
747
|
},
|
|
712
748
|
});
|
|
713
749
|
} else {
|
|
714
750
|
run = await WorkflowRun.findOne({ id: +run_id });
|
|
715
|
-
await addToContext(run, {
|
|
716
|
-
interactions: [{ role: "user", content: userinput }],
|
|
717
|
-
});
|
|
718
751
|
}
|
|
752
|
+
let fileBadges = "";
|
|
719
753
|
if (config.image_upload && req.files?.file) {
|
|
720
754
|
const file = await File.from_req_files(
|
|
721
755
|
req.files.file,
|
|
@@ -723,6 +757,11 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
723
757
|
100,
|
|
724
758
|
// file_field?.attributes?.folder
|
|
725
759
|
);
|
|
760
|
+
fileBadges = span(
|
|
761
|
+
{ class: "badge text-bg-info" },
|
|
762
|
+
i({ class: "fas fa-image me-1" }),
|
|
763
|
+
file.filename,
|
|
764
|
+
);
|
|
726
765
|
const baseUrl = getState().getConfig("base_url").replace(/\/$/, "");
|
|
727
766
|
let imageurl;
|
|
728
767
|
if (
|
|
@@ -735,24 +774,22 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
735
774
|
const b64 = await file.get_contents("base64");
|
|
736
775
|
imageurl = `data:${file.mimetype};base64,${b64}`;
|
|
737
776
|
}
|
|
777
|
+
await getState().functions.llm_add_message.run("image", imageurl, {
|
|
778
|
+
chat: run.context.interactions || [],
|
|
779
|
+
});
|
|
738
780
|
await addToContext(run, {
|
|
739
|
-
interactions: [
|
|
740
|
-
{
|
|
741
|
-
role: "user",
|
|
742
|
-
content: [
|
|
743
|
-
{
|
|
744
|
-
type: "image_url",
|
|
745
|
-
image_url: {
|
|
746
|
-
url: imageurl,
|
|
747
|
-
},
|
|
748
|
-
},
|
|
749
|
-
],
|
|
750
|
-
},
|
|
751
|
-
],
|
|
781
|
+
interactions: run.context.interactions || [],
|
|
752
782
|
});
|
|
753
783
|
}
|
|
754
|
-
|
|
755
|
-
|
|
784
|
+
await addToContext(run, {
|
|
785
|
+
interactions: [
|
|
786
|
+
...(run.context.interactions || []),
|
|
787
|
+
{ role: "user", content: userinput },
|
|
788
|
+
],
|
|
789
|
+
html_interactions: [wrapSegment(p(userinput) + fileBadges, "You")],
|
|
790
|
+
});
|
|
791
|
+
const dyn_updates = getState().getConfig("enable_dynamic_updates", true);
|
|
792
|
+
const process_promise = process_interaction(
|
|
756
793
|
run,
|
|
757
794
|
action.configuration,
|
|
758
795
|
req,
|
|
@@ -760,7 +797,21 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
760
797
|
[],
|
|
761
798
|
triggering_row,
|
|
762
799
|
config,
|
|
800
|
+
dyn_updates,
|
|
763
801
|
);
|
|
802
|
+
if (dyn_updates) {
|
|
803
|
+
process_promise.catch((e) => {
|
|
804
|
+
console.error(e);
|
|
805
|
+
getState().emitDynamicUpdate(
|
|
806
|
+
db.getTenantSchema(),
|
|
807
|
+
{
|
|
808
|
+
error: e?.message || e,
|
|
809
|
+
},
|
|
810
|
+
[req.user.id],
|
|
811
|
+
);
|
|
812
|
+
});
|
|
813
|
+
return;
|
|
814
|
+
} else return await process_promise;
|
|
764
815
|
};
|
|
765
816
|
|
|
766
817
|
const delprevrun = async (table_id, viewname, config, body, { req, res }) => {
|
|
@@ -845,36 +896,42 @@ const skillroute = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
845
896
|
},
|
|
846
897
|
};
|
|
847
898
|
};
|
|
848
|
-
|
|
849
|
-
|
|
899
|
+
|
|
900
|
+
const execute_user_action = async (
|
|
901
|
+
table_id,
|
|
850
902
|
viewname,
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
{
|
|
870
|
-
type: "button",
|
|
871
|
-
id: "exec-" + tool_call.id,
|
|
872
|
-
class: "btn btn-primary d-block mt-3 float-end",
|
|
873
|
-
onclick: `press_store_button(this, true);view_post('${viewname}', 'execute', {fcall_id: '${tool_call.id}', run_id: ${run.id}}, processExecuteResponse)`,
|
|
874
|
-
},
|
|
875
|
-
"Apply",
|
|
876
|
-
) + div({ id: "postexec-" + tool_call.id }),
|
|
903
|
+
config,
|
|
904
|
+
body,
|
|
905
|
+
{ req, res },
|
|
906
|
+
) => {
|
|
907
|
+
const { run_id, rndid, uaname } = body;
|
|
908
|
+
|
|
909
|
+
const action = await Trigger.findOne({ id: config.action_id });
|
|
910
|
+
const run = await WorkflowRun.findOne({ id: +run_id });
|
|
911
|
+
//console.log("run uas",run.context.user_actions );
|
|
912
|
+
|
|
913
|
+
if (!run) return;
|
|
914
|
+
const instances = get_skill_instances(action.configuration);
|
|
915
|
+
const instance = instances.find((i) => i.userActions?.[uaname]);
|
|
916
|
+
//console.log({ instance });
|
|
917
|
+
|
|
918
|
+
if (!instance) return;
|
|
919
|
+
const uadata = (run.context.user_actions || []).find(
|
|
920
|
+
(ua) => ua.rndid === rndid,
|
|
877
921
|
);
|
|
922
|
+
if (!uadata) return;
|
|
923
|
+
const result = await instance.userActions[uaname]({
|
|
924
|
+
user: req.user,
|
|
925
|
+
...uadata.tool_call.input,
|
|
926
|
+
...uadata.input,
|
|
927
|
+
});
|
|
928
|
+
return {
|
|
929
|
+
json: {
|
|
930
|
+
success: "ok",
|
|
931
|
+
...result,
|
|
932
|
+
},
|
|
933
|
+
};
|
|
934
|
+
};
|
|
878
935
|
|
|
879
936
|
module.exports = {
|
|
880
937
|
name: "Agent Chat",
|
|
@@ -884,5 +941,5 @@ module.exports = {
|
|
|
884
941
|
//tableless: true,
|
|
885
942
|
table_optional: true,
|
|
886
943
|
run,
|
|
887
|
-
routes: { interact, delprevrun, debug_info, skillroute },
|
|
944
|
+
routes: { interact, delprevrun, debug_info, skillroute, execute_user_action },
|
|
888
945
|
};
|