@saltcorn/agents 0.7.0 → 0.7.2

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 CHANGED
@@ -4,6 +4,7 @@ const { get_skills, process_interaction } = require("./common");
4
4
  const { applyAsync } = require("@saltcorn/data/utils");
5
5
  const WorkflowRun = require("@saltcorn/data/models/workflow_run");
6
6
  const { interpolate } = require("@saltcorn/data/utils");
7
+ const { getState } = require("@saltcorn/data/db/state");
7
8
 
8
9
  module.exports = {
9
10
  disableInBuilder: true,
@@ -22,12 +23,10 @@ module.exports = {
22
23
  }
23
24
  }
24
25
  }
25
- const tables_with_json_field = (await Table.find({})).filter(
26
- (table) =>
27
- !table.external &&
28
- !table.provider_name &&
29
- table.fields.some((f) => f.type?.name === "JSON"),
30
- );
26
+ const llm_cfg_fun = getState().functions.llm_get_configuration;
27
+ const alt_config_options = llm_cfg_fun
28
+ ? llm_cfg_fun.run().alt_config_names || []
29
+ : [];
31
30
  return [
32
31
  ...(table
33
32
  ? [
@@ -50,6 +49,17 @@ module.exports = {
50
49
  type: "String",
51
50
  fieldview: "textarea",
52
51
  },
52
+ ...(alt_config_options.length
53
+ ? [
54
+ {
55
+ name: "alt_config",
56
+ label: "Alternative configuration",
57
+ sublabel: "Use this configuration for LLM interactions",
58
+ type: "String",
59
+ attributes: { options: alt_config_options },
60
+ },
61
+ ]
62
+ : []),
53
63
  {
54
64
  name: "model",
55
65
  label: "Model",
package/agent-view.js CHANGED
@@ -50,7 +50,7 @@ const {
50
50
  saveInteractions,
51
51
  } = require("./common");
52
52
  const MarkdownIt = require("markdown-it"),
53
- md = new MarkdownIt();
53
+ md = new MarkdownIt({ html: true, breaks: true, linkify: true });
54
54
  const { isWeb, escapeHtml } = require("@saltcorn/data/utils");
55
55
  const path = require("path");
56
56
 
@@ -119,7 +119,7 @@ const configuration_workflow = (req) =>
119
119
  type: "String",
120
120
  required: true,
121
121
  attributes: {
122
- options: ["Standard", "No card"],
122
+ options: ["Standard", "No card", "Modern chat", "Modern chat - no card"],
123
123
  },
124
124
  },
125
125
  {
@@ -180,11 +180,11 @@ const uploadForm = (viewname, req) =>
180
180
  span({ class: "ms-2 filename-label" }),
181
181
  );
182
182
 
183
- const realTimeCollabScript = (viewname, rndid) => {
183
+ const realTimeCollabScript = (viewname, rndid, layout) => {
184
184
  const view = View.findOne({ name: viewname });
185
185
  return script(
186
186
  domReady(`
187
- const md = markdownit()
187
+ const md = markdownit({html: true, breaks: true, linkify: true})
188
188
  window['stream scratch ${viewname} ${rndid}'] = []
189
189
  const callback = () => {
190
190
  const collabCfg = {
@@ -193,8 +193,11 @@ const realTimeCollabScript = (viewname, rndid) => {
193
193
  "STREAM_CHUNK",
194
194
  )}' + \`?page_load_tag=\${_sc_pageloadtag}\`]: async (data) => {
195
195
  window['stream scratch ${viewname} ${rndid}'].push(data.content)
196
+ const rendered = md.render(window['stream scratch ${viewname} ${rndid}'].join(""));
196
197
  $('form.agent-view div.next_response_scratch').html(
197
- md.render(window['stream scratch ${viewname} ${rndid}'].join(""))
198
+ (${JSON.stringify(layout || "")} || "").startsWith("Modern chat")
199
+ ? '<div class="chat-message chat-assistant"><div class="chat-avatar"><i class="fas fa-robot"></i></div><div class="chat-bubble">' + rendered + '</div></div>'
200
+ : rendered
198
201
  );
199
202
  }
200
203
  }
@@ -284,26 +287,24 @@ const run = async (
284
287
  const image_url = interact.content[0].image_url.url;
285
288
  if (image_url.startsWith("data"))
286
289
  interactMarkups.push(
287
- div(
288
- { class: "interaction-segment" },
289
- span({ class: "badge bg-secondary" }, "You"),
290
- "File",
291
- ),
290
+ wrapSegment("File", "You", true, layout),
292
291
  );
293
292
  else
294
293
  interactMarkups.push(
295
- div(
296
- { class: "interaction-segment" },
297
- span({ class: "badge bg-secondary" }, "You"),
294
+ wrapSegment(
298
295
  a({ href: image_url, target: "_blank" }, "File"),
296
+ "You",
297
+ true,
298
+ layout,
299
299
  ),
300
300
  );
301
301
  } else
302
302
  interactMarkups.push(
303
- div(
304
- { class: "interaction-segment" },
305
- span({ class: "badge bg-secondary" }, "You"),
303
+ wrapSegment(
306
304
  md.render(interact.content),
305
+ "You",
306
+ true,
307
+ layout,
307
308
  ),
308
309
  );
309
310
  break;
@@ -329,6 +330,8 @@ const run = async (
329
330
  rendered,
330
331
  ),
331
332
  action.name,
333
+ false,
334
+ layout,
332
335
  ),
333
336
  );
334
337
  }
@@ -354,6 +357,8 @@ const run = async (
354
357
  rendered,
355
358
  ),
356
359
  action.name,
360
+ false,
361
+ layout,
357
362
  ),
358
363
  );
359
364
  }
@@ -364,14 +369,15 @@ const run = async (
364
369
  typeof interact.content?.content === "string"
365
370
  )
366
371
  interactMarkups.push(
367
- div(
368
- { class: "interaction-segment" },
369
- span({ class: "badge bg-secondary" }, action.name),
372
+ wrapSegment(
370
373
  typeof interact.content === "string"
371
374
  ? md.render(interact.content)
372
375
  : typeof interact.content?.content === "string"
373
376
  ? md.render(interact.content.content)
374
377
  : interact.content,
378
+ action.name,
379
+ false,
380
+ layout,
375
381
  ),
376
382
  );
377
383
  break;
@@ -400,6 +406,8 @@ const run = async (
400
406
  markupContent,
401
407
  ),
402
408
  action.name,
409
+ false,
410
+ layout,
403
411
  ),
404
412
  );
405
413
  }
@@ -484,63 +492,110 @@ const run = async (
484
492
  explainer && small({ class: "explainer" }, i(explainer)),
485
493
  ),
486
494
  stream &&
487
- realTimeCollabScript(viewname, rndid) +
495
+ realTimeCollabScript(viewname, rndid, layout) +
488
496
  div({ class: "next_response_scratch" }),
489
497
  );
490
498
 
499
+ const isModernSidebar = layout && layout.startsWith("Modern chat");
491
500
  const prev_runs_side_bar = show_prev_runs
492
501
  ? div(
493
- div(
494
- {
495
- class: "d-flex flex-wrap justify-content-between align-middle mb-2",
496
- },
497
- div(
498
- { class: "d-flex" },
499
- i({
500
- class: "fas fa-caret-down me-1 session-open-sessions",
501
- onclick: "close_session_list()",
502
- }),
503
- h5(req.__("Sessions")),
504
- ),
505
- button(
506
- {
507
- type: "button",
508
- class: "btn btn-secondary btn-sm pt-0 pb-1",
509
- style: "font-size: 0.9em;height:1.5em",
510
- onclick: "unset_state_field('run_id')",
511
- title: "New session",
512
- },
513
- i({ class: "fas fa-redo fa-sm" }),
514
- ),
515
- ),
516
- prevRuns.map((run) =>
517
- div(
518
- {
519
- onclick: `set_state_field('run_id',${run.id})`,
520
- class: "prevcopilotrun border p-2",
521
- },
522
- div(
523
- { class: "d-flex justify-content-between" },
524
- span(
525
- { class: "text-truncate", style: "min-width:0" },
526
- localeDateTime(run.started_at),
502
+ { class: isModernSidebar ? "modern-sessions" : "" },
503
+ isModernSidebar
504
+ ? div(
505
+ { class: "modern-sessions-header" },
506
+ div(
507
+ { class: "d-flex align-items-center" },
508
+ i({
509
+ class: "fas fa-caret-down me-2 session-open-sessions",
510
+ onclick: "close_session_list()",
511
+ }),
512
+ i({ class: "fas fa-comments me-2 text-primary" }),
513
+ span({ class: "fw-semibold" }, req.__("Sessions")),
527
514
  ),
528
- i({
529
- class: "far fa-trash-alt",
530
- onclick: `delprevrun(event, ${run.id})`,
531
- }),
532
- ),
533
-
534
- p(
535
- { class: "prevrun_content" },
536
- escapeHtml(
537
- run.context.interactions
538
- .find((i) => typeof i?.content === "string")
539
- ?.content?.substring?.(0, 80),
515
+ button(
516
+ {
517
+ type: "button",
518
+ class: "btn btn-primary btn-sm rounded-pill px-3",
519
+ onclick: "unset_state_field('run_id')",
520
+ title: "New chat",
521
+ },
522
+ i({ class: "fas fa-plus me-1" }),
523
+ "New",
524
+ ),
525
+ )
526
+ : div(
527
+ {
528
+ class: "d-flex flex-wrap justify-content-between align-middle mb-2",
529
+ },
530
+ div(
531
+ { class: "d-flex" },
532
+ i({
533
+ class: "fas fa-caret-down me-1 session-open-sessions",
534
+ onclick: "close_session_list()",
535
+ }),
536
+ h5(req.__("Sessions")),
537
+ ),
538
+ button(
539
+ {
540
+ type: "button",
541
+ class: "btn btn-secondary btn-sm pt-0 pb-1",
542
+ style: "font-size: 0.9em;height:1.5em",
543
+ onclick: "unset_state_field('run_id')",
544
+ title: "New session",
545
+ },
546
+ i({ class: "fas fa-redo fa-sm" }),
540
547
  ),
541
548
  ),
542
- ),
543
- ),
549
+ prevRuns.map((run) => {
550
+ const isActive = state.run_id && +state.run_id === run.id;
551
+ const preview = escapeHtml(
552
+ run.context.interactions
553
+ .find((ix) => typeof ix?.content === "string")
554
+ ?.content?.substring?.(0, 80),
555
+ );
556
+ return isModernSidebar
557
+ ? div(
558
+ {
559
+ onclick: `set_state_field('run_id',${run.id})`,
560
+ class:
561
+ "prevcopilotrun modern-session-item" +
562
+ (isActive ? " active-session" : ""),
563
+ },
564
+ div(
565
+ { class: "d-flex justify-content-between align-items-center mb-1" },
566
+ small(
567
+ { class: "text-muted text-truncate", style: "min-width:0" },
568
+ localeDateTime(run.started_at),
569
+ ),
570
+ i({
571
+ class: "far fa-trash-alt text-muted",
572
+ onclick: `delprevrun(event, ${run.id})`,
573
+ }),
574
+ ),
575
+ p({ class: "prevrun_content mb-0" }, preview),
576
+ )
577
+ : div(
578
+ {
579
+ onclick: `set_state_field('run_id',${run.id})`,
580
+ class: "prevcopilotrun border p-2",
581
+ },
582
+ div(
583
+ { class: "d-flex justify-content-between" },
584
+ span(
585
+ { class: "text-truncate", style: "min-width:0" },
586
+ localeDateTime(run.started_at),
587
+ ),
588
+ i({
589
+ class: "far fa-trash-alt",
590
+ onclick: `delprevrun(event, ${run.id})`,
591
+ }),
592
+ ),
593
+ p(
594
+ { class: "prevrun_content" },
595
+ preview,
596
+ ),
597
+ );
598
+ }),
544
599
  )
545
600
  : "";
546
601
 
@@ -629,7 +684,199 @@ const run = async (
629
684
  overflow: hidden;
630
685
  margin-bottom: 0px;
631
686
  display: block;
632
- text-overflow: ellipsis;}`,
687
+ text-overflow: ellipsis;}
688
+ /* Modern Chat Layout */
689
+ .modern-chat-layout {
690
+ display: flex;
691
+ flex-direction: column;
692
+ height: 100%;
693
+ }
694
+ .modern-chat-layout #copilotinteractions {
695
+ max-height: 70vh;
696
+ overflow-y: auto;
697
+ padding: 1rem;
698
+ display: flex;
699
+ flex-direction: column;
700
+ gap: 0.75rem;
701
+ }
702
+ .modern-chat-layout .chat-message {
703
+ display: flex;
704
+ gap: 0.5rem;
705
+ max-width: 85%;
706
+ align-items: flex-start;
707
+ }
708
+ .modern-chat-layout .chat-message.chat-user {
709
+ align-self: flex-end;
710
+ flex-direction: row-reverse;
711
+ }
712
+ .modern-chat-layout .chat-message.chat-assistant {
713
+ align-self: flex-start;
714
+ }
715
+ .modern-chat-layout .chat-avatar {
716
+ width: 2rem;
717
+ height: 2rem;
718
+ border-radius: 50%;
719
+ display: flex;
720
+ align-items: center;
721
+ justify-content: center;
722
+ flex-shrink: 0;
723
+ font-size: 0.85rem;
724
+ background: var(--tblr-secondary-bg-subtle, var(--bs-secondary-bg-subtle, #e9ecef));
725
+ color: var(--tblr-secondary-color, var(--bs-secondary-color, #6c757d));
726
+ }
727
+ .modern-chat-layout .chat-user .chat-avatar {
728
+ background: #0d6efd;
729
+ color: #fff;
730
+ }
731
+ .modern-chat-layout .chat-bubble {
732
+ padding: 0.6rem 1rem;
733
+ border-radius: 1rem;
734
+ line-height: 1.5;
735
+ word-wrap: break-word;
736
+ overflow-wrap: break-word;
737
+ }
738
+ .modern-chat-layout .chat-user .chat-bubble {
739
+ background: #0d6efd;
740
+ color: #fff;
741
+ border-bottom-right-radius: 0.25rem;
742
+ }
743
+ .modern-chat-layout .chat-assistant .chat-bubble {
744
+ background: var(--tblr-secondary-bg-subtle, var(--bs-secondary-bg-subtle, #f0f2f5));
745
+ color: var(--tblr-body-color, var(--bs-body-color, #212529));
746
+ border-bottom-left-radius: 0.25rem;
747
+ }
748
+ /* Markdown content inside bubbles */
749
+ .modern-chat-layout .chat-bubble h1,
750
+ .modern-chat-layout .chat-bubble h2,
751
+ .modern-chat-layout .chat-bubble h3,
752
+ .modern-chat-layout .chat-bubble h4 {
753
+ margin-top: 0.5rem;
754
+ margin-bottom: 0.25rem;
755
+ }
756
+ .modern-chat-layout .chat-bubble h1 { font-size: 1.3rem; }
757
+ .modern-chat-layout .chat-bubble h2 { font-size: 1.15rem; }
758
+ .modern-chat-layout .chat-bubble h3 { font-size: 1.05rem; }
759
+ .modern-chat-layout .chat-bubble h4 { font-size: 1rem; }
760
+ .modern-chat-layout .chat-bubble p {
761
+ margin-bottom: 0.4rem;
762
+ }
763
+ .modern-chat-layout .chat-bubble p:last-child {
764
+ margin-bottom: 0;
765
+ }
766
+ .modern-chat-layout .chat-bubble ul,
767
+ .modern-chat-layout .chat-bubble ol {
768
+ padding-left: 1.5rem;
769
+ margin-bottom: 0.4rem;
770
+ }
771
+ .modern-chat-layout .chat-bubble table {
772
+ width: 100%;
773
+ border-collapse: collapse;
774
+ margin: 0.5rem 0;
775
+ font-size: 0.9em;
776
+ }
777
+ .modern-chat-layout .chat-bubble table th,
778
+ .modern-chat-layout .chat-bubble table td {
779
+ border: 1px solid rgba(0,0,0,0.15);
780
+ padding: 0.3rem 0.5rem;
781
+ }
782
+ .modern-chat-layout .chat-bubble table th {
783
+ background: rgba(0,0,0,0.05);
784
+ font-weight: 600;
785
+ }
786
+ .modern-chat-layout .chat-bubble pre {
787
+ background: rgba(0,0,0,0.06);
788
+ padding: 0.5rem;
789
+ border-radius: 0.5rem;
790
+ overflow-x: auto;
791
+ margin: 0.4rem 0;
792
+ }
793
+ .modern-chat-layout .chat-bubble code {
794
+ font-size: 0.88em;
795
+ }
796
+ .modern-chat-layout .chat-bubble p > code {
797
+ background: rgba(0,0,0,0.06);
798
+ padding: 0.1rem 0.3rem;
799
+ border-radius: 0.25rem;
800
+ }
801
+ .modern-chat-layout .chat-user .chat-bubble pre {
802
+ background: rgba(255,255,255,0.15);
803
+ }
804
+ .modern-chat-layout .chat-user .chat-bubble p > code {
805
+ background: rgba(255,255,255,0.15);
806
+ }
807
+ .modern-chat-layout .chat-user .chat-bubble table th,
808
+ .modern-chat-layout .chat-user .chat-bubble table td {
809
+ border-color: rgba(255,255,255,0.25);
810
+ }
811
+ .modern-chat-layout .chat-user .chat-bubble table th {
812
+ background: rgba(255,255,255,0.1);
813
+ }
814
+ /* Input area for modern chat */
815
+ .modern-chat-layout .copilot-entry {
816
+ border-top: 1px solid var(--tblr-border-color, var(--bs-border-color, #dee2e6));
817
+ padding-top: 0.75rem;
818
+ margin-top: 0.5rem;
819
+ }
820
+ .modern-chat-layout .copilot-entry textarea {
821
+ border-radius: 1.5rem;
822
+ padding: 0.6rem 1rem;
823
+ resize: none;
824
+ }
825
+ /* Streaming scratch in modern chat */
826
+ .modern-chat-layout .next_response_scratch {
827
+ padding: 0 1rem;
828
+ }
829
+ .modern-chat-layout .next_response_scratch:not(:empty) {
830
+ margin-bottom: 0.5rem;
831
+ }
832
+ /* Interaction segment (tool cards) inside modern chat */
833
+ .modern-chat-layout .interaction-segment {
834
+ border-top: none;
835
+ }
836
+ /* Modern Sessions Sidebar */
837
+ .modern-sessions-header {
838
+ display: flex;
839
+ align-items: center;
840
+ justify-content: space-between;
841
+ padding: 0.6rem 0.75rem;
842
+ margin-bottom: 0.75rem;
843
+ background: var(--tblr-secondary-bg-subtle, var(--bs-secondary-bg-subtle, #f8f9fa));
844
+ border-radius: 0.75rem;
845
+ border-bottom: 1px solid var(--tblr-border-color, var(--bs-border-color, #dee2e6));
846
+ position: sticky;
847
+ top: 0;
848
+ z-index: 1;
849
+ }
850
+ .modern-sessions .modern-session-item {
851
+ border-radius: 0.75rem;
852
+ padding: 0.65rem 0.75rem;
853
+ margin-bottom: 0.4rem;
854
+ border: 1px solid var(--tblr-border-color, var(--bs-border-color, #dee2e6));
855
+ cursor: pointer;
856
+ transition: all 0.15s ease;
857
+ }
858
+ .modern-sessions .modern-session-item:hover {
859
+ box-shadow: 0 2px 8px rgba(0,0,0,0.07);
860
+ background-color: var(--tblr-secondary-bg-subtle, var(--bs-secondary-bg-subtle, #f8f9fa));
861
+ }
862
+ .modern-sessions .modern-session-item.active-session {
863
+ border-left: 3px solid #0d6efd;
864
+ background-color: rgba(13, 110, 253, 0.05);
865
+ }
866
+ .modern-sessions .modern-session-item i.fa-trash-alt {
867
+ display: none;
868
+ font-size: 0.8em;
869
+ }
870
+ .modern-sessions .modern-session-item:hover i.fa-trash-alt {
871
+ display: inline;
872
+ }
873
+ .modern-sessions .modern-session-item .prevrun_content {
874
+ font-size: 0.85em;
875
+ color: var(--tblr-secondary-color, var(--bs-secondary-color, #6c757d));
876
+ white-space: nowrap;
877
+ overflow: hidden;
878
+ text-overflow: ellipsis;
879
+ }`,
633
880
  ),
634
881
  script(domReady(`$( "#inputuserinput" ).autogrow({paddingBottom: 20});`)),
635
882
  script(
@@ -661,10 +908,13 @@ const run = async (
661
908
  const $runidin= $("input[name=run_id")
662
909
  if(res.run_id && (!$runidin.val() || $runidin.val()=="undefined"))
663
910
  $runidin.val(res.run_id);
664
- const wrapSegment = (html, who) => '<div class="interaction-segment"><span class="badge bg-secondary">'+who+'</span>'+html+'</div>'
911
+ const currentLayout = ${JSON.stringify(layout || "")};
912
+ const wrapSegment = (html, who, toRight) => currentLayout.startsWith("Modern chat")
913
+ ? '<div class="chat-message '+(toRight ? 'chat-user' : 'chat-assistant')+'"><div class="chat-avatar"><i class="fas '+(toRight ? 'fa-user' : 'fa-robot')+'"></i></div><div class="chat-bubble">'+html+'</div></div>'
914
+ : '<div class="interaction-segment '+(toRight ? 'to-right' : '')+'"><div><div class="badgewrap"><span class="badge bg-secondary">'+who+'</span></div>'+html+'</div></div>'
665
915
  const user_input = $("textarea[name=userinput]").val()
666
916
  if(user_input && (!${JSON.stringify(dyn_updates)}))
667
- $("#copilotinteractions").append(wrapSegment('<p>'+user_input+'</p>'+fileBadge, "You"))
917
+ $("#copilotinteractions").append(wrapSegment('<p>'+user_input+'</p>'+fileBadge, "You", true))
668
918
  $("textarea[name=userinput]").val("")
669
919
  $('form.agent-view div.next_response_scratch').html("")
670
920
  window['stream scratch ${viewname} ${rndid}'] = []
@@ -804,10 +1054,15 @@ const run = async (
804
1054
  initial_q && domReady("$('form.copilot').submit()"),
805
1055
  ),
806
1056
  );
1057
+ const isModern = layout && layout.startsWith("Modern chat");
807
1058
  const main_chat =
808
- layout === "No card"
809
- ? div({ class: "mx-1" }, main_inner)
810
- : div({ class: "card" }, div({ class: "card-body" }, main_inner));
1059
+ layout === "Modern chat"
1060
+ ? div({ class: "card" }, div({ class: "card-body modern-chat-layout" }, main_inner))
1061
+ : layout === "Modern chat - no card"
1062
+ ? div({ class: "modern-chat-layout" }, main_inner)
1063
+ : layout === "No card"
1064
+ ? div({ class: "mx-1" }, main_inner)
1065
+ : div({ class: "card" }, div({ class: "card-body" }, main_inner));
811
1066
 
812
1067
  return show_prev_runs
813
1068
  ? div(
@@ -900,6 +1155,7 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
900
1155
  p(escapeHtml(userinput)) + fileBadges,
901
1156
  "You",
902
1157
  true,
1158
+ config.layout,
903
1159
  );
904
1160
 
905
1161
  await addToContext(run, {
package/common.js CHANGED
@@ -6,7 +6,7 @@ const { interpolate } = require("@saltcorn/data/utils");
6
6
  const db = require("@saltcorn/data/db");
7
7
 
8
8
  const MarkdownIt = require("markdown-it"),
9
- md = new MarkdownIt();
9
+ md = new MarkdownIt({ html: true, breaks: true, linkify: true });
10
10
 
11
11
  const nubBy = (f, xs) => {
12
12
  const vs = new Set();
@@ -141,6 +141,7 @@ const getCompletionArguments = async (
141
141
  if (tools.length === 0) tools = undefined;
142
142
  const complArgs = { tools, systemPrompt: sysPrompts.join("\n\n") };
143
143
  if (config.model) complArgs.model = config.model;
144
+ if (config.alt_config) complArgs.alt_config = config.alt_config;
144
145
  return complArgs;
145
146
  };
146
147
 
@@ -193,14 +194,19 @@ const saveInteractions = async (run) => {
193
194
  });
194
195
  };
195
196
 
196
- const wrapSegment = (html, who, to_right) =>
197
+ const wrapSegment = (html, who, to_right, layout) =>
197
198
  who === null
198
199
  ? html
199
- : `<div class="interaction-segment ${to_right ? "to-right" : ""}"><div><div class="badgewrap"><span class="badge bg-secondary">` +
200
- who +
201
- "</span></div>" +
202
- html +
203
- "</div></div>";
200
+ : layout && layout.startsWith("Modern chat")
201
+ ? `<div class="chat-message ${to_right ? "chat-user" : "chat-assistant"}">` +
202
+ `<div class="chat-avatar"><i class="fas ${to_right ? "fa-user" : "fa-robot"}"></i></div>` +
203
+ `<div class="chat-bubble">${html}</div>` +
204
+ `</div>`
205
+ : `<div class="interaction-segment ${to_right ? "to-right" : ""}"><div><div class="badgewrap"><span class="badge bg-secondary">` +
206
+ who +
207
+ "</span></div>" +
208
+ html +
209
+ "</div></div>";
204
210
 
205
211
  const wrapCard = (title, ...inners) =>
206
212
  span({ class: "badge bg-info ms-1" }, title) +
@@ -221,7 +227,7 @@ const process_interaction = async (
221
227
  agentsViewCfg = { stream: false },
222
228
  dyn_updates = false,
223
229
  ) => {
224
- const { stream, viewname } = agentsViewCfg;
230
+ const { stream, viewname, layout } = agentsViewCfg;
225
231
  const sysState = getState();
226
232
  const complArgs = await getCompletionArguments(
227
233
  config,
@@ -310,6 +316,8 @@ const process_interaction = async (
310
316
  rendered,
311
317
  ),
312
318
  agent_label,
319
+ false,
320
+ layout,
313
321
  ),
314
322
  );
315
323
  }
@@ -318,7 +326,7 @@ const process_interaction = async (
318
326
  add_response(
319
327
  req.disable_markdown_render
320
328
  ? answer
321
- : wrapSegment(md.render(answer.content), agent_label),
329
+ : wrapSegment(md.render(answer.content), agent_label, false, layout),
322
330
  );
323
331
  }
324
332
 
@@ -331,7 +339,7 @@ const process_interaction = async (
331
339
  add_response(
332
340
  req.disable_markdown_render
333
341
  ? answer
334
- : wrapSegment(md.render(answer.content), agent_label),
342
+ : wrapSegment(md.render(answer.content), agent_label, false, layout),
335
343
  );
336
344
  //const actions = [];
337
345
  let hasResult = false;
@@ -378,6 +386,8 @@ const process_interaction = async (
378
386
  rendered,
379
387
  ),
380
388
  agent_label,
389
+ false,
390
+ layout,
381
391
  ),
382
392
  );
383
393
  }
@@ -403,6 +413,8 @@ const process_interaction = async (
403
413
  rendered,
404
414
  ),
405
415
  agent_label,
416
+ false,
417
+ layout,
406
418
  ),
407
419
  );
408
420
  }
@@ -449,6 +461,7 @@ const process_interaction = async (
449
461
  chat,
450
462
  appendToChat: true,
451
463
  systemPrompt,
464
+ alt_config: config.alt_config,
452
465
  ...opts,
453
466
  });
454
467
  },
@@ -477,13 +490,18 @@ const process_interaction = async (
477
490
  ],
478
491
  });
479
492
  if (postprocres.add_response) {
493
+ const renderedAddResponse = typeof postprocres.add_response === "string"
494
+ ? md.render(postprocres.add_response)
495
+ : postprocres.add_response;
480
496
  add_response(
481
497
  wrapSegment(
482
498
  wrapCard(
483
499
  tool.skill.skill_label || tool.skill.constructor.skill_name,
484
- postprocres.add_response,
500
+ renderedAddResponse,
485
501
  ),
486
502
  agent_label,
503
+ false,
504
+ layout,
487
505
  ),
488
506
  );
489
507
  //replace tool response with this
@@ -561,7 +579,7 @@ const process_interaction = async (
561
579
  add_response(
562
580
  req.disable_markdown_render
563
581
  ? answer
564
- : wrapSegment(md.render(answer), agent_label),
582
+ : wrapSegment(md.render(answer), agent_label, false, layout),
565
583
  );
566
584
  if (dyn_updates)
567
585
  getState().emitDynamicUpdate(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/agents",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "AI agents for Saltcorn",
5
5
  "main": "index.js",
6
6
  "dependencies": {