import { h as head, a as attr_class, e as ensure_array_like, s as stringify, b as attr } from './index2-CzosXNJA.js';
import { p as page, g as goto } from './index3-DWsxdehH.js';
import { B as Button } from './Button-Byk8IDvI.js';
import { D as Dropdown } from './Dropdown-CJ9m5usm.js';
import { I as Icon } from './Link-BxAwzNX6.js';
import { X as escape_html } from './context-BZ_07CFR.js';
import { o as onDestroy, T as Tabs, a as Tab } from './Tab-Bkjowzww.js';
import { C as ContextEditor } from './ContextEditor-BUTyqJ-R.js';
import { P as Panel } from './Panel-D5AI50iS.js';
import { I as Input } from './Input-CN285S9J.js';
import 'nunjucks';
import { A as AgentSidebar } from './AgentSidebar-DRTSgEv8.js';
import { g as getAgentsContext } from './agents-context-BFekPmHw.js';
import './state.svelte-Yu4RD6aK.js';
import './utils-KcIDVAAe.js';
import './index-FgxKh3J4.js';
import './html-FW6Ia4bL.js';
import 'js-yaml';

function History($$renderer, $$props) {
  $$renderer.component(($$renderer2) => {
    let {
      agentStates,
      currentState,
      onSelectState,
      class: className = ""
    } = $$props;
    let isOpen = false;
    let anchorEl = null;
    function toggleDropdown() {
      isOpen = !isOpen;
    }
    function handleSelectState(stateId) {
      onSelectState(stateId);
      isOpen = false;
    }
    function getUserMessage(state) {
      const raw = state.userMessage;
      if (raw == null) return "No message";
      const msg = (typeof raw === "string" ? raw : String(raw)).trim();
      return msg || "No message";
    }
    function truncateMessage(message, maxLength = 80, ellipsis = "…") {
      if (!message) return "";
      if (message.length <= maxLength) return message;
      const slice = message.slice(0, maxLength + 1);
      const lastSpace = Math.max(slice.lastIndexOf(" "), slice.lastIndexOf(" "), slice.lastIndexOf("	"), slice.lastIndexOf("\n"), slice.lastIndexOf("\r"));
      const cut = lastSpace > 0 ? slice.slice(0, lastSpace) : message.slice(0, maxLength);
      return cut.trimEnd() + ellipsis;
    }
    function handleKeyDown(event) {
      if (event.key === "ArrowDown" && !isOpen) {
        isOpen = true;
        event.preventDefault();
      } else if (event.key === "ArrowUp" && isOpen) {
        isOpen = false;
        event.preventDefault();
      }
    }
    let selectedState = agentStates.find((s) => s.id === currentState) ?? null;
    let triggerTitle = selectedState?.name ?? "History";
    let $$settled = true;
    let $$inner_renderer;
    function $$render_inner($$renderer3) {
      $$renderer3.push(`<div${attr_class(`relative ${className}`)}>`);
      Button($$renderer3, {
        variant: "outlined",
        size: "medium",
        "aria-expanded": isOpen,
        "aria-haspopup": "listbox",
        "aria-controls": "history-dropdown",
        onclick: toggleDropdown,
        onkeydown: handleKeyDown,
        class: "flex items-center gap-3 rounded-xs border border-transparent bg-rc-gray-800 text-rc-gray-300 shadow-sm hover:bg-rc-gray-700 focus:outline-none focus:ring-0",
        get el() {
          return anchorEl;
        },
        set el($$value) {
          anchorEl = $$value;
          $$settled = false;
        },
        children: ($$renderer4) => {
          $$renderer4.push(`<span>${escape_html(triggerTitle)}</span> `);
          Icon($$renderer4, {
            name: "chevron-down",
            class: "size-5 transition-transform " + (isOpen ? "rotate-180" : "")
          });
          $$renderer4.push(`<!---->`);
        },
        $$slots: { default: true }
      });
      $$renderer3.push(`<!----> `);
      {
        let children = function($$renderer4) {
          $$renderer4.push(`<div class="mt-1 max-h-96 w-80 overflow-y-auto border border-rc-gray-600 bg-rc-gray-800 shadow-lg" role="listbox"><!--[-->`);
          const each_array = ensure_array_like(agentStates.slice().reverse());
          for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
            let state = each_array[$$index];
            Button($$renderer4, {
              variant: "ghost",
              size: "small",
              role: "option",
              "aria-selected": state.id === currentState,
              onclick: () => handleSelectState(state.id),
              class: "w-full border-b border-rc-gray-600 py-2 pr-3 text-left last:border-b-0 hover:bg-rc-gray-700 focus:bg-rc-gray-400",
              children: ($$renderer5) => {
                $$renderer5.push(`<div class="flex items-start gap-2"><span class="flex h-5 w-5 items-center justify-center">`);
                if (state.id === currentState) {
                  $$renderer5.push("<!--[-->");
                  $$renderer5.push(`<span class="text-green-500">`);
                  Icon($$renderer5, {
                    name: "checkmark",
                    width: 20,
                    height: 20,
                    class: "inline-block"
                  });
                  $$renderer5.push(`<!----></span>`);
                } else {
                  $$renderer5.push("<!--[!-->");
                }
                $$renderer5.push(`<!--]--></span> <div class="min-w-0"><div class="text-sm font-bold leading-tight text-rc-gray-300">${escape_html(state.name)}</div> <div class="mt-1 text-sm leading-tight text-rc-gray-100">${escape_html(truncateMessage(getUserMessage(state)))}</div></div></div>`);
              },
              $$slots: { default: true }
            });
          }
          $$renderer4.push(`<!--]--></div>`);
        };
        Dropdown($$renderer3, {
          id: "history-dropdown",
          open: isOpen,
          onClose: () => isOpen = false,
          anchorEl,
          placement: "bottom-start",
          offset: [0, 1],
          children
        });
      }
      $$renderer3.push(`<!----></div>`);
    }
    do {
      $$settled = true;
      $$inner_renderer = $$renderer2.copy();
      $$render_inner($$inner_renderer);
    } while (!$$settled);
    $$renderer2.subsume($$inner_renderer);
  });
}
let chatContent = [];
function isChatMessage(message) {
  return !isAction(message);
}
function isAction(message) {
  return "action" in message;
}
function clearChatContent() {
  chatContent.length = 0;
}
function ChatMessage($$renderer, $$props) {
  $$renderer.component(($$renderer2) => {
    let { message } = $$props;
    $$renderer2.push(`<div${attr_class("group flex", void 0, {
      "justify-end": message.sender === "user" || message.sender === "system"
    })}><div${attr_class(`rounded ${stringify(message.sender === "system" ? "w-5/6 justify-self-end whitespace-pre-line break-words border border-emerald-500 text-emerald-500" : message.sender !== "user" ? "w-5/6 whitespace-pre-line break-words bg-emerald-700 text-rc-gray-100" : "border-1 max-w5/6 justify-self-end border  border-rc-gray-100 text-rc-gray-100")} mb-2 p-2`)}>`);
    if (message.imageUrl) {
      $$renderer2.push("<!--[-->");
      $$renderer2.push(`<img${attr("src", message.imageUrl)} alt="image"/>`);
    } else {
      $$renderer2.push("<!--[!-->");
    }
    $$renderer2.push(`<!--]--> <div>${escape_html(message.text)}</div></div> `);
    if (message.sender === "agent") {
      $$renderer2.push("<!--[-->");
      $$renderer2.push(`<div${attr_class(`add-test cursor-pointer p-2 transition-opacity ${stringify("opacity-0 group-hover:opacity-100")}`)}>`);
      {
        $$renderer2.push("<!--[!-->");
        {
          $$renderer2.push("<!--[!-->");
          $$renderer2.push(`Add test`);
        }
        $$renderer2.push(`<!--]-->`);
      }
      $$renderer2.push(`<!--]--></div>`);
    } else {
      $$renderer2.push("<!--[!-->");
    }
    $$renderer2.push(`<!--]--></div>`);
  });
}
function ChatAction($$renderer, $$props) {
  $$renderer.component(($$renderer2) => {
    const { action } = $$props;
    $$renderer2.push(`<div><div class="block"><div${attr_class("mb-1 rounded p-0 text-rc-gray-100", void 0, { "cursor-pointer": action.logs.length > 0 })}><div${attr_class(`relative top-0 inline-flex rounded-sm border border-rc-gray-100 text-xs text-rc-gray-100 ${stringify(action.action.type === "AI Engine" ? "hidden" : "")}`)}><div class="mx-1 my-1">${escape_html(action.action.type)}</div></div> <div class="inline-flex">${escape_html(action.action.message)}</div> `);
    if (action.logs.length > 0) {
      $$renderer2.push("<!--[-->");
      $$renderer2.push(`<span class="ml-1">`);
      Icon($$renderer2, { name: "log", width: 15, height: 15, class: "inline-block" });
      $$renderer2.push(`<!----></span>`);
    } else {
      $$renderer2.push("<!--[!-->");
    }
    $$renderer2.push(`<!--]--> `);
    if (action.action.state === "completed") {
      $$renderer2.push("<!--[-->");
      $$renderer2.push(`<span class="text-green-500">`);
      Icon($$renderer2, {
        name: "checkmark",
        width: 20,
        height: 20,
        class: "inline-block"
      });
      $$renderer2.push(`<!----></span>`);
    } else {
      $$renderer2.push("<!--[!-->");
      if (action.action.state === "failed") {
        $$renderer2.push("<!--[-->");
        $$renderer2.push(`<span>❌</span>`);
      } else {
        $$renderer2.push("<!--[!-->");
      }
      $$renderer2.push(`<!--]-->`);
    }
    $$renderer2.push(`<!--]--></div> `);
    {
      $$renderer2.push("<!--[!-->");
    }
    $$renderer2.push(`<!--]--></div></div>`);
  });
}
function Dialog($$renderer, $$props) {
  $$renderer.component(($$renderer2) => {
    let dialog;
    let {
      showCloseButton = false,
      children
    } = $$props;
    $$renderer2.push(`<dialog class="dialog m-auto bg-transparent p-0 text-rc-gray-100 shadow-md svelte-jby388">`);
    children($$renderer2);
    $$renderer2.push(`<!----> `);
    if (showCloseButton) {
      $$renderer2.push("<!--[-->");
      Button($$renderer2, {
        variant: "ghost",
        onclick: () => dialog.close(),
        class: "absolute right-2 top-2",
        children: ($$renderer3) => {
          $$renderer3.push(`<!---->✕`);
        },
        $$slots: { default: true }
      });
    } else {
      $$renderer2.push("<!--[!-->");
    }
    $$renderer2.push(`<!--]--></dialog>`);
  });
}
function PlaygroundChat($$renderer, $$props) {
  $$renderer.component(($$renderer2) => {
    let { class: className } = $$props;
    let text = "";
    let imageUrlInputValue = "";
    let $$settled = true;
    let $$inner_renderer;
    function $$render_inner($$renderer3) {
      Dialog($$renderer3, {
        showCloseButton: true,
        children: ($$renderer4) => {
          Panel($$renderer4, {
            class: "p-4",
            children: ($$renderer5) => {
              $$renderer5.push(`<form><h2 class="text-l mb-4 text-gray-300">Image URL</h2> `);
              Input($$renderer5, {
                class: "mb-2 w-80",
                get value() {
                  return imageUrlInputValue;
                },
                set value($$value) {
                  imageUrlInputValue = $$value;
                  $$settled = false;
                }
              });
              $$renderer5.push(`<!----> `);
              Button($$renderer5, {
                variant: "outlined",
                size: "big",
                type: "submit",
                class: "p-2",
                children: ($$renderer6) => {
                  $$renderer6.push(`<!---->Attach`);
                },
                $$slots: { default: true }
              });
              $$renderer5.push(`<!----></form>`);
            }
          });
        }
      });
      $$renderer3.push(`<!----> `);
      Panel($$renderer3, {
        class: `flex flex-col p-2 ${stringify(className)}`,
        children: ($$renderer4) => {
          $$renderer4.push(`<div class="scrollbar-none flex-1 overflow-y-auto"><!--[-->`);
          const each_array = ensure_array_like(chatContent);
          for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
            let message = each_array[$$index];
            $$renderer4.push(`<div${attr_class("log-element svelte-14u1pl2", void 0, { "log-element-chat": isChatMessage(message) })}><div>`);
            if (isAction(message)) {
              $$renderer4.push("<!--[-->");
              $$renderer4.push(`<div class="chat-action svelte-14u1pl2">`);
              ChatAction($$renderer4, { action: message });
              $$renderer4.push(`<!----></div>`);
            } else {
              $$renderer4.push("<!--[!-->");
              ChatMessage($$renderer4, { message });
            }
            $$renderer4.push(`<!--]--></div></div>`);
          }
          $$renderer4.push(`<!--]--></div> <form class="mt-2 flex flex-none">`);
          Input($$renderer4, {
            class: "block w-full",
            placeholder: "Enter user's message...",
            get value() {
              return text;
            },
            set value($$value) {
              text = $$value;
              $$settled = false;
            }
          });
          $$renderer4.push(`<!----> `);
          Button($$renderer4, {
            class: "ml-2",
            onclick: () => true,
            children: ($$renderer5) => {
              Icon($$renderer5, { name: "paperclip" });
            },
            $$slots: { default: true }
          });
          $$renderer4.push(`<!----> `);
          Button($$renderer4, {
            class: "ml-2",
            type: "submit",
            children: ($$renderer5) => {
              Icon($$renderer5, { name: "send" });
            },
            $$slots: { default: true }
          });
          $$renderer4.push(`<!----></form>`);
        }
      });
      $$renderer3.push(`<!---->`);
    }
    do {
      $$settled = true;
      $$inner_renderer = $$renderer2.copy();
      $$render_inner($$inner_renderer);
    } while (!$$settled);
    $$renderer2.subsume($$inner_renderer);
  });
}
function PromptEditor($$renderer, $$props) {
  $$renderer.component(($$renderer2) => {
    let { class: className } = $$props;
    Panel($$renderer2, {
      class: `overflow-hidden ${stringify(className)}`,
      children: ($$renderer3) => {
        $$renderer3.push(`<div class="flex items-center justify-between p-3 focus:outline-none focus:ring-0"><h2 class="text-xl font-semibold">Prompt</h2> <label class="flex items-center gap-2 text-sm"><input type="checkbox" class="checkbox svelte-1br1z62"/> Preview</label></div> <div class="h-full w-full"></div>`);
      }
    });
  });
}
class WebSocketClient {
  constructor(wsUrl) {
    this.wsUrl = wsUrl;
  }
  ws = null;
  openHandler = null;
  closeHandler = null;
  errorHandler = null;
  messageHandler = null;
  retries = 0;
  maxRetries = 5;
  retryDelay = 500;
  retryTimeout = null;
  isOpen = false;
  isDestroyed = false;
  init = () => {
    if (this.isOpen) {
      return;
    }
    console.log(`Initializing websocket connection with [${this.wsUrl}]`);
    try {
      this.ws = new WebSocket(this.wsUrl);
    } catch (e) {
      this.retryConnect();
      return;
    }
    this.isDestroyed = false;
    this.ws.onmessage = (event) => {
      const message = JSON.parse(event.data);
      if (message.channel === "error") {
        this.errorHandler?.(message.message);
      } else if (message.channel === "app-events") {
        console.log("MSG:", message.event.type);
      }
      this.messageHandler?.(message);
    };
    this.ws.onerror = (error) => {
      console.error("Websocket error:", error);
      this.ws?.close();
      this.retryConnect();
    };
    this.ws.onclose = () => {
      console.log("Websocket closed");
      this.isOpen = false;
      this.retryConnect();
    };
    this.ws.onopen = () => {
      this.retries = 0;
      this.isOpen = true;
      if (this.retryTimeout) {
        clearTimeout(this.retryTimeout);
      }
      this.openHandler?.();
      console.log("Websocket connected");
    };
  };
  destroy = () => {
    this.isDestroyed = true;
    this.ws?.close();
  };
  onOpen = (handler) => {
    this.openHandler = handler;
    if (this.isOpen) {
      handler();
    }
  };
  onClose = (handler) => {
    this.closeHandler = handler;
    if (!this.isOpen) {
      handler();
    }
  };
  onError = (handler) => {
    this.errorHandler = handler;
  };
  onMessage = (handler) => {
    this.messageHandler = handler;
  };
  sendMessage = (message) => {
    if (message.channel === "app-events") ;
    this.ws?.send(JSON.stringify(message));
  };
  retryConnect = () => {
    if (this.isDestroyed) return;
    if (!this.isOpen && this.retries < this.maxRetries) {
      this.retries++;
      this.init();
      this.retryTimeout = setTimeout(this.retryConnect, this.retryDelay);
    } else {
      this.errorHandler?.("WebSocket Error, please reload the browser");
      this.closeHandler?.();
    }
  };
}
const wsHost = "ws://localhost:8080";
const wsClient = new WebSocketClient(wsHost);
function _page($$renderer, $$props) {
  $$renderer.component(($$renderer2) => {
    const { data } = $$props;
    const { onAgentSelect, onError } = getAgentsContext();
    let steps = [];
    let currentStep = null;
    let agentStates = [];
    let context = null;
    let delayedActions = {};
    let currentState = null;
    let sidebarCollapsed = false;
    function getQueryParam(key, params) {
      if (params) return params.get(key);
      if (typeof window === "undefined") return null;
      const url = new URL(window.location.href);
      return url.searchParams.get(key);
    }
    const agentIdFromUrl = getQueryParam("agent", page.url.searchParams);
    onDestroy(() => {
      wsClient.destroy();
    });
    function sendEvent(event) {
      wsClient.sendMessage({ channel: "app-events", event });
    }
    function handleContextChanged(newContext) {
      console.log("Context changed", newContext);
      sendEvent({ type: "context-updated", context: newContext });
    }
    function selectAgent(agent) {
      onAgentSelect(agent);
    }
    function handleSelectState(stateId) {
      if (!agentIdFromUrl) {
        return;
      }
      currentState = stateId;
      clearChatContent();
      sendEvent({
        type: "select-agent",
        agent: agentIdFromUrl,
        state: currentState
      });
    }
    function handleNew() {
      if (!agentIdFromUrl) {
        return;
      }
      clearChatContent();
      currentState = null;
      sendEvent({
        type: "select-agent",
        agent: agentIdFromUrl,
        state: currentState
      });
    }
    const hasActions = () => Object.keys(delayedActions).length > 0;
    const panels = {
      sidebar: { width: "w-1/6" },
      promptColumn: {
        width: "w-1/2",
        height: "h-full",
        visibility: "hidden"
      },
      promptEditor: {
        width: "w-full",
        height: "h-full"
      },
      chat: {
        width: "w-2/3",
        height: "h-full"
      },
      contextEditor: {
        width: hasActions() ? "w-1/4" : "w-1/3",
        height: "h-full"
      }
    };
    function handleTabChange({ value }) {
      if (value === "roleplay") return;
      const agentId = getQueryParam("agent", page.url.searchParams);
      getQueryParam("step");
      if (value === "tests") {
        if (agentId) {
          const [proj, ag] = agentId.split("/");
          if (proj && ag) {
            goto();
            return;
          }
        }
        goto();
        return;
      }
      if (value === "traces") {
        goto();
        return;
      }
      goto();
    }
    head($$renderer2, ($$renderer3) => {
      $$renderer3.title(($$renderer4) => {
        $$renderer4.push(`<title>Bosun: Playground</title>`);
      });
    });
    $$renderer2.push(`<div class="flex h-screen">`);
    AgentSidebar($$renderer2, {
      className: "flex-none",
      agents: data.agents,
      currentAgent: agentIdFromUrl || "",
      onSelect: selectAgent,
      onToggle: () => sidebarCollapsed = !sidebarCollapsed,
      isCollapsed: sidebarCollapsed
    });
    $$renderer2.push(`<!----> <div class="flex h-full min-w-0 flex-1 flex-col bg-rc-gray-700 py-2 pr-lg"><nav class="flex h-14 flex-none items-center justify-between bg-rc-gray-700"><div class="flex items-center">`);
    Tabs($$renderer2, {
      value: page.url.pathname.replace(/^\//, ""),
      ariaLabel: "Top tabs",
      onChange: handleTabChange,
      children: ($$renderer3) => {
        Tab($$renderer3, {
          value: "roleplay",
          class: "px-3",
          children: ($$renderer4) => {
            $$renderer4.push(`<!---->Roleplay`);
          }
        });
        $$renderer3.push(`<!----> `);
        Tab($$renderer3, {
          value: "tests",
          class: "px-3",
          children: ($$renderer4) => {
            $$renderer4.push(`<!---->Tests`);
          }
        });
        $$renderer3.push(`<!----> `);
        Tab($$renderer3, {
          value: "traces",
          class: "px-3",
          children: ($$renderer4) => {
            $$renderer4.push(`<!---->Traces`);
          }
        });
        $$renderer3.push(`<!---->`);
      },
      $$slots: { default: true }
    });
    $$renderer2.push(`<!----></div> <div class="ml-auto flex items-center gap-5">`);
    if (agentStates.length > 1) {
      $$renderer2.push("<!--[-->");
      History($$renderer2, { agentStates, currentState, onSelectState: handleSelectState });
    } else {
      $$renderer2.push("<!--[!-->");
    }
    $$renderer2.push(`<!--]--> `);
    Button($$renderer2, {
      onclick: handleNew,
      children: ($$renderer3) => {
        $$renderer3.push(`<!---->New chat`);
      },
      $$slots: { default: true }
    });
    $$renderer2.push(`<!----></div></nav> <div class="flex-1 overflow-hidden"><div${attr_class(`${stringify("hidden")} h-full w-full border-thin border-rc-gray-300/40 focus:outline-none focus:ring-0`)}><div${attr_class(`flex h-full ${stringify(panels.sidebar.width)} flex-col border-r-thin border-r-rc-gray-300/40 pt-4 text-rc-gray-200`)}>`);
    {
      $$renderer2.push("<!--[!-->");
      $$renderer2.push(`<!--[-->`);
      const each_array = ensure_array_like(steps);
      for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
        let step = each_array[$$index];
        $$renderer2.push(`<button${attr_class(`border-l-2 p-2 text-left ${stringify(step.name === currentStep?.name ? "border-l-rc-green-200 text-rc-green-200" : "border-l-transparent")}`)}><span>${escape_html(step.name)}</span></button>`);
      }
      $$renderer2.push(`<!--]-->`);
    }
    $$renderer2.push(`<!--]--></div> <div${attr_class(`${stringify(panels.promptColumn.visibility)} ${stringify(panels.promptColumn.height)} ${stringify(panels.promptColumn.width)} flex-col`)}>`);
    PromptEditor($$renderer2, {
      class: `${stringify(panels.promptEditor.height)} ${stringify(panels.promptEditor.width)} rounded-none border-r-thin border-t-0 border-r-rc-gray-300/40 focus:outline-none focus:ring-0`
    });
    $$renderer2.push(`<!----> `);
    {
      $$renderer2.push("<!--[!-->");
    }
    $$renderer2.push(`<!--]--></div> `);
    if (agentIdFromUrl) {
      $$renderer2.push("<!--[-->");
      PlaygroundChat($$renderer2, {
        class: `${stringify(panels.chat.height)} ${stringify(panels.chat.width)}`
      });
    } else {
      $$renderer2.push("<!--[!-->");
      $$renderer2.push(`<div${attr_class(`${stringify(panels.chat.height)} ${stringify(panels.chat.width)} flex items-start justify-center pt-40 text-rc-gray-200`)}>Select an agent on the left panel to start chatting</div>`);
    }
    $$renderer2.push(`<!--]--> `);
    ContextEditor($$renderer2, {
      class: `${stringify(panels.contextEditor.height)} ${stringify(panels.contextEditor.width)} min-h-0 rounded-none border-l-thin border-l-rc-gray-300/40 focus:outline-none focus:ring-0`,
      context,
      onContextChanged: handleContextChanged
    });
    $$renderer2.push(`<!----></div> <div${attr_class(`${stringify("flex")} h-full items-center justify-center`)}><div class="text-rc-gray-100">Connecting...</div></div></div></div></div>`);
  });
}

export { _page as default };
//# sourceMappingURL=_page.svelte-DJ3s4Val.js.map
