AkurAI Build
Menu

Public repository / fee5b6c2cde89fa6bf8dc51068af7336b56a88b8

AkurAI-Framework / site/frontend/ai/runtime/reasoning.js

Latest change 22a320a8e40a1822b386e2d5fd9bcf3537282876 - feat(ai): generative-UI / tool-call runtime + primitives by Ólafur Búi Ólafsson

// reasoning.js — collapsible reasoning / thinking block for assistant turns.
//
// Renders the model's intermediate reasoning behind a native <details> toggle
// (the one HTML element markdown can't express — sanctioned by house rules).
// Closed by default; toggling emits a `reasoning:toggle` CustomEvent.
//
// createReasoning(opts) -> {
//   element,                 // <details class="toolui-reasoning">
//   setText(text), setOpen(bool), isOpen(),
// }
//   opts = {
//     text = "",             // reasoning content (plain text; newlines kept)
//     summary = "Reasoning", // the clickable summary label
//     open = false,
//     onToggle(open),
//   }

function createReasoning(opts) {
  const o = opts || {};

  const element = document.createElement("details");
  element.className = "toolui-reasoning";
  if (o.open) element.open = true;

  const summary = document.createElement("summary");
  summary.className = "toolui-reasoning-summary muted";
  summary.style.cursor = "pointer";
  summary.textContent = o.summary || "Reasoning";
  element.appendChild(summary);

  const body = document.createElement("div");
  body.className = "toolui-reasoning-body small muted";
  body.style.whiteSpace = "pre-wrap";
  body.style.marginTop = "8px";
  body.textContent = o.text || "";
  element.appendChild(body);

  element.addEventListener("toggle", () => {
    const open = element.open;
    element.dispatchEvent(new CustomEvent("reasoning:toggle", { detail: { open }, bubbles: true }));
    if (typeof o.onToggle === "function") o.onToggle(open);
    console.log("[runtime] reasoning:toggle", open);
  });

  return {
    element,
    setText: (text) => {
      body.textContent = text || "";
    },
    setOpen: (open) => {
      element.open = !!open;
    },
    isOpen: () => element.open,
  };
}

const ToolUiReasoning = { createReasoning };
if (typeof window !== "undefined") window.ToolUiReasoning = ToolUiReasoning;

export { createReasoning };
export default ToolUiReasoning;