@saltcorn/agents 0.8.9 → 0.8.11

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
@@ -708,15 +708,60 @@ const run = async (
708
708
  stream ? div({ class: "next_response_scratch" }) : "",
709
709
  hasInputForm && input_form,
710
710
  style(agents_css),
711
- script(domReady(`$( "#inputuserinput" ).autogrow({paddingBottom: 20});`)),
711
+ script(
712
+ domReady(`
713
+ $("#inputuserinput" ).autogrow({paddingBottom: 20});
714
+ ensure_script_loaded("/static_assets/"+_sc_version_tag+"/mermaid.min.js", ()=>{
715
+ mermaid.initialize({ startOnLoad: false });
716
+ activate_mermaid()
717
+ })`),
718
+ ),
712
719
  script(
713
720
  `
721
+ function activate_mermaid() {
722
+ const mermaids = document.querySelectorAll('code.language-mermaid:not([data-processed])')
723
+ if(mermaids.length) {
724
+
725
+ const el0 =document.querySelector('code.language-mermaid:not([data-processed])')
726
+ const parent = el0.closest("div.copy-to-clipboard-elem")
727
+ if(!parent) return;
728
+ parent.setAttribute("data-copy-text", parent.innerText)
729
+
730
+ let processed = false
731
+ parent.querySelectorAll('code.language-mermaid:not([data-processed])').forEach(async (el) => {
732
+ try {
733
+ // parse() throws if the syntax is invalid
734
+ await mermaid.parse(el.textContent);
735
+
736
+ // Valid — safe to render
737
+ // mermaid.run() works on a live NodeList, so target this element directly
738
+ mermaid.run({ nodes: [el] });
739
+ processed = true
740
+ } catch (e) {
741
+ // Invalid — leave the <code> block completely untouched
742
+ console.warn('Mermaid syntax error (diagram left as-is):', e.message);
743
+ }
744
+ })
745
+ if(processed) activate_mermaid()
746
+ }
747
+ }
714
748
  function scrollAgentToBottom() {
715
749
  const container = document.getElementById('copilotinteractions');
716
- if (container) {
717
- if (container.scrollHeight > container.clientHeight) {
718
- container.scrollTo({ top: container.scrollHeight, behavior: 'smooth' });
719
- }
750
+ if (!container) return;
751
+ // The message list scrolls internally when its height is bounded.
752
+ if (container.scrollHeight > container.clientHeight + 2) {
753
+ container.scrollTo({ top: container.scrollHeight, behavior: 'smooth' });
754
+ }
755
+ const layout = container.closest('.modern-chat-layout');
756
+ if (layout) {
757
+ // Footer-sticky modern chat: the page scrolls while the input bar is
758
+ // position:sticky, so scrollIntoView() on the bar is a no-op (it
759
+ // always reports as already "in view"). Scroll the page down by the
760
+ // amount the chat extends past the viewport bottom, so the newest
761
+ // content + input bar end up at the bottom of the screen.
762
+ const overshoot = layout.getBoundingClientRect().bottom - window.innerHeight;
763
+ if (overshoot > 0) window.scrollBy({ top: overshoot + 8, behavior: 'smooth' });
764
+ } else {
720
765
  const inputForm = document.querySelector('form.agent-view');
721
766
  if (inputForm) inputForm.scrollIntoView({ behavior: 'smooth', block: 'end' });
722
767
  }
@@ -758,7 +803,7 @@ const run = async (
758
803
  const user_input = $("textarea[name=userinput]").val()
759
804
  if(user_input && (!${JSON.stringify(dyn_updates)}))
760
805
  $("#copilotinteractions").append(wrapSegment('<p>'+user_input+'</p>'+fileBadge, "You", true))
761
- $("textarea[name=userinput]").val("")
806
+ $("textarea[name=userinput]").val("").trigger("update.autogrow")
762
807
  $('div.next_response_scratch').html("")
763
808
  window['stream scratch ${viewname} ${rndid}'] = []
764
809
  $("button.modern-share").show()
@@ -767,6 +812,7 @@ const run = async (
767
812
  $("#copilotinteractions").append(res.response);
768
813
  scrollAgentToBottom();
769
814
  }
815
+ activate_mermaid()
770
816
  }
771
817
  window.processCopilotResponse = processCopilotResponse;
772
818
  window.final_agent_response = () => {
@@ -937,7 +983,7 @@ const run = async (
937
983
  e.preventDefault();
938
984
 
939
985
  try {
940
- await navigator.clipboard.writeText(target.innerText);
986
+ await navigator.clipboard.writeText(target.getAttribute("data-copy-text") || target.innerText);
941
987
  target.classList.add('copy-success');
942
988
  setTimeout(() => target.classList.remove('copy-success'), 1000);
943
989
  } catch (err) {
@@ -1475,6 +1521,7 @@ const debug_info = async (table_id, viewname, config, body, { req, res }) => {
1475
1521
  sysPrompt = complArgs.systemPrompt;
1476
1522
  }
1477
1523
  const apiJson = JSON.stringify(run.context.api_interactions, null, 2);
1524
+ const msgJson = JSON.stringify(run.context.interactions, null, 2);
1478
1525
  const debug_html = div(
1479
1526
  { class: "accordion", id: "debugAccordion" },
1480
1527
  div(
@@ -1506,6 +1553,50 @@ const debug_info = async (table_id, viewname, config, body, { req, res }) => {
1506
1553
  ),
1507
1554
  ),
1508
1555
  ),
1556
+ div(
1557
+ { class: "accordion-item" },
1558
+ h2(
1559
+ { class: "accordion-header", id: "debugHeadMessages" },
1560
+ button(
1561
+ {
1562
+ class: "accordion-button",
1563
+ type: "button",
1564
+ "data-bs-toggle": "collapse",
1565
+ "data-bs-target": "#debugCollapseMessages",
1566
+ "aria-expanded": "true",
1567
+ "aria-controls": "debugCollapseMessages",
1568
+ },
1569
+ "Messages",
1570
+ ),
1571
+ ),
1572
+ div(
1573
+ {
1574
+ id: "debugCollapseMessages",
1575
+ class: "accordion-collapse collapse show",
1576
+ "aria-labelledby": "debugHeadMessages",
1577
+ "data-bs-parent": "#debugAccordion",
1578
+ },
1579
+ div(
1580
+ { class: "accordion-body" },
1581
+ button(
1582
+ {
1583
+ class: "btn btn-sm btn-outline-secondary mb-2",
1584
+ onclick: `
1585
+ var t=document.getElementById('debugMessagesPre').textContent;
1586
+ navigator.clipboard.writeText(t).then(function(){
1587
+ var b=event.target;b.textContent='Copied!';
1588
+ setTimeout(function(){b.textContent='Copy to clipboard'},1500)
1589
+ })`,
1590
+ },
1591
+ "Copy to clipboard",
1592
+ ),
1593
+ pre(
1594
+ { id: "debugMessagesPre", style: "white-space:pre-wrap" },
1595
+ text(escapeHtml(msgJson)),
1596
+ ),
1597
+ ),
1598
+ ),
1599
+ ),
1509
1600
  div(
1510
1601
  { class: "accordion-item" },
1511
1602
  h2(
@@ -1516,7 +1607,7 @@ const debug_info = async (table_id, viewname, config, body, { req, res }) => {
1516
1607
  type: "button",
1517
1608
  "data-bs-toggle": "collapse",
1518
1609
  "data-bs-target": "#debugCollapseAPI",
1519
- "aria-expanded": "true",
1610
+ "aria-expanded": "false",
1520
1611
  "aria-controls": "debugCollapseAPI",
1521
1612
  },
1522
1613
  "API interactions",
package/agents.css CHANGED
@@ -411,19 +411,65 @@ p.prevrun_content {
411
411
  Everything else uses Bootstrap utility classes in the markup; only
412
412
  the rules below are custom and cannot be expressed via utilities. */
413
413
  .modern-chat-shell.chat-wide .modern-sessions-offcanvas {
414
- position: static !important;
414
+ position: sticky !important;
415
+ top: 1rem;
416
+ align-self: flex-start;
417
+ max-height: calc(100vh - 2rem);
418
+ overflow-y: auto;
415
419
  transform: none !important;
420
+ transition: none !important;
416
421
  visibility: visible !important;
417
422
  z-index: auto !important;
418
423
  width: 260px;
419
424
  max-width: 260px;
420
425
  flex: 0 0 260px;
421
426
  background: transparent;
422
- height: auto;
423
427
  box-shadow: none;
424
428
  }
425
429
  .modern-chat-shell.chat-wide .modern-chat-hamburger { display: none; }
426
430
 
431
+ /* Slim, subtle scrollbars for the scrollable chat areas (sessions sidebar
432
+ and the message list). Firefox uses scrollbar-width/-color; WebKit/Blink
433
+ use the ::-webkit-scrollbar pseudo-elements. The thumb is mostly
434
+ transparent and only becomes clearly visible on hover, so the scrollbar
435
+ doesn't visually clutter the layout. */
436
+ .modern-chat-shell.chat-wide .modern-sessions-offcanvas,
437
+ .modern-chat-layout #copilotinteractions {
438
+ scrollbar-width: thin;
439
+ scrollbar-color: transparent transparent;
440
+ }
441
+ .modern-chat-shell.chat-wide .modern-sessions-offcanvas:hover,
442
+ .modern-chat-layout #copilotinteractions:hover {
443
+ scrollbar-color: rgba(0, 0, 0, 0.25) transparent;
444
+ }
445
+ .modern-chat-shell.chat-wide .modern-sessions-offcanvas::-webkit-scrollbar,
446
+ .modern-chat-layout #copilotinteractions::-webkit-scrollbar {
447
+ width: 6px;
448
+ height: 6px;
449
+ }
450
+ .modern-chat-shell.chat-wide
451
+ .modern-sessions-offcanvas::-webkit-scrollbar-track,
452
+ .modern-chat-layout #copilotinteractions::-webkit-scrollbar-track {
453
+ background: transparent;
454
+ }
455
+ .modern-chat-shell.chat-wide
456
+ .modern-sessions-offcanvas::-webkit-scrollbar-thumb,
457
+ .modern-chat-layout #copilotinteractions::-webkit-scrollbar-thumb {
458
+ background-color: transparent;
459
+ border-radius: 10px;
460
+ transition: background-color 0.2s ease;
461
+ }
462
+ .modern-chat-shell.chat-wide
463
+ .modern-sessions-offcanvas:hover::-webkit-scrollbar-thumb,
464
+ .modern-chat-layout #copilotinteractions:hover::-webkit-scrollbar-thumb {
465
+ background-color: rgba(0, 0, 0, 0.25);
466
+ }
467
+ .modern-chat-shell.chat-wide
468
+ .modern-sessions-offcanvas::-webkit-scrollbar-thumb:hover,
469
+ .modern-chat-layout #copilotinteractions::-webkit-scrollbar-thumb:hover {
470
+ background-color: rgba(0, 0, 0, 0.4);
471
+ }
472
+
427
473
  /* Bootstrap has no `:empty` utility — collapse the interaction list when
428
474
  it has no content so the input form sits directly under the header. */
429
475
  .modern-chat-layout #copilotinteractions:empty { display: none; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/agents",
3
- "version": "0.8.9",
3
+ "version": "0.8.11",
4
4
  "description": "AI agents for Saltcorn",
5
5
  "main": "index.js",
6
6
  "dependencies": {