@saltcorn/agents 0.6.3 → 0.6.4

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 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({
@@ -271,6 +275,7 @@ const run = async (
271
275
  interactMarkups.push(...run.context.html_interactions);
272
276
  } else
273
277
  for (const interact of run.context.interactions) {
278
+ //legacy
274
279
  switch (interact.role) {
275
280
  case "user":
276
281
  if (interact.content?.[0]?.type === "image_url") {
@@ -485,7 +490,7 @@ const run = async (
485
490
  ? div(
486
491
  div(
487
492
  {
488
- class: "d-flex justify-content-between align-middle mb-2",
493
+ class: "d-flex flex-wrap justify-content-between align-middle mb-2",
489
494
  },
490
495
  div(
491
496
  { class: "d-flex" },
@@ -498,7 +503,7 @@ const run = async (
498
503
  button(
499
504
  {
500
505
  type: "button",
501
- class: "btn btn-secondary btn-sm py-0",
506
+ class: "btn btn-secondary btn-sm pt-0 pb-1",
502
507
  style: "font-size: 0.9em;height:1.5em",
503
508
  onclick: "unset_state_field('run_id')",
504
509
  title: "New session",
@@ -514,7 +519,10 @@ const run = async (
514
519
  },
515
520
  div(
516
521
  { class: "d-flex justify-content-between" },
517
- localeDateTime(run.started_at),
522
+ span(
523
+ { class: "text-truncate", style: "min-width:0" },
524
+ localeDateTime(run.started_at),
525
+ ),
518
526
  i({
519
527
  class: "far fa-trash-alt",
520
528
  onclick: `delprevrun(event, ${run.id})`,
@@ -550,7 +558,15 @@ const run = async (
550
558
  `div.interaction-segment:not(:first-child) {border-top: 1px solid #e7e7e7; }
551
559
  div.interaction-segment {padding-top: 5px;padding-bottom: 5px;}
552
560
  div.interaction-segment p {margin-bottom: 0px;}
553
- div.interaction-segment div.card {margin-top: 0.5rem;}
561
+ div.interaction-segment div.card {margin-top: 0.5rem;}
562
+ div.interaction-segment.to-right {
563
+ display: flex;
564
+ flex-direction: row-reverse;
565
+ }
566
+ div.interaction-segment.to-right div.badgewrap {
567
+ display: flex;
568
+ flex-direction: row-reverse;
569
+ }
554
570
  div.prevcopilotrun:hover {cursor: pointer; background-color: var(--tblr-secondary-bg-subtle, var(--bs-secondary-bg-subtle, gray));}
555
571
  div.prevcopilotrun i.fa-trash-alt {display: none;}
556
572
  div.prevcopilotrun:hover i.fa-trash-alt {display: block;}
@@ -625,7 +641,7 @@ const run = async (
625
641
  function get_run_id(elem) {
626
642
  return $("input[name=run_id").val()
627
643
  }
628
- function processCopilotResponse(res) {
644
+ function processCopilotResponse(res, not_final) {
629
645
  console.log("processCopilotResponse", res)
630
646
  const fileInput = $("input#attach_agent_image")[0];
631
647
  let fileBadge = "";
@@ -637,13 +653,13 @@ const run = async (
637
653
  $("span.filename-label").text("").removeClass("me-2");
638
654
  _agentDT.items.clear();
639
655
  $("input#attach_agent_image").val(null);
640
- $("#sendbuttonicon").attr("class","far fa-paper-plane");
656
+ if(!not_final || (!${JSON.stringify(dyn_updates)})) $("#sendbuttonicon").attr("class","far fa-paper-plane");
641
657
  const $runidin= $("input[name=run_id")
642
658
  if(res.run_id && (!$runidin.val() || $runidin.val()=="undefined"))
643
659
  $runidin.val(res.run_id);
644
660
  const wrapSegment = (html, who) => '<div class="interaction-segment"><span class="badge bg-secondary">'+who+'</span>'+html+'</div>'
645
661
  const user_input = $("textarea[name=userinput]").val()
646
- if(user_input)
662
+ if(user_input && (!${JSON.stringify(dyn_updates)}))
647
663
  $("#copilotinteractions").append(wrapSegment('<p>'+user_input+'</p>'+fileBadge, "You"))
648
664
  $("textarea[name=userinput]").val("")
649
665
  $('form.agent-view div.next_response_scratch').html("")
@@ -652,6 +668,9 @@ const run = async (
652
668
  $("#copilotinteractions").append(res.response)
653
669
  }
654
670
  window.processCopilotResponse = processCopilotResponse;
671
+ window.final_agent_response = () => {
672
+ $("#sendbuttonicon").attr("class","far fa-paper-plane");
673
+ }
655
674
  const _agentDT = new DataTransfer();
656
675
  function setAgentFiles(files) {
657
676
  for (const f of files) _agentDT.items.add(f);
@@ -666,7 +685,11 @@ const run = async (
666
685
  } else {
667
686
  $label.addClass("me-2");
668
687
  const text = n === 1 ? _agentDT.files[0].name : n + " files";
669
- $label.html(text + ' <span class="badge text-bg-secondary" style="cursor:pointer;font-size:.65em;vertical-align:middle" onclick="clearAgentFiles()" title="Remove files">&times;</span>');
688
+ $label.html(${
689
+ isWeb(req)
690
+ ? `text + ' <span class="badge text-bg-secondary" style="cursor:pointer;font-size:.65em;vertical-align:middle" onclick="clearAgentFiles()" title="Remove files">&times;</span>'`
691
+ : `'<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">&times;</span>'`
692
+ });
670
693
  }
671
694
  }
672
695
  function clearAgentFiles() {
@@ -839,9 +862,13 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
839
862
  100,
840
863
  );
841
864
  badges.push(
842
- span(
843
- { class: "badge text-bg-info" },
844
- i({ class: "fas fa-image me-1" }),
865
+ div(
866
+ { class: "bg-secondary-subtle p-2 m-2 rounded-2" },
867
+ img({
868
+ src: `/files/resize/${50}/${50}/${file.path_to_serve}`,
869
+ class: "d-block",
870
+ onclick: `expand_thumbnail('${file.path_to_serve}', '${path.basename(file.path_to_serve)}')`,
871
+ }),
845
872
  file.filename,
846
873
  ),
847
874
  );
@@ -860,20 +887,30 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
860
887
  await getState().functions.llm_add_message.run("image", imageurl, {
861
888
  chat: run.context.interactions || [],
862
889
  });
863
- await addToContext(run, {
864
- interactions: run.context.interactions || [],
865
- });
866
890
  }
867
- fileBadges = badges.join("");
891
+ await saveInteractions(run);
892
+ fileBadges = div({ class: "d-flex" }, badges);
868
893
  }
894
+ const userInteractions = wrapSegment(p(userinput) + fileBadges, "You", true);
895
+
869
896
  await addToContext(run, {
870
897
  interactions: [
871
898
  ...(run.context.interactions || []),
872
899
  { role: "user", content: userinput },
873
900
  ],
874
- html_interactions: [wrapSegment(p(userinput) + fileBadges, "You")],
901
+ html_interactions: [userInteractions],
875
902
  });
876
903
  const dyn_updates = getState().getConfig("enable_dynamic_updates", true);
904
+ if (dyn_updates) {
905
+ getState().emitDynamicUpdate(
906
+ db.getTenantSchema(),
907
+ {
908
+ eval_js: `processCopilotResponse({response: ${JSON.stringify(userInteractions)}, run_id: ${run.id}}, true)`,
909
+ page_load_tag: req?.headers?.["page-load-tag"],
910
+ },
911
+ [req.user.id],
912
+ );
913
+ }
877
914
  const process_promise = process_interaction(
878
915
  run,
879
916
  action.configuration,
@@ -1028,4 +1065,5 @@ module.exports = {
1028
1065
  table_optional: true,
1029
1066
  run,
1030
1067
  routes: { interact, delprevrun, debug_info, skillroute, execute_user_action },
1068
+ mobile_render_server_side: true,
1031
1069
  };
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 wrapSegment = (html, who) =>
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
- : '<div class="interaction-segment"><span class="badge bg-secondary">' +
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
- const add_response = async (resp) => {
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@${
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/agents",
3
- "version": "0.6.3",
3
+ "version": "0.6.4",
4
4
  "description": "AI agents for Saltcorn",
5
5
  "main": "index.js",
6
6
  "dependencies": {