@miiflow/assistant-ui 0.7.0 → 0.10.0

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.
Files changed (44) hide show
  1. package/dist/{WelcomeScreen-XVZqMpVW.d.ts → WelcomeScreen-Cbipi2rK.d.ts} +18 -8
  2. package/dist/{avatar-C13xc3tA.d.ts → avatar-CD685KQV.d.ts} +1 -1
  3. package/dist/branding-NieTEGQf.d.ts +32 -0
  4. package/dist/chunk-NG4HKXYB.js +2 -0
  5. package/dist/chunk-NG4HKXYB.js.map +1 -0
  6. package/dist/chunk-NKLA5PPB.js +2 -0
  7. package/dist/chunk-NKLA5PPB.js.map +1 -0
  8. package/dist/chunk-QECTWT2H.js +2 -0
  9. package/dist/chunk-QECTWT2H.js.map +1 -0
  10. package/dist/chunk-UZ2Z7C43.js +133 -0
  11. package/dist/chunk-UZ2Z7C43.js.map +1 -0
  12. package/dist/chunk-ZP4FGAAH.js +2 -0
  13. package/dist/chunk-ZP4FGAAH.js.map +1 -0
  14. package/dist/client/index.d.ts +41 -4
  15. package/dist/client/index.js +7 -5
  16. package/dist/client/index.js.map +1 -1
  17. package/dist/composer/index.d.ts +187 -0
  18. package/dist/composer/index.js +2 -0
  19. package/dist/composer/index.js.map +1 -0
  20. package/dist/context/index.d.ts +16 -4
  21. package/dist/context/index.js +1 -1
  22. package/dist/hooks/index.d.ts +2 -2
  23. package/dist/hooks/index.js +1 -1
  24. package/dist/index.d.ts +14 -6
  25. package/dist/index.js +1 -1
  26. package/dist/index.js.map +1 -1
  27. package/dist/{message-BrHFdwb2.d.ts → message-D0oMw3tR.d.ts} +1 -1
  28. package/dist/primitives/index.d.ts +3 -3
  29. package/dist/{streaming-DURrv9_E.d.ts → streaming-CmQo_OOA.d.ts} +81 -122
  30. package/dist/styled/index.d.ts +217 -91
  31. package/dist/styled/index.js +1 -1
  32. package/dist/styles-no-preflight.css +1 -1
  33. package/dist/styles.css +1 -1
  34. package/dist/types-Du00UBst.d.ts +48 -0
  35. package/package.json +18 -2
  36. package/dist/branding-SzYU4ncD.d.ts +0 -18
  37. package/dist/chunk-EI3GOLHT.js +0 -128
  38. package/dist/chunk-EI3GOLHT.js.map +0 -1
  39. package/dist/chunk-NSTK5EUQ.js +0 -2
  40. package/dist/chunk-NSTK5EUQ.js.map +0 -1
  41. package/dist/chunk-O2ILSWHS.js +0 -2
  42. package/dist/chunk-O2ILSWHS.js.map +0 -1
  43. package/dist/chunk-OCKHJ4WO.js +0 -2
  44. package/dist/chunk-OCKHJ4WO.js.map +0 -1
@@ -0,0 +1,2 @@
1
+ import {$getSelection,$isRangeSelection,$getRoot,KEY_ENTER_COMMAND,COMMAND_PRIORITY_HIGH,DecoratorNode,$isTextNode,$createTextNode,$isElementNode}from'lexical';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {useLexicalComposerContext}from'@lexical/react/LexicalComposerContext';import {LexicalTypeaheadMenuPlugin,MenuOption}from'@lexical/react/LexicalTypeaheadMenuPlugin';import {forwardRef,useMemo,useRef,useEffect,useCallback,useImperativeHandle,useState,useLayoutEffect}from'react';import {createPortal}from'react-dom';import {LexicalComposer}from'@lexical/react/LexicalComposer';import {ContentEditable}from'@lexical/react/LexicalContentEditable';import {LexicalErrorBoundary}from'@lexical/react/LexicalErrorBoundary';import {HistoryPlugin}from'@lexical/react/LexicalHistoryPlugin';import {OnChangePlugin}from'@lexical/react/LexicalOnChangePlugin';import {RichTextPlugin}from'@lexical/react/LexicalRichTextPlugin';import {useReducedMotion,AnimatePresence,motion}from'framer-motion';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';var ee="color-mix(in srgb, currentColor 16%, transparent)",te="color-mix(in srgb, currentColor 8%, transparent)",ne="color-mix(in srgb, currentColor 6%, transparent)",oe="color-mix(in srgb, currentColor 12%, transparent)",F={flexShrink:0,display:"inline-flex",alignItems:"center",fontSize:10,fontWeight:700,letterSpacing:.5,textTransform:"uppercase",padding:"2px 5px",borderRadius:3,background:ee,lineHeight:1};function N({id:t,kind:e,label:n,description:s,icon:r,tag:d,variant:p="chip",selected:c=false,onMouseEnter:g,onMouseDown:h,htmlId:C}){let l=n??t,T=d!==void 0?jsx("span",{style:{display:"inline-flex",flexShrink:0,alignItems:"center"},children:d}):jsx("span",{style:F,children:e});return p==="chip"?jsxs("span",{"data-chat-command-chip":"true","data-command-id":t,"data-command-kind":e,title:`${e}: ${t}`,style:{display:"inline-flex",alignItems:"center",gap:5,verticalAlign:"middle",background:te,borderRadius:999,padding:"2px 9px 2px 4px",margin:"0 1px",whiteSpace:"nowrap",fontWeight:500,lineHeight:1},children:[T,r&&jsx("span",{style:{display:"inline-flex",flexShrink:0},children:r}),jsx("span",{children:l})]}):jsxs("div",{role:"option","aria-selected":c,id:C,onMouseEnter:g,onMouseDown:h,"data-command-id":t,"data-command-kind":e,style:{display:"flex",alignItems:"center",gap:8,padding:"6px 8px",borderRadius:6,cursor:"pointer",background:c?oe:"transparent",transition:"background 80ms ease"},onMouseOver:a=>{c||(a.currentTarget.style.background=ne);},onMouseOut:a=>{c||(a.currentTarget.style.background="transparent");},children:[jsx("span",{style:F,children:e}),r&&jsx("span",{style:{display:"inline-flex",flexShrink:0},children:r}),jsxs("div",{style:{flex:1,minWidth:0,lineHeight:1.3},children:[jsx("div",{style:{fontSize:12,fontWeight:500,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:l}),s&&jsx("div",{style:{fontSize:11,opacity:.65,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:s})]})]})}var $="data-chat-command-token",L="/",E=class t extends DecoratorNode{constructor(e,n,s,r=L,d){super(d),this.__id=e,this.__kind=n,this.__label=s,this.__prefix=r;}static getType(){return "command-token"}static clone(e){return new t(e.__id,e.__kind,e.__label,e.__prefix,e.__key)}static importJSON(e){return new t(e.commandId,e.commandKind,e.commandLabel,e.commandPrefix??L)}exportJSON(){return {...super.exportJSON(),commandId:this.__id,commandKind:this.__kind,commandLabel:this.__label,commandPrefix:this.__prefix,type:"command-token",version:2}}getCommandId(){return this.__id}getCommandKind(){return this.__kind}getCommandLabel(){return this.__label}getCommandPrefix(){return this.__prefix}getEncodedText(){return `${this.__prefix}${this.__id}:${this.__kind}`}createDOM(){let e=document.createElement("span");return e.setAttribute($,"true"),e}updateDOM(){return false}exportDOM(){let e=document.createElement("span");return e.setAttribute($,"true"),e.setAttribute("data-command-id",this.__id),e.setAttribute("data-command-kind",this.__kind),e.setAttribute("data-command-prefix",this.__prefix),e.textContent=this.getEncodedText(),{element:e}}static importDOM(){return {span:e=>e.hasAttribute($)?{conversion:ie,priority:1}:null}}decorate(){return jsx("span",{contentEditable:false,style:{userSelect:"none"},children:jsx(N,{id:this.__id,kind:this.__kind,label:this.__label,variant:"chip"})})}isInline(){return true}isKeyboardSelectable(){return true}getTextContent(){return this.getEncodedText()}};function ie(t){let e=t.getAttribute("data-command-id"),n=t.getAttribute("data-command-kind");if(!e||!n)return null;let s=t.getAttribute("data-command-prefix")??L,r=t.textContent?.replace(new RegExp(`^[\\${s}]`),"")??e;return {node:I(e,n,r,s)}}function I(t,e,n,s=L){return new E(t,e,n,s)}function S(t){return t instanceof E}var H=/(^|\s|\(|\[)([/@])([^\n:]+?):([\w-]+)(?=$|[\s.,!?)\]])/g;function ae(t){let e=[];H.lastIndex=0;let n;for(;(n=H.exec(t))!==null;){let s=n[1]??"",r=n[2],d=n[3],p=n[4],c=n.index+s.length,g=n[0].slice(s.length);e.push({id:d,kind:p,prefix:r,raw:g,index:c,endIndex:c+g.length});}return e}var Ce="/",he=75,K=class extends MenuOption{constructor(e){super(`${e.kind}:${e.id}`),this.command=e;}};function ye(t){let e=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|\\s|\\()(${e}((?:[^${e}\\s]){0,${he}}))$`)}function z({commandProvider:t,menuRenderer:e,onMenuStateChange:n}){let[s]=useLexicalComposerContext(),[r,d]=useState(null),[p,c]=useState([]),g=t?.trigger??Ce,h=useMemo(()=>ye(g),[g]);useEffect(()=>{n?.(r!=null);},[r,n]),useEffect(()=>{if(!t||r==null){c([]);return}let i=false;return Promise.resolve(t.fetch(r)).then(o=>{i||c(o);}),()=>{i=true;}},[t,r]);let C=useMemo(()=>p.map(i=>new K(i)),[p]),l=useCallback(i=>{let o=h.exec(i);if(!o)return null;let m=o[1]??"",x=o[3]??"";return {leadOffset:o.index+m.length,matchingString:x,replaceableString:o[2]??""}},[h]),T=t?.singletonKinds,a=useCallback((i,o,m)=>{s.update(()=>{let x=i.command.kind;if(T?.includes(x)??false){let w=[],R=k=>{if(S(k)&&k.getCommandKind()===x){w.push({node:k,index:0});return}if($isElementNode(k))for(let _ of k.getChildren())R(_);};R($getRoot());for(let k of w){let _=k.node.getNextSibling();if(k.node.remove(),_&&$isTextNode(_)){let V=_.getTextContent();if(V.startsWith(" ")){let W=V.slice(1);W.length===0?_.remove():_.setTextContent(W);}}}}let f=I(i.command.id,x,i.command.label,g),b=$createTextNode(" ");o&&o.replace(f).insertAfter(b),b.select(),m();});},[s,g,T]);return t?jsx(LexicalTypeaheadMenuPlugin,{onQueryChange:d,onSelectOption:a,triggerFn:l,options:C,menuRenderFn:(i,{selectedIndex:o,selectOptionAndCleanUp:m,setHighlightedIndex:x})=>e?jsx(Fragment,{children:e({anchorElement:i.current,options:p,selectedIndex:o??0,setSelectedIndex:x,selectOption:u=>{let f=C.find(b=>b.command.id===u.id&&b.command.kind===u.kind);f&&m(f);},closeMenu:()=>d(null)})}):jsx(Te,{anchorElement:i.current,options:C,selectedIndex:o??0,setHighlightedIndex:x,selectOptionAndCleanUp:m,visible:p.length>0||r!=null,queryString:r})}):null}function Te({anchorElement:t,options:e,selectedIndex:n,setHighlightedIndex:s,selectOptionAndCleanUp:r,visible:d,queryString:p}){let c=useRef(null),[g,h]=useState(false),C=6;if(useEffect(()=>{let a=c.current;if(!a||e.length===0)return;let i=a.querySelector(`#command-typeahead-item-${n}`);if(!i)return;let o=a.getBoundingClientRect(),m=i.getBoundingClientRect();m.top<o.top?a.scrollTop-=o.top-m.top:m.bottom>o.bottom&&(a.scrollTop+=m.bottom-o.bottom);},[n,e.length]),useLayoutEffect(()=>{if(!t||!d||!c.current)return;let a=()=>{let i=c.current;if(!i)return;let o=t.getBoundingClientRect(),m=i.offsetHeight,u=window.innerHeight-o.top,b=o.top-o.height,w=m+C>u,R=m+C<=b;h(w&&R);};return a(),window.addEventListener("resize",a),window.addEventListener("scroll",a,true),()=>{window.removeEventListener("resize",a),window.removeEventListener("scroll",a,true);}},[t,d,e.length]),!t||!d)return null;let l=t.offsetHeight||20,T=g?`translateY(calc(-100% - ${l+C}px))`:"none";return createPortal(jsx("div",{ref:c,role:"listbox",style:{position:"absolute",top:0,left:0,transform:T,zIndex:99999,minWidth:320,maxWidth:520,maxHeight:280,overflowY:"auto",borderRadius:8,border:"1px solid rgba(0,0,0,0.1)",background:"#ffffff",boxShadow:"0 8px 24px rgba(0,0,0,0.15)",padding:4,fontSize:12,color:"#1f2937"},children:e.length===0?jsxs("div",{style:{padding:"6px 10px",fontSize:11,color:"#6b7280"},children:["No matching commands",p?` for "${p}"`:""]}):e.map((a,i)=>{let o=i===n,m=a.command;return jsx(N,{variant:"row",id:m.id,kind:m.kind,label:m.label,description:m.description,icon:m.icon,selected:o,htmlId:`command-typeahead-item-${i}`,onMouseEnter:()=>s(i),onMouseDown:x=>{x.preventDefault(),x.stopPropagation(),s(i),r(a);}},a.key)})}),t)}function P(...t){return twMerge(clsx(t))}var Be={paragraph:"chat-composer-paragraph"};function j(t){let e="",n=[];return t.getEditorState().read(()=>{let s=$getRoot();e=s.getTextContent();let r=d=>{if(S(d)&&n.push({id:d.getCommandId(),kind:d.getCommandKind(),label:d.getCommandLabel()}),$isElementNode(d))for(let p of d.getChildren())r(p);};r(s);}),{text:e,tokens:n}}var Ge=forwardRef(function({placeholder:e="Type a message...",disabled:n=false,className:s,inputClassName:r,placeholderClassName:d,children:p,onChange:c,onSubmit:g,commandProvider:h,commandProviders:C},l){let T=useMemo(()=>({namespace:"ChatComposer",theme:Be,nodes:[E],editable:!n,onError:a=>{console.error("[chat-ui composer]",a);}}),[]);return jsx(LexicalComposer,{initialConfig:T,children:jsx(Ve,{placeholder:e,disabled:n,className:s,inputClassName:r,placeholderClassName:d,onChange:c,onSubmit:g,commandProvider:h,commandProviders:C,imperativeHandle:l,children:p})})});function Ve({placeholder:t,disabled:e,className:n,inputClassName:s,placeholderClassName:r,children:d,onChange:p,onSubmit:c,commandProvider:g,commandProviders:h,imperativeHandle:C}){let[l]=useLexicalComposerContext(),T=useReducedMotion(),a=useRef(c);a.current=c;let i=useRef(false);useEffect(()=>{l.setEditable(!e);},[l,e]);let o=useCallback(()=>{let u=j(l);u.text.trim().length===0&&u.tokens.length===0||a.current(u);},[l]);useImperativeHandle(C,()=>({clear:()=>{l.update(()=>{$getRoot().clear();});},submit:o,focus:()=>l.focus(),insertText:u=>{l.focus(()=>{l.update(()=>{let f=$getSelection();$isRangeSelection(f)||($getRoot().selectEnd(),f=$getSelection()),$isRangeSelection(f)&&f.insertText(u);});});}}),[l,o]),useEffect(()=>l.registerCommand(KEY_ENTER_COMMAND,u=>{if(i.current)return false;let f=u;return f?.shiftKey?false:(f?.preventDefault(),o(),true)},COMMAND_PRIORITY_HIGH),[l,o]);let m=useCallback(u=>{i.current=u;},[]),x=useCallback(u=>{if(!p)return;let f=j(l);p(f);},[l,p]);return jsxs("div",{className:P("relative w-full",n),children:[jsx("div",{className:"relative",children:jsx(RichTextPlugin,{contentEditable:jsx(ContentEditable,{className:P("outline-none w-full text-sm leading-relaxed","min-h-[24px] max-h-[200px] overflow-y-auto","text-gray-900 dark:text-zinc-100",e&&"opacity-50 cursor-not-allowed",s)}),placeholder:jsx("div",{className:P("pointer-events-none absolute inset-0 flex items-center overflow-hidden","text-sm text-gray-400 dark:text-zinc-500 select-none",r),children:T?jsx("span",{className:"truncate",children:t}):jsx(AnimatePresence,{mode:"wait",initial:false,children:jsx(motion.span,{className:"truncate",initial:{opacity:0,y:4},animate:{opacity:1,y:0},exit:{opacity:0,y:-4},transition:{duration:.18,ease:[.4,0,.2,1]},children:t},t)})}),ErrorBoundary:LexicalErrorBoundary})}),jsx(OnChangePlugin,{onChange:x}),jsx(HistoryPlugin,{}),(h&&h.length>0?h:g?[g]:[]).map((f,b)=>jsx(z,{commandProvider:f,onMenuStateChange:m},`${f.trigger??"/"}-${b}`)),d]})}export{P as a,N as b,E as c,I as d,S as e,H as f,ae as g,z as h,Ge as i};//# sourceMappingURL=chunk-ZP4FGAAH.js.map
2
+ //# sourceMappingURL=chunk-ZP4FGAAH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/composer/CommandTokenView.tsx","../src/composer/CommandTokenNode.tsx","../src/composer/CommandTokenPlugin.tsx","../src/utils/cn.ts","../src/composer/LexicalChatInput.tsx"],"names":["TAG_BG","CHIP_BG","ROW_HOVER_BG","ROW_SELECTED_BG","tagStyle","CommandTokenView","id","kind","label","description","icon","tag","variant","selected","onMouseEnter","onMouseDown","htmlId","display","tagNode","jsx","jsxs","e","TOKEN_DATA_ATTR","DEFAULT_PREFIX","CommandTokenNode","_CommandTokenNode","DecoratorNode","prefix","key","node","serialized","span","element","domNode","convertCommandTokenElement","$createCommandTokenNode","$isCommandTokenNode","COMMAND_TOKEN_REGEX","findInlineCommandTokens","text","matches","m","leading","start","raw","DEFAULT_TRIGGER","QUERY_LENGTH_LIMIT","CommandTypeaheadOption","MenuOption","command","buildTriggerRegex","trigger","escaped","CommandTokenPlugin","commandProvider","menuRenderer","onMenuStateChange","editor","useLexicalComposerContext","queryString","setQueryString","useState","results","setResults","triggerRegex","useMemo","useEffect","cancelled","cmds","options","cmd","checkForMatch","useCallback","match","matchingString","singletonKinds","onSelectOption","selectedOption","nodeToReplace","closeMenu","stale","walk","n","$isElementNode","c","$getRoot","entry","next","$isTextNode","nextText","trimmed","tokenNode","trailingSpace","$createTextNode","LexicalTypeaheadMenuPlugin","anchorElementRef","selectedIndex","selectOptionAndCleanUp","setHighlightedIndex","Fragment","option","o","DefaultCommandMenu","anchorElement","visible","menuRef","useRef","flipped","setFlipped","VERTICAL_GAP","menu","selectedEl","menuRect","itemRect","useLayoutEffect","reposition","menuEl","anchorRect","menuHeight","spaceBelow","spaceAbove","wouldOverflowBottom","fitsAbove","anchorHeight","transform","createPortal","isSelected","cn","inputs","twMerge","clsx","EDITOR_THEME","readPayload","tokens","root","collect","child","LexicalChatInput","forwardRef","placeholder","disabled","className","inputClassName","placeholderClassName","children","onChange","onSubmit","commandProviders","ref","initialConfig","error","LexicalComposer","ChatInputBody","imperativeHandle","prefersReducedMotion","useReducedMotion","onSubmitRef","commandMenuOpenRef","submit","payload","useImperativeHandle","selection","$getSelection","$isRangeSelection","KEY_ENTER_COMMAND","event","keyboard","COMMAND_PRIORITY_HIGH","handleCommandMenuStateChange","isOpen","handleChange","_state","RichTextPlugin","ContentEditable","AnimatePresence","motion","LexicalErrorBoundary","OnChangePlugin","HistoryPlugin","p","i"],"mappings":"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","file":"chunk-ZP4FGAAH.js","sourcesContent":["import type { CSSProperties, ReactNode } from \"react\";\n\n/**\n * Single source of truth for slash-command token visuals.\n *\n * Used in three places:\n * - Typeahead popover row (variant=\"row\")\n * - Inline chip in the editor (variant=\"chip\", inside CommandTokenNode.decorate)\n * - Inline chip in message history (variant=\"chip\", inside MarkdownContent)\n *\n * Renders a kind tag + label so the user gets the same visual identity at\n * every step: pick → type → send → re-read. Adapts to the surrounding text\n * color via `currentColor` so it survives light bubbles, dark bubbles, and\n * any branded chat surface without bespoke palettes.\n */\nexport interface CommandTokenViewProps {\n /** Slug-style id (wire format `/<id>:<kind>`). */\n id: string;\n /** Token category, e.g. \"skill\", \"mode\". Rendered as the leading tag. */\n kind: string;\n /** Display name; falls back to `id` if not provided. */\n label?: string;\n /** Optional secondary line; only rendered for variant=\"row\". */\n description?: string;\n /** Optional leading icon (slotted before the label, after the tag). */\n icon?: ReactNode;\n /** Optional override for the leading tag (where `kind` renders by default).\n * When set, replaces the uppercase kind pill — e.g. swap \"AD-ACCOUNT\" for\n * the platform logo. */\n tag?: ReactNode;\n /** Compact inline pill (\"chip\") vs. full popover row (\"row\"). */\n variant?: \"chip\" | \"row\";\n /** When true, applies the row's \"selected\" styling. */\n selected?: boolean;\n /** Optional click handler (popover row uses it; chip doesn't by default). */\n onMouseEnter?: () => void;\n onMouseDown?: (e: React.MouseEvent) => void;\n /** Pass-through id for ARIA wiring (used by typeahead). */\n htmlId?: string;\n}\n\nconst TAG_BG = \"color-mix(in srgb, currentColor 16%, transparent)\";\nconst CHIP_BG = \"color-mix(in srgb, currentColor 8%, transparent)\";\nconst ROW_HOVER_BG = \"color-mix(in srgb, currentColor 6%, transparent)\";\nconst ROW_SELECTED_BG = \"color-mix(in srgb, currentColor 12%, transparent)\";\n\nconst tagStyle: CSSProperties = {\n flexShrink: 0,\n display: \"inline-flex\",\n alignItems: \"center\",\n fontSize: 10,\n fontWeight: 700,\n letterSpacing: 0.5,\n textTransform: \"uppercase\",\n padding: \"2px 5px\",\n borderRadius: 3,\n background: TAG_BG,\n lineHeight: 1,\n};\n\nexport function CommandTokenView({\n id,\n kind,\n label,\n description,\n icon,\n tag,\n variant = \"chip\",\n selected = false,\n onMouseEnter,\n onMouseDown,\n htmlId,\n}: CommandTokenViewProps) {\n const display = label ?? id;\n\n // When the caller supplies a tag node (e.g. a platform logo for an\n // ad-account chip), render it raw — no uppercase pill background. The\n // default kind text still uses tagStyle.\n const tagNode =\n tag !== undefined ? (\n <span style={{ display: \"inline-flex\", flexShrink: 0, alignItems: \"center\" }}>{tag}</span>\n ) : (\n <span style={tagStyle}>{kind}</span>\n );\n\n if (variant === \"chip\") {\n return (\n <span\n data-chat-command-chip=\"true\"\n data-command-id={id}\n data-command-kind={kind}\n title={`${kind}: ${id}`}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 5,\n verticalAlign: \"middle\",\n background: CHIP_BG,\n borderRadius: 999,\n padding: \"2px 9px 2px 4px\",\n margin: \"0 1px\",\n whiteSpace: \"nowrap\",\n fontWeight: 500,\n lineHeight: 1,\n }}\n >\n {tagNode}\n {icon && (\n <span style={{ display: \"inline-flex\", flexShrink: 0 }}>{icon}</span>\n )}\n <span>{display}</span>\n </span>\n );\n }\n\n // variant === \"row\"\n return (\n <div\n role=\"option\"\n aria-selected={selected}\n id={htmlId}\n onMouseEnter={onMouseEnter}\n onMouseDown={onMouseDown}\n data-command-id={id}\n data-command-kind={kind}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"6px 8px\",\n borderRadius: 6,\n cursor: \"pointer\",\n background: selected ? ROW_SELECTED_BG : \"transparent\",\n transition: \"background 80ms ease\",\n }}\n onMouseOver={(e) => {\n if (!selected) {\n (e.currentTarget as HTMLDivElement).style.background = ROW_HOVER_BG;\n }\n }}\n onMouseOut={(e) => {\n if (!selected) {\n (e.currentTarget as HTMLDivElement).style.background = \"transparent\";\n }\n }}\n >\n <span style={tagStyle}>{kind}</span>\n {icon && (\n <span style={{ display: \"inline-flex\", flexShrink: 0 }}>{icon}</span>\n )}\n <div style={{ flex: 1, minWidth: 0, lineHeight: 1.3 }}>\n <div\n style={{\n fontSize: 12,\n fontWeight: 500,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {display}\n </div>\n {description && (\n <div\n style={{\n fontSize: 11,\n opacity: 0.65,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {description}\n </div>\n )}\n </div>\n </div>\n );\n}\n","import {\n DecoratorNode,\n type DOMConversionMap,\n type DOMConversionOutput,\n type DOMExportOutput,\n type LexicalNode,\n type NodeKey,\n type SerializedLexicalNode,\n type Spread,\n} from \"lexical\";\nimport type { ReactNode } from \"react\";\n\nimport { CommandTokenView } from \"./CommandTokenView\";\n\nexport type SerializedCommandTokenNode = Spread<\n {\n commandId: string;\n commandKind: string;\n commandLabel: string;\n /** Trigger character that produced the chip (e.g. \"/\" or \"@\"). Optional in\n * v1 payloads — defaulted to \"/\" on import for backwards compatibility. */\n commandPrefix?: string;\n type: \"command-token\";\n version: 1 | 2;\n },\n SerializedLexicalNode\n>;\n\nconst TOKEN_DATA_ATTR = \"data-chat-command-token\";\nconst DEFAULT_PREFIX = \"/\";\n\nexport class CommandTokenNode extends DecoratorNode<ReactNode> {\n __id: string;\n __kind: string;\n __label: string;\n __prefix: string;\n\n constructor(\n id: string,\n kind: string,\n label: string,\n prefix: string = DEFAULT_PREFIX,\n key?: NodeKey,\n ) {\n super(key);\n this.__id = id;\n this.__kind = kind;\n this.__label = label;\n this.__prefix = prefix;\n }\n\n static getType(): string {\n return \"command-token\";\n }\n\n static clone(node: CommandTokenNode): CommandTokenNode {\n return new CommandTokenNode(\n node.__id,\n node.__kind,\n node.__label,\n node.__prefix,\n node.__key,\n );\n }\n\n static importJSON(serialized: SerializedCommandTokenNode): CommandTokenNode {\n return new CommandTokenNode(\n serialized.commandId,\n serialized.commandKind,\n serialized.commandLabel,\n serialized.commandPrefix ?? DEFAULT_PREFIX,\n );\n }\n\n exportJSON(): SerializedCommandTokenNode {\n return {\n ...super.exportJSON(),\n commandId: this.__id,\n commandKind: this.__kind,\n commandLabel: this.__label,\n commandPrefix: this.__prefix,\n type: \"command-token\",\n version: 2,\n };\n }\n\n getCommandId(): string {\n return this.__id;\n }\n\n getCommandKind(): string {\n return this.__kind;\n }\n\n getCommandLabel(): string {\n return this.__label;\n }\n\n getCommandPrefix(): string {\n return this.__prefix;\n }\n\n /** Wire format. Backend parses `<prefix><id>:<kind>` from the message body. */\n getEncodedText(): string {\n return `${this.__prefix}${this.__id}:${this.__kind}`;\n }\n\n createDOM(): HTMLElement {\n const span = document.createElement(\"span\");\n span.setAttribute(TOKEN_DATA_ATTR, \"true\");\n return span;\n }\n\n updateDOM(): false {\n return false;\n }\n\n exportDOM(): DOMExportOutput {\n const element = document.createElement(\"span\");\n element.setAttribute(TOKEN_DATA_ATTR, \"true\");\n element.setAttribute(\"data-command-id\", this.__id);\n element.setAttribute(\"data-command-kind\", this.__kind);\n element.setAttribute(\"data-command-prefix\", this.__prefix);\n element.textContent = this.getEncodedText();\n return { element };\n }\n\n static importDOM(): DOMConversionMap | null {\n return {\n span: (domNode: HTMLElement) => {\n if (!domNode.hasAttribute(TOKEN_DATA_ATTR)) return null;\n return { conversion: convertCommandTokenElement, priority: 1 };\n },\n };\n }\n\n decorate(): ReactNode {\n return (\n <span contentEditable={false} style={{ userSelect: \"none\" }}>\n <CommandTokenView\n id={this.__id}\n kind={this.__kind}\n label={this.__label}\n variant=\"chip\"\n />\n </span>\n );\n }\n\n isInline(): boolean {\n return true;\n }\n\n isKeyboardSelectable(): boolean {\n return true;\n }\n\n /** Plain-text projection (clipboard, root.getTextContent, etc.). */\n getTextContent(): string {\n return this.getEncodedText();\n }\n}\n\nfunction convertCommandTokenElement(domNode: HTMLElement): DOMConversionOutput | null {\n const id = domNode.getAttribute(\"data-command-id\");\n const kind = domNode.getAttribute(\"data-command-kind\");\n if (!id || !kind) return null;\n const prefix = domNode.getAttribute(\"data-command-prefix\") ?? DEFAULT_PREFIX;\n const label =\n domNode.textContent?.replace(new RegExp(`^[\\\\${prefix}]`), \"\") ?? id;\n return { node: $createCommandTokenNode(id, kind, label, prefix) };\n}\n\nexport function $createCommandTokenNode(\n id: string,\n kind: string,\n label: string,\n prefix: string = DEFAULT_PREFIX,\n): CommandTokenNode {\n return new CommandTokenNode(id, kind, label, prefix);\n}\n\nexport function $isCommandTokenNode(\n node: LexicalNode | null | undefined,\n): node is CommandTokenNode {\n return node instanceof CommandTokenNode;\n}\n\n/**\n * Matches `<prefix><id>:<kind>` substrings emitted by `CommandTokenNode.getEncodedText()`,\n * where `<prefix>` is `/` (skill / mode chips) or `@` (ad-account chips).\n *\n * Bounded by start-of-string, whitespace, or an opening bracket on the left,\n * and end-of-string, whitespace, or punctuation on the right — so it doesn't\n * fire on URLs like `https://example.com/path:foo` or emails like\n * `user@host.com:port`.\n *\n * The id capture allows spaces (skill names may have them); the kind capture\n * allows word chars and hyphens (e.g. `ad-account`).\n */\nexport const COMMAND_TOKEN_REGEX =\n /(^|\\s|\\(|\\[)([/@])([^\\n:]+?):([\\w-]+)(?=$|[\\s.,!?)\\]])/g;\n\nexport interface InlineCommandTokenMatch {\n id: string;\n kind: string;\n /** Trigger character that introduced the chip (`/` or `@`). */\n prefix: string;\n /** The full matched substring including the leading prefix (no leading boundary). */\n raw: string;\n /** Index in the original string where the leading prefix sits. */\n index: number;\n /** End index (exclusive) of the matched token. */\n endIndex: number;\n}\n\n/**\n * Find all `<prefix><id>:<kind>` tokens in a plain-text string.\n *\n * Returns matches in document order. Use this when rendering message\n * history to replace token substrings with a visual chip.\n */\nexport function findInlineCommandTokens(text: string): InlineCommandTokenMatch[] {\n const matches: InlineCommandTokenMatch[] = [];\n COMMAND_TOKEN_REGEX.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = COMMAND_TOKEN_REGEX.exec(text)) !== null) {\n const leading = m[1] ?? \"\";\n const prefix = m[2];\n const id = m[3];\n const kind = m[4];\n const start = m.index + leading.length;\n const raw = m[0].slice(leading.length);\n matches.push({\n id,\n kind,\n prefix,\n raw,\n index: start,\n endIndex: start + raw.length,\n });\n }\n return matches;\n}\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport {\n LexicalTypeaheadMenuPlugin,\n MenuOption,\n type MenuTextMatch,\n} from \"@lexical/react/LexicalTypeaheadMenuPlugin\";\nimport {\n $createTextNode,\n $getRoot,\n $isElementNode,\n $isTextNode,\n type ElementNode,\n type LexicalNode,\n type TextNode,\n} from \"lexical\";\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { $createCommandTokenNode, $isCommandTokenNode } from \"./CommandTokenNode\";\nimport { CommandTokenView } from \"./CommandTokenView\";\nimport type { ChatComposerCommand, CommandProvider } from \"./types\";\n\nconst DEFAULT_TRIGGER = \"/\";\nconst QUERY_LENGTH_LIMIT = 75;\n\nclass CommandTypeaheadOption extends MenuOption {\n command: ChatComposerCommand;\n\n constructor(command: ChatComposerCommand) {\n super(`${command.kind}:${command.id}`);\n this.command = command;\n }\n}\n\nfunction buildTriggerRegex(trigger: string): RegExp {\n // Escape the trigger char for use in a character class.\n const escaped = trigger.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n // Match: leading boundary (start, whitespace, or open-paren), the trigger,\n // then up to QUERY_LENGTH_LIMIT chars that are not whitespace.\n return new RegExp(\n `(^|\\\\s|\\\\()(${escaped}((?:[^${escaped}\\\\s]){0,${QUERY_LENGTH_LIMIT}}))$`,\n );\n}\n\nexport interface CommandTokenPluginProps {\n /** The data source for the typeahead. When null, the plugin is inert. */\n commandProvider?: CommandProvider | null;\n /**\n * Optional override for the typeahead UI. When supplied, replaces the\n * default Tailwind popover (use this to render an MUI/host-themed menu).\n */\n menuRenderer?: (params: {\n anchorElement: HTMLElement | null;\n options: ChatComposerCommand[];\n selectedIndex: number;\n setSelectedIndex: (index: number) => void;\n selectOption: (option: ChatComposerCommand) => void;\n closeMenu: () => void;\n }) => React.ReactNode;\n /**\n * Notified whenever the typeahead menu opens or closes. Use this to gate\n * keyboard handlers (e.g. don't submit on Enter while the menu is open).\n */\n onMenuStateChange?: (isOpen: boolean) => void;\n}\n\nexport function CommandTokenPlugin({\n commandProvider,\n menuRenderer,\n onMenuStateChange,\n}: CommandTokenPluginProps): React.JSX.Element | null {\n const [editor] = useLexicalComposerContext();\n const [queryString, setQueryString] = useState<string | null>(null);\n const [results, setResults] = useState<ChatComposerCommand[]>([]);\n\n const trigger = commandProvider?.trigger ?? DEFAULT_TRIGGER;\n const triggerRegex = useMemo(() => buildTriggerRegex(trigger), [trigger]);\n\n useEffect(() => {\n onMenuStateChange?.(queryString != null);\n }, [queryString, onMenuStateChange]);\n\n useEffect(() => {\n if (!commandProvider || queryString == null) {\n setResults([]);\n return;\n }\n let cancelled = false;\n Promise.resolve(commandProvider.fetch(queryString)).then((cmds) => {\n if (!cancelled) setResults(cmds);\n });\n return () => {\n cancelled = true;\n };\n }, [commandProvider, queryString]);\n\n const options = useMemo(\n () => results.map((cmd) => new CommandTypeaheadOption(cmd)),\n [results],\n );\n\n const checkForMatch = useCallback(\n (text: string): MenuTextMatch | null => {\n const match = triggerRegex.exec(text);\n if (!match) return null;\n const leading = match[1] ?? \"\";\n const matchingString = match[3] ?? \"\";\n return {\n leadOffset: match.index + leading.length,\n matchingString,\n replaceableString: match[2] ?? \"\",\n };\n },\n [triggerRegex],\n );\n\n const singletonKinds = commandProvider?.singletonKinds;\n\n const onSelectOption = useCallback(\n (\n selectedOption: CommandTypeaheadOption,\n nodeToReplace: TextNode | null,\n closeMenu: () => void,\n ) => {\n editor.update(() => {\n const kind = selectedOption.command.kind;\n const isSingleton = singletonKinds?.includes(kind) ?? false;\n\n if (isSingleton) {\n // Remove any existing chip of the same kind. Walking once with a\n // collected list (rather than mutating during traversal) keeps the\n // tree stable while we iterate.\n const stale: { node: ReturnType<typeof $createCommandTokenNode>; index: number }[] = [];\n const walk = (n: LexicalNode) => {\n if ($isCommandTokenNode(n) && n.getCommandKind() === kind) {\n stale.push({ node: n, index: 0 });\n return;\n }\n if ($isElementNode(n)) {\n for (const c of (n as ElementNode).getChildren()) walk(c);\n }\n };\n walk($getRoot());\n for (const entry of stale) {\n // If the chip is followed by a single space, drop that too so\n // we don't leave an orphan space where the chip used to sit.\n const next = entry.node.getNextSibling();\n entry.node.remove();\n if (next && $isTextNode(next)) {\n const nextText = next.getTextContent();\n if (nextText.startsWith(\" \")) {\n const trimmed = nextText.slice(1);\n if (trimmed.length === 0) next.remove();\n else next.setTextContent(trimmed);\n }\n }\n }\n }\n\n const tokenNode = $createCommandTokenNode(\n selectedOption.command.id,\n kind,\n selectedOption.command.label,\n trigger,\n );\n const trailingSpace = $createTextNode(\" \");\n if (nodeToReplace) {\n nodeToReplace.replace(tokenNode).insertAfter(trailingSpace);\n }\n trailingSpace.select();\n closeMenu();\n });\n },\n [editor, trigger, singletonKinds],\n );\n\n if (!commandProvider) return null;\n\n return (\n <LexicalTypeaheadMenuPlugin<CommandTypeaheadOption>\n onQueryChange={setQueryString}\n onSelectOption={onSelectOption}\n triggerFn={checkForMatch}\n options={options}\n menuRenderFn={(\n anchorElementRef,\n { selectedIndex, selectOptionAndCleanUp, setHighlightedIndex },\n ) => {\n if (menuRenderer) {\n return (\n <>\n {menuRenderer({\n anchorElement: anchorElementRef.current,\n options: results,\n selectedIndex: selectedIndex ?? 0,\n setSelectedIndex: setHighlightedIndex,\n selectOption: (option) => {\n const match = options.find(\n (o) => o.command.id === option.id && o.command.kind === option.kind,\n );\n if (match) selectOptionAndCleanUp(match);\n },\n closeMenu: () => setQueryString(null),\n })}\n </>\n );\n }\n return (\n <DefaultCommandMenu\n anchorElement={anchorElementRef.current}\n options={options}\n selectedIndex={selectedIndex ?? 0}\n setHighlightedIndex={setHighlightedIndex}\n selectOptionAndCleanUp={selectOptionAndCleanUp}\n visible={results.length > 0 || queryString != null}\n queryString={queryString}\n />\n );\n }}\n />\n );\n}\n\nfunction DefaultCommandMenu({\n anchorElement,\n options,\n selectedIndex,\n setHighlightedIndex,\n selectOptionAndCleanUp,\n visible,\n queryString,\n}: {\n anchorElement: HTMLElement | null;\n options: CommandTypeaheadOption[];\n selectedIndex: number;\n setHighlightedIndex: (index: number) => void;\n selectOptionAndCleanUp: (option: CommandTypeaheadOption) => void;\n visible: boolean;\n queryString: string | null;\n}) {\n const menuRef = useRef<HTMLDivElement>(null);\n const [flipped, setFlipped] = useState(false);\n const VERTICAL_GAP = 6;\n\n useEffect(() => {\n const menu = menuRef.current;\n if (!menu || options.length === 0) return;\n const selectedEl = menu.querySelector<HTMLElement>(\n `#command-typeahead-item-${selectedIndex}`,\n );\n if (!selectedEl) return;\n const menuRect = menu.getBoundingClientRect();\n const itemRect = selectedEl.getBoundingClientRect();\n if (itemRect.top < menuRect.top) {\n menu.scrollTop -= menuRect.top - itemRect.top;\n } else if (itemRect.bottom > menuRect.bottom) {\n menu.scrollTop += itemRect.bottom - menuRect.bottom;\n }\n }, [selectedIndex, options.length]);\n\n useLayoutEffect(() => {\n if (!anchorElement || !visible || !menuRef.current) return;\n const reposition = () => {\n const menuEl = menuRef.current;\n if (!menuEl) return;\n const anchorRect = anchorElement.getBoundingClientRect();\n const menuHeight = menuEl.offsetHeight;\n const viewportHeight = window.innerHeight;\n // Lexical positions the anchor right below the cursor; anchorRect.top is\n // where the menu would render by default. anchorRect.height is the\n // cursor-line height (~20px), so the cursor's top is anchorRect.top - height.\n const spaceBelow = viewportHeight - anchorRect.top;\n const cursorTop = anchorRect.top - anchorRect.height;\n const spaceAbove = cursorTop;\n const wouldOverflowBottom = menuHeight + VERTICAL_GAP > spaceBelow;\n const fitsAbove = menuHeight + VERTICAL_GAP <= spaceAbove;\n setFlipped(wouldOverflowBottom && fitsAbove);\n };\n reposition();\n window.addEventListener(\"resize\", reposition);\n window.addEventListener(\"scroll\", reposition, true);\n return () => {\n window.removeEventListener(\"resize\", reposition);\n window.removeEventListener(\"scroll\", reposition, true);\n };\n }, [anchorElement, visible, options.length]);\n\n if (!anchorElement || !visible) return null;\n\n const anchorHeight = anchorElement.offsetHeight || 20;\n const transform = flipped\n ? `translateY(calc(-100% - ${anchorHeight + VERTICAL_GAP}px))`\n : \"none\";\n\n return createPortal(\n <div\n ref={menuRef}\n role=\"listbox\"\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n transform,\n zIndex: 99999,\n minWidth: 320,\n maxWidth: 520,\n maxHeight: 280,\n overflowY: \"auto\",\n borderRadius: 8,\n border: \"1px solid rgba(0,0,0,0.1)\",\n background: \"#ffffff\",\n boxShadow: \"0 8px 24px rgba(0,0,0,0.15)\",\n padding: 4,\n fontSize: 12,\n color: \"#1f2937\",\n }}\n >\n {options.length === 0 ? (\n <div style={{ padding: \"6px 10px\", fontSize: 11, color: \"#6b7280\" }}>\n No matching commands{queryString ? ` for \"${queryString}\"` : \"\"}\n </div>\n ) : (\n options.map((option, i) => {\n const isSelected = i === selectedIndex;\n const cmd = option.command;\n return (\n <CommandTokenView\n key={option.key}\n variant=\"row\"\n id={cmd.id}\n kind={cmd.kind}\n label={cmd.label}\n description={cmd.description}\n icon={cmd.icon}\n selected={isSelected}\n htmlId={`command-typeahead-item-${i}`}\n onMouseEnter={() => setHighlightedIndex(i)}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setHighlightedIndex(i);\n selectOptionAndCleanUp(option);\n }}\n />\n );\n })\n )}\n </div>,\n anchorElement,\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Utility function to merge Tailwind CSS classes with proper precedence.\n * Combines clsx for conditional classes with tailwind-merge for conflict resolution.\n *\n * @example\n * cn(\"px-4 py-2\", \"px-6\") // => \"py-2 px-6\"\n * cn(\"text-red-500\", isActive && \"text-blue-500\") // => \"text-blue-500\" when isActive\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import { LexicalComposer } from \"@lexical/react/LexicalComposer\";\nimport { LexicalComposerContext, useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { ContentEditable } from \"@lexical/react/LexicalContentEditable\";\nimport { LexicalErrorBoundary } from \"@lexical/react/LexicalErrorBoundary\";\nimport { HistoryPlugin } from \"@lexical/react/LexicalHistoryPlugin\";\nimport { OnChangePlugin } from \"@lexical/react/LexicalOnChangePlugin\";\nimport { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\nimport { AnimatePresence, motion, useReducedMotion } from \"framer-motion\";\nimport {\n $getRoot,\n $getSelection,\n $isElementNode,\n $isRangeSelection,\n COMMAND_PRIORITY_HIGH,\n KEY_ENTER_COMMAND,\n type EditorState,\n type LexicalEditor,\n type LexicalNode,\n} from \"lexical\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n type ReactNode,\n} from \"react\";\n\nimport { cn } from \"../utils/cn\";\nimport { CommandTokenNode, $isCommandTokenNode } from \"./CommandTokenNode\";\nimport { CommandTokenPlugin } from \"./CommandTokenPlugin\";\nimport type {\n ChatComposerSubmitPayload,\n ChatComposerToken,\n CommandProvider,\n} from \"./types\";\n\nconst EDITOR_THEME = {\n paragraph: \"chat-composer-paragraph\",\n};\n\nexport interface LexicalChatInputHandle {\n /** Clear the editor contents and reset history. */\n clear: () => void;\n /** Programmatically submit the current editor contents. */\n submit: () => void;\n /** Focus the editor. */\n focus: () => void;\n /**\n * Insert text at the caret (or at the end when there is no selection) and\n * focus the editor. Used by toolbar buttons to type trigger characters\n * like \"/\" or \"@\" so the matching typeahead opens.\n */\n insertText: (text: string) => void;\n}\n\nexport interface LexicalChatInputProps {\n placeholder?: string;\n disabled?: boolean;\n className?: string;\n /** Tailwind classes applied to the inner ContentEditable element. */\n inputClassName?: string;\n /** Tailwind classes applied to the placeholder overlay (e.g. font sizing). */\n placeholderClassName?: string;\n /** Slot for additional Lexical plugins (mounted inside LexicalComposer). */\n children?: ReactNode;\n /**\n * Called whenever the editor's plain-text projection changes. Use this to\n * gate a parent-rendered submit button on `text.trim().length > 0`.\n */\n onChange?: (payload: ChatComposerSubmitPayload) => void;\n /** Called when the user presses Enter (without Shift). */\n onSubmit: (payload: ChatComposerSubmitPayload) => void | Promise<void>;\n /**\n * Optional slash-command typeahead. When omitted, the editor behaves like\n * a plain rich-text input.\n */\n commandProvider?: CommandProvider | null;\n /**\n * Multiple typeahead providers, one per trigger character (e.g. `/` for\n * skills + modes, `@` for ad accounts). When supplied, this takes\n * precedence over the singular `commandProvider`. Each provider mounts its\n * own `CommandTokenPlugin` instance.\n */\n commandProviders?: CommandProvider[];\n}\n\nfunction readPayload(editor: LexicalEditor): ChatComposerSubmitPayload {\n let text = \"\";\n const tokens: ChatComposerToken[] = [];\n editor.getEditorState().read(() => {\n const root = $getRoot();\n text = root.getTextContent();\n const collect = (node: LexicalNode) => {\n if ($isCommandTokenNode(node)) {\n tokens.push({\n id: node.getCommandId(),\n kind: node.getCommandKind(),\n label: node.getCommandLabel(),\n });\n }\n if ($isElementNode(node)) {\n for (const child of node.getChildren()) collect(child);\n }\n };\n collect(root);\n });\n return { text, tokens };\n}\n\nexport const LexicalChatInput = forwardRef<LexicalChatInputHandle, LexicalChatInputProps>(\n function LexicalChatInput(\n {\n placeholder = \"Type a message...\",\n disabled = false,\n className,\n inputClassName,\n placeholderClassName,\n children,\n onChange,\n onSubmit,\n commandProvider,\n commandProviders,\n },\n ref,\n ) {\n const initialConfig = useMemo(\n () => ({\n namespace: \"ChatComposer\",\n theme: EDITOR_THEME,\n nodes: [CommandTokenNode],\n editable: !disabled,\n onError: (error: Error) => {\n // eslint-disable-next-line no-console\n console.error(\"[chat-ui composer]\", error);\n },\n }),\n // The initial config can't change after mount; `disabled` is applied via editor.setEditable below.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n );\n\n return (\n <LexicalComposer initialConfig={initialConfig}>\n <ChatInputBody\n placeholder={placeholder}\n disabled={disabled}\n className={className}\n inputClassName={inputClassName}\n placeholderClassName={placeholderClassName}\n onChange={onChange}\n onSubmit={onSubmit}\n commandProvider={commandProvider}\n commandProviders={commandProviders}\n imperativeHandle={ref}\n >\n {children}\n </ChatInputBody>\n </LexicalComposer>\n );\n },\n);\n\nfunction ChatInputBody({\n placeholder,\n disabled,\n className,\n inputClassName,\n placeholderClassName,\n children,\n onChange,\n onSubmit,\n commandProvider,\n commandProviders,\n imperativeHandle,\n}: LexicalChatInputProps & {\n imperativeHandle: React.ForwardedRef<LexicalChatInputHandle>;\n}) {\n const [editor] = useLexicalComposerContext();\n const prefersReducedMotion = useReducedMotion();\n const onSubmitRef = useRef(onSubmit);\n onSubmitRef.current = onSubmit;\n const commandMenuOpenRef = useRef(false);\n\n useEffect(() => {\n editor.setEditable(!disabled);\n }, [editor, disabled]);\n\n const submit = useCallback(() => {\n const payload = readPayload(editor);\n if (payload.text.trim().length === 0 && payload.tokens.length === 0) return;\n void onSubmitRef.current(payload);\n }, [editor]);\n\n useImperativeHandle(\n imperativeHandle,\n () => ({\n clear: () => {\n editor.update(() => {\n const root = $getRoot();\n root.clear();\n });\n },\n submit,\n focus: () => editor.focus(),\n insertText: (text: string) => {\n editor.focus(() => {\n editor.update(() => {\n let selection = $getSelection();\n if (!$isRangeSelection(selection)) {\n $getRoot().selectEnd();\n selection = $getSelection();\n }\n if ($isRangeSelection(selection)) {\n selection.insertText(text);\n }\n });\n });\n },\n }),\n [editor, submit],\n );\n\n // Intercept Enter (without Shift) and trigger submit, unless the\n // command-token typeahead menu is open — in which case the typeahead's\n // own LOW-priority handler takes the key to select an option.\n useEffect(() => {\n return editor.registerCommand(\n KEY_ENTER_COMMAND,\n (event) => {\n if (commandMenuOpenRef.current) return false;\n const keyboard = event as KeyboardEvent | null;\n if (keyboard?.shiftKey) return false;\n keyboard?.preventDefault();\n submit();\n return true;\n },\n COMMAND_PRIORITY_HIGH,\n );\n }, [editor, submit]);\n\n const handleCommandMenuStateChange = useCallback((isOpen: boolean) => {\n commandMenuOpenRef.current = isOpen;\n }, []);\n\n const handleChange = useCallback(\n (_state: EditorState) => {\n if (!onChange) return;\n const payload = readPayload(editor);\n onChange(payload);\n },\n [editor, onChange],\n );\n\n return (\n <div className={cn(\"relative w-full\", className)}>\n {/* The placeholder is absolutely positioned; this wrapper (not the padded\n outer div) is its containing block so it overlays the editable text\n exactly, regardless of caller padding. */}\n <div className=\"relative\">\n <RichTextPlugin\n contentEditable={\n <ContentEditable\n className={cn(\n \"outline-none w-full text-sm leading-relaxed\",\n \"min-h-[24px] max-h-[200px] overflow-y-auto\",\n \"text-gray-900 dark:text-zinc-100\",\n disabled && \"opacity-50 cursor-not-allowed\",\n inputClassName,\n )}\n />\n }\n placeholder={\n <div\n className={cn(\n \"pointer-events-none absolute inset-0 flex items-center overflow-hidden\",\n \"text-sm text-gray-400 dark:text-zinc-500 select-none\",\n placeholderClassName,\n )}\n >\n {prefersReducedMotion ? (\n <span className=\"truncate\">{placeholder}</span>\n ) : (\n <AnimatePresence mode=\"wait\" initial={false}>\n <motion.span\n key={placeholder}\n className=\"truncate\"\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -4 }}\n transition={{ duration: 0.18, ease: [0.4, 0, 0.2, 1] }}\n >\n {placeholder}\n </motion.span>\n </AnimatePresence>\n )}\n </div>\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n </div>\n <OnChangePlugin onChange={handleChange} />\n <HistoryPlugin />\n {(() => {\n // Plural takes precedence; fall back to singular for back-compat.\n // We mount one plugin per provider so different triggers (e.g. `/`\n // and `@`) can each fire their own typeahead. The menu-open ref is\n // shared so submit-on-Enter is gated whichever menu is open.\n const providers =\n commandProviders && commandProviders.length > 0\n ? commandProviders\n : commandProvider\n ? [commandProvider]\n : [];\n return providers.map((p, i) => (\n <CommandTokenPlugin\n key={`${p.trigger ?? \"/\"}-${i}`}\n commandProvider={p}\n onMenuStateChange={handleCommandMenuStateChange}\n />\n ));\n })()}\n {children}\n </div>\n );\n}\n\n// Re-export so consumers that mount their own LexicalComposer can grab the\n// editor instance for advanced wiring.\nexport { useLexicalComposerContext, LexicalComposerContext };\n"]}
@@ -1,6 +1,6 @@
1
- import { C as ChatMessage } from '../message-BrHFdwb2.js';
2
- import { B as BrandingData } from '../branding-SzYU4ncD.js';
3
- import '../streaming-DURrv9_E.js';
1
+ import { C as ChatMessage } from '../message-D0oMw3tR.js';
2
+ import { B as BrandingData } from '../branding-NieTEGQf.js';
3
+ import '../streaming-CmQo_OOA.js';
4
4
 
5
5
  /**
6
6
  * Types for the Miiflow chat client (transport layer).
@@ -43,6 +43,19 @@ interface MiiflowChatConfig {
43
43
  id: string;
44
44
  content: string;
45
45
  }) => void;
46
+ /**
47
+ * Branding to render before the session initializes, so the chat shell paints
48
+ * instantly without waiting on the network. Server branding from init()
49
+ * overrides this once it arrives. SSR-safe (a deterministic prop), unlike the
50
+ * cached branding the hook also applies post-mount for returning visitors.
51
+ */
52
+ initialBranding?: BrandingData;
53
+ /**
54
+ * Client tools to register as part of the init round-trip instead of via a
55
+ * separate registerTools() call. Use when the tool set is known at mount;
56
+ * dynamic tools can still be added later with registerTools().
57
+ */
58
+ tools?: ClientToolDefinition[];
46
59
  }
47
60
  interface EmbedSessionBranding {
48
61
  show_header?: boolean;
@@ -68,6 +81,12 @@ interface EmbedSession {
68
81
  token: string;
69
82
  config: EmbedSessionConfig;
70
83
  session_id: string;
84
+ /**
85
+ * Names of client tools the backend registered during init (when tools were
86
+ * folded into the init call). Transient — used to decide whether a fallback
87
+ * register-tools call is needed; not persisted to the session cache.
88
+ */
89
+ registeredTools?: string[];
71
90
  }
72
91
  interface MiiflowChatResult {
73
92
  /** Chat messages in ChatMessage format (directly compatible with ChatProvider) */
@@ -192,10 +211,28 @@ declare function getBackendBaseUrl(config: MiiflowChatConfig): string;
192
211
  * Get or create a persistent anonymous user ID stored in localStorage.
193
212
  */
194
213
  declare function getOrCreateUserId(): string;
214
+ /**
215
+ * Options for {@link initSession}.
216
+ */
217
+ interface InitSessionOptions {
218
+ /**
219
+ * A previously-issued (cached) embed token. When present it is sent as a
220
+ * Bearer credential so the backend can take a fast path — skipping the
221
+ * public-key/HMAC handshake — and just mint a fresh thread. Backward
222
+ * compatible: older backends ignore the header and run the normal handshake.
223
+ */
224
+ token?: string;
225
+ /**
226
+ * Client tool definitions (without handlers) to register in the same
227
+ * round-trip as init, so no separate register-tool(s) call is needed.
228
+ * Backward compatible: older backends ignore the extra field.
229
+ */
230
+ tools?: Array<Omit<ClientToolDefinition, "handler">>;
231
+ }
195
232
  /**
196
233
  * Initialize an embed session by calling the backend init endpoint.
197
234
  */
198
- declare function initSession(config: MiiflowChatConfig): Promise<EmbedSession>;
235
+ declare function initSession(config: MiiflowChatConfig, options?: InitSessionOptions): Promise<EmbedSession>;
199
236
  /**
200
237
  * Create a new thread for the current session.
201
238
  */
@@ -1,9 +1,11 @@
1
- export{c as clearMeasurementCache,b as measureMessageHeight}from'../chunk-O2ILSWHS.js';import {b}from'../chunk-NSTK5EUQ.js';import {useState,useRef,useEffect,useMemo,useCallback}from'react';function A(t){return t.baseUrl?t.baseUrl.replace(/\/api\/?$/,""):t.bundleUrl?.includes("localhost")||t.bundleUrl?.includes("127.0.0.1")||false?"http://localhost:8003":"https://api.miiflow.ai"}function U(){let t="miiflow-user-id",n=null;try{n=localStorage.getItem(t);}catch{}if(!n){n=`muid_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;try{localStorage.setItem(t,n);}catch{}}return n}async function me(t){let n=A(t),l=await fetch(`${n}/api/embed/init`,{method:"POST",headers:{"Content-Type":"application/json","X-Embed-Public-Key":t.publicKey,"x-mii-user-id":U()},body:JSON.stringify({assistant_id:t.assistantId,user_data:{user_id:t.userId,name:t.userName,email:t.userEmail}})});if(!l.ok){let d=await l.text();throw new Error(`Init failed: ${l.status} - ${d}`)}let c=await l.json();if(!c.success)throw new Error(c.error||"Failed to initialize session");return {token:c.token,config:c.config,session_id:c.session_id}}async function ge(t,n){let l=A(t),c=await fetch(`${l}/api/embed/graphql`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`,"x-mii-user-id":U()},body:JSON.stringify({operationName:"CreateThread",variables:{input:{assistantId:n.config.assistant_id,name:"New Thread",isPreview:false}},query:`mutation CreateThread($input: CreateThreadInput!) {
1
+ export{c as clearMeasurementCache,b as measureMessageHeight}from'../chunk-NG4HKXYB.js';import {b}from'../chunk-QECTWT2H.js';import {useState,useRef,useEffect,useMemo,useCallback}from'react';function ge(e){try{let o=e.split(".");if(o.length!==3)return null;let r=o[1].replace(/-/g,"+").replace(/_/g,"/"),s=atob(r),l=JSON.parse(s);return typeof l.exp=="number"?l.exp*1e3:null}catch{return null}}function we(e,o){let r=ge(e);return r===null?true:r-Date.now()<=o}function We(e){let o=ge(e);return o===null?true:Date.now()>=o}function qe(e){let o=ge(e);return o===null?0:Math.max(0,o-Date.now())}function O(e){return e.baseUrl?e.baseUrl.replace(/\/api\/?$/,""):e.bundleUrl?.includes("localhost")||e.bundleUrl?.includes("127.0.0.1")||false?"http://localhost:8003":"https://api.miiflow.ai"}function B(){let e="miiflow-user-id",o=null;try{o=localStorage.getItem(e);}catch{}if(!o){o=`muid_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;try{localStorage.setItem(e,o);}catch{}}return o}async function ie(e,o={}){let r=O(e),s={"Content-Type":"application/json","X-Embed-Public-Key":e.publicKey,"x-mii-user-id":B()};o.token&&(s.Authorization=`Bearer ${o.token}`);let l=await fetch(`${r}/api/embed/init`,{method:"POST",headers:s,body:JSON.stringify({assistant_id:e.assistantId,user_data:{user_id:e.userId,name:e.userName,email:e.userEmail},...o.tools&&o.tools.length>0?{tools:o.tools}:{}})});if(!l.ok){let d=await l.text();throw new Error(`Init failed: ${l.status} - ${d}`)}let u=await l.json();if(!u.success)throw new Error(u.error||"Failed to initialize session");return {token:u.token,config:u.config,session_id:u.session_id,registeredTools:Array.isArray(u.registered_tools)?u.registered_tools:void 0}}var Je="miiflow-session",Xe=300*1e3;function be(e){return `${Je}:${e.publicKey}:${e.assistantId}:${B()}`}function Me(e){try{let o=localStorage.getItem(be(e));if(!o)return null;let r=JSON.parse(o);return !r?.token||!r?.config||we(r.token,Xe)?null:r}catch{return null}}function Ae(e,o){try{let r={token:o.token,config:o.config};localStorage.setItem(be(e),JSON.stringify(r));}catch{}}function Ie(e){try{localStorage.removeItem(be(e));}catch{}}async function ye(e,o){let r=O(e),s=await fetch(`${r}/api/embed/graphql`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o.token}`,"x-mii-user-id":B()},body:JSON.stringify({operationName:"CreateThread",variables:{input:{assistantId:o.config.assistant_id,name:"New Thread",isPreview:false}},query:`mutation CreateThread($input: CreateThreadInput!) {
2
2
  createThread(input: $input) {
3
3
  thread { id status name isPreview }
4
4
  }
5
- }`})});if(!c.ok)throw new Error(`Failed to create thread: ${c.status}`);let d=await c.json(),m=d.data?.createThread?.thread?.id;if(!m)throw new Error("No thread ID returned");return {threadId:m,token:d.token}}async function Oe(t,n,l){let c=A(t);await fetch(`${c}/api/embed/update`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`},body:JSON.stringify({user_data:l})});}async function he(t,n,l){let d=`${A(t)}/api/embed/upload-attachment`,m=new FormData;m.append("file",l);let p=await fetch(d,{method:"POST",headers:{Authorization:`Bearer ${n.token}`,"x-mii-user-id":U()},body:m});if(!p.ok){let T=await p.text();throw new Error(`Upload failed: ${p.status} - ${T}`)}let o=(await p.json()).attachment?.id;if(!o)throw new Error("No attachment ID returned");return o}async function _e(t,n,l){let c=A(t),d=await fetch(`${c}/api/embed/system-event`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`,"x-mii-user-id":U()},body:JSON.stringify({thread_id:n.config.thread_id,system_event:{action:l.action,description:l.description,followUpInstruction:l.followUpInstruction,metadata:l.metadata||{}}})});if(!d.ok){let p=await d.text();throw new Error(`Failed to send system event: ${d.status} - ${p}`)}let m=await d.json();if(!m.success)throw new Error(m.error||"Failed to send system event")}async function be(t,n,l){let c=A(t),d=await fetch(`${c}/api/embed/page-context`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`,"x-mii-user-id":U()},body:JSON.stringify({thread_id:n.config.thread_id,page_context:{action:l.action,content:l.content,metadata:l.metadata||{}}})});if(!d.ok){let p=await d.text();throw new Error(`Failed to send page context: ${d.status} - ${p}`)}let m=await d.json();if(!m.success)throw new Error(m.error||"Failed to send page context")}async function Q(t,n,l){let c=A(t),d=await fetch(`${c}/api/embed/tool-result`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`},body:JSON.stringify(l)});if(!d.ok){let p=await d.text();throw new Error(`Failed to send tool result: ${d.status} - ${p}`)}let m=await d.json();if(!m.success)throw new Error(`Failed to send tool result: ${m.error}`)}async function ae(t,n,l){let c=A(t);if(l.length===1){let d=await fetch(`${c}/api/embed/register-tool`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`},body:JSON.stringify(l[0])});if(!d.ok){let p=await d.text();throw new Error(`Failed to register tool: ${d.status} - ${p}`)}let m=await d.json();if(!m.success)throw new Error(`Failed to register tool: ${m.error||"Unknown error"}`)}else if(l.length>1){let d=await fetch(`${c}/api/embed/register-tools`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`},body:JSON.stringify(l)});if(!d.ok){let p=await d.text();throw new Error(`Failed to register tools: ${d.status} - ${p}`)}let m=await d.json();if(!m.success)throw new Error(`Failed to register tools: ${m.error||"Unknown error"}`)}}var Ce=new Set(["string","number","integer","boolean","array","object","null"]),Ne=/^[a-zA-Z_][a-zA-Z0-9_]*$/,y=class extends Error{constructor(n){super(n),this.name="ToolValidationError";}};function de(t){if(!t.name)throw new y("Tool name is required");if(!t.description)throw new y("Tool description is required");if(!t.parameters)throw new y("Tool parameters schema is required");if(typeof t.handler!="function")throw new y("Tool handler must be a function");Ue(t.name),$e(t.description),Re(t.parameters);}function Ue(t){if(typeof t!="string")throw new y("Tool name must be a string");if(t.length===0)throw new y("Tool name cannot be empty");if(t.length>64)throw new y("Tool name too long (max 64 characters)");if(!Ne.test(t))throw new y("Tool name must start with letter/underscore and contain only alphanumeric characters and underscores")}function $e(t){if(typeof t!="string")throw new y("Tool description must be a string");if(t.trim().length===0)throw new y("Tool description cannot be empty");if(t.length>500)throw new y("Tool description too long (max 500 characters)")}function Re(t){if(typeof t!="object"||t===null||Array.isArray(t))throw new y("Parameters must be a JSON Schema object");if(t.type!=="object")throw new y("Parameters schema must be of type 'object' (function parameters)");if(t.properties&&typeof t.properties=="object")for(let[n,l]of Object.entries(t.properties))ce(n,l);if(t.required!==void 0){if(!Array.isArray(t.required))throw new y("'required' must be an array");for(let n of t.required)if(typeof n!="string")throw new y("'required' array must contain only strings")}if(t.additionalProperties!==void 0&&typeof t.additionalProperties!="boolean"&&(typeof t.additionalProperties!="object"||t.additionalProperties===null))throw new y("'additionalProperties' must be boolean or object")}function ce(t,n){if(typeof n!="object"||n===null||Array.isArray(n))throw new y(`Property '${t}' schema must be an object`);if(n.type!==void 0){let l=Array.isArray(n.type)?n.type:[n.type];for(let c of l)if(!Ce.has(c))throw new y(`Invalid type '${c}' for property '${t}'. Valid types: ${Array.from(Ce).join(", ")}`)}if(n.enum!==void 0&&!Array.isArray(n.enum))throw new y(`Property '${t}' enum must be an array`);if(n.properties&&typeof n.properties=="object")for(let[l,c]of Object.entries(n.properties))ce(`${t}.${l}`,c);n.items&&(Array.isArray(n.items)?n.items.forEach((l,c)=>{ce(`${t}[${c}]`,l);}):ce(`${t}[]`,n.items));}function pe(t){return {name:t.name,description:t.description,parameters:t.parameters}}var Be=new Set(["image/jpeg","image/jpg","image/png","image/webp","image/bmp"]);function je(t){return Be.has(t.type)}function Fe(t){return new Promise((n,l)=>{let c=URL.createObjectURL(t),d=new Image;d.onload=()=>{URL.revokeObjectURL(c),n(d);},d.onerror=()=>{URL.revokeObjectURL(c),l(new Error("Failed to load image"));},d.src=c;})}function we(t,n,l,c){return new Promise((d,m)=>{let p=Math.round(t.naturalWidth*n),h=Math.round(t.naturalHeight*n),o=document.createElement("canvas");o.width=p,o.height=h;let T=o.getContext("2d");if(!T){m(new Error("Canvas 2D context unavailable"));return}T.drawImage(t,0,0,p,h),o.toBlob($=>{$?d($):m(new Error("Canvas toBlob returned null"));},c,l);})}async function Se(t){if(!je(t)||t.size<=4194304)return t;let n=await Fe(t),l=Math.min(1,4096/Math.max(n.naturalWidth,n.naturalHeight)),c="image/jpeg",d=[.85,.7,.5,.3,.15],m=[l,l*.75,l*.5,l*.25];for(let h of d){let o=await we(n,l,h,c);if(o.size<=4194304)return ye(o,t.name,c)}for(let h of m.slice(1))for(let o of d){let T=await we(n,h,o,c);if(T.size<=4194304)return ye(T,t.name,c)}let p=await we(n,.1,.1,c);return ye(p,t.name,c)}function ye(t,n,l){let c=n.replace(/\.[^.]+$/,".jpg");return new File([t],c,{type:l,lastModified:Date.now()})}var ze=21e3,We=1e3,qe=3e4;function Le(t,n){if(t.webSocketUrl){let p=new URL(t.webSocketUrl);return p.pathname=`/ws/assistant/thread/${n.config.thread_id}/`,p.searchParams.set("role","user"),p.searchParams.set("user_id",U()),p.searchParams.set("embed_token",n.token),p.toString()}let d=A(t).replace(/\/api$/,"").replace(/^https:/,"wss:").replace(/^http:/,"ws:"),m=U();return `${d}/ws/assistant/thread/${n.config.thread_id}/?role=user&user_id=${encodeURIComponent(m)}&embed_token=${encodeURIComponent(n.token)}`}function He(t){let n=t?.config.branding;return n?{customName:n.custom_name,messageFontSize:n.message_font_size,welcomeMessage:n.welcome_message,chatboxPlaceholder:n.chatbox_placeholder,backgroundBubbleColor:n.background_bubble_color,headerBackgroundColor:n.header_background_color,showHeader:n.show_header,rotatingPlaceholders:n.rotating_placeholders,presetQuestions:n.preset_questions,chatbotLogo:n.chatbot_logo,assistantAvatar:n.assistant_avatar}:null}async function Je(t,n,l,c){let d=new TextDecoder,m=Date.now(),p="",h=null,o=[],T,$,te,R=[],b=false,_="answer",C="",B,P,I,L,H,j,J,X,O,G,Y,V,K,Z,oe=false,ne="",se=n.config.branding,N=()=>{(C||_==="tool")&&(o.push({type:_,content:C,toolName:B,toolDescription:P,success:I,status:L,subtaskId:H,planData:j,subtaskData:J,isSynthesis:X,isReplan:O,toolArgs:G,replanAttempt:Y,maxReplans:V,failureReason:K,progress:Z}),C="",B=void 0,P=void 0,I=void 0,L=void 0,H=void 0,j=void 0,J=void 0,X=void 0,O=void 0,G=void 0,Y=void 0,V=void 0,K=void 0,Z=void 0);},r=()=>{let f=o.map(g=>g);return (C||_==="tool")&&f.push({type:_,content:C,toolName:B,toolDescription:P,success:I,status:L,subtaskId:H,planData:j,subtaskData:J,isSynthesis:X,isReplan:O,toolArgs:G,replanAttempt:Y,maxReplans:V,failureReason:K,progress:Z}),f},s=()=>{let f=r();if(h)c.onMessageUpdate({id:h,textContent:p,reasoning:f,suggestedActions:T,medias:R.length>0?R:void 0});else {h=`assistant-${Date.now()}`;let g={id:h,textContent:p,participant:{id:"assistant",name:se?.custom_name||n.config.assistant_name,role:"assistant",avatarUrl:se?.assistant_avatar},createdAt:new Date().toISOString(),isStreaming:true,reasoning:f,suggestedActions:T,medias:R.length>0?R:void 0};c.onMessageCreate(g);}};for(;;){let{done:f,value:g}=await t.read();if(f)break;let x=d.decode(g,{stream:true}),w=(ne+x).split(`
6
- `);x.endsWith(`
7
- `)?ne="":ne=w.pop()||"";for(let z of w){if(!z.startsWith("data: "))continue;let M=z.slice(6);if(M==="[DONE]")break;try{let e=JSON.parse(M);if(e.type==="assistant_chunk"){if(e.is_tool_planned){(C||_!=="answer")&&(N(),_="answer"),o.push({type:"tool",content:"",toolName:e.tool_name,toolDescription:e.tool_description,status:"planned",subtaskId:e.subtask_id}),s();continue}if(e.is_tool_executing){for(let a=o.length-1;a>=0;a--){let u=o[a];if(u.type==="tool"&&u.toolName===e.tool_name&&(e.subtask_id===void 0||u.subtaskId===e.subtask_id)){o[a].status="executing";break}}s();continue}if(e.is_observation){for(let a=o.length-1;a>=0;a--){let u=o[a];if(u.type==="tool"&&u.toolName===e.tool_name&&(e.subtask_id===void 0||u.subtaskId===e.subtask_id)){o[a].status="completed";break}}s();continue}if(e.suggested_actions){T=e.suggested_actions.map(a=>({id:a.action,label:a.label,value:a.action})),s();continue}if(e.is_wave_start){(C||_!=="answer")&&(N(),_="answer"),o.push({type:"wave_start",content:"",waveNumber:e.wave_number,isParallel:!0,waveData:{waveNumber:e.wave_number,subtaskIds:e.subtask_ids||[],parallelCount:e.parallel_count||0,totalWaves:e.total_waves||1}}),s();continue}if(e.is_wave_complete){o.push({type:"wave_complete",content:"",waveNumber:e.wave_number,isParallel:!0,waveData:{waveNumber:e.wave_number,subtaskIds:[],parallelCount:0,totalWaves:0,completedIds:e.completed_ids||[],success:e.success,executionTime:e.execution_time}}),s();continue}if(e.is_parallel_subtask_start){o.push({type:"parallel_subtask_start",content:"",subtaskId:e.subtask_id,waveNumber:e.wave_number,isParallel:!0,parallelSubtaskData:{subtaskId:e.subtask_id,waveNumber:e.wave_number,description:e.description}}),s();continue}if(e.is_parallel_subtask_complete){o.push({type:"parallel_subtask_complete",content:"",subtaskId:e.subtask_id,waveNumber:e.wave_number,isParallel:!0,success:e.success,parallelSubtaskData:{subtaskId:e.subtask_id,waveNumber:e.wave_number,success:e.success,result:e.result,error:e.error,executionTime:e.execution_time}}),s();continue}if(e.is_multi_agent_planning){oe=!0,(C||_!=="answer")&&(N(),_="answer"),o.push({type:"multi_agent_planning",content:"",isMultiAgent:!0}),s();continue}if(e.is_reasoning&&e.reasoning_delta){let a=o.findIndex(u=>u.type==="thinking"&&u.isMultiAgent);a>=0?o[a]={...o[a],content:(o[a].content||"")+e.reasoning_delta}:o.push({type:"thinking",content:e.reasoning_delta,isMultiAgent:!0}),s();continue}if(e.is_multi_agent_planning_complete){let a=o.findIndex(u=>u.type==="multi_agent_planning"&&u.isMultiAgent);a>=0?o[a]={...o[a],subagentAllocations:e.subagents||[]}:o.push({type:"multi_agent_planning",content:"",isMultiAgent:!0,subagentAllocations:e.subagents||[]}),s();continue}if(e.is_multi_agent_execution_start)continue;if(e.is_subagent_start){o.push({type:"subagent_start",content:"",isMultiAgent:!0,subagentInfo:{id:e.subagent_id,name:e.subagent_name,task:e.task,status:"running"}}),s();continue}if(e.is_subagent_progress){let a=o.findIndex(u=>u.type==="subagent_start"&&u.subagentInfo?.id===e.subagent_id);a!==-1&&o[a].subagentInfo&&(o[a]={...o[a],content:e.progress||""}),s();continue}if(e.is_subagent_complete){o.push({type:"subagent_complete",content:"",isMultiAgent:!0,subagentInfo:{id:e.subagent_id,name:e.subagent_name,status:"completed",result:e.result,executionTime:e.execution_time}}),s();continue}if(e.is_subagent_failed){o.push({type:"subagent_failed",content:"",isMultiAgent:!0,subagentInfo:{id:e.subagent_id,name:e.subagent_name,status:"failed",error:e.error}}),s();continue}if(e.is_synthesis_start&&oe){o.push({type:"synthesis",content:"",isMultiAgent:!0,isSynthesis:!0}),s();continue}if(e.plan_data){let a=e.plan_data;j={goal:a.goal||"",reasoning:a.reasoning||"",subtasks:(a.subtasks||[]).map(u=>({id:Number(u.id),description:u.description,required_tools:u.required_tools,dependencies:u.dependencies,status:"pending"})),total_subtasks:a.subtasks?.length||0,completed_subtasks:0,failed_subtasks:0,progress_percentage:0};}e.subtask_data&&(J=e.subtask_data),e.is_synthesis_start&&(X=!0),e.is_replan&&(O=!0),e.tool_args&&(G=e.tool_args),e.replan_attempt!==void 0&&(Y=e.replan_attempt),e.max_replans!==void 0&&(V=e.max_replans),e.failure_reason&&(K=e.failure_reason),e.progress&&(Z=e.progress);let i="answer";if(e.is_thinking?i="thinking":e.is_planning||e.is_plan_complete||e.is_replanning?i="planning":e.is_subtask_start||e.is_subtask_complete||e.is_subtask_failed?i="subtask":e.is_progress_update&&(i="progress"),i!==_&&(N(),_=i),e.tool_name&&(B=e.tool_name),e.success!==void 0&&(I=e.success),e.subtask_id!==void 0&&(H=e.subtask_id),i==="thinking"){C+=e.chunk||"";let a=C.match(/"thought"\s*:\s*"((?:[^"\\]|\\.)*)"/);a&&(C=a[1].replace(/\\n/g,`
8
- `).replace(/\\"/g,'"').replace(/\\t/g," ").replace(/\\\\/g,"\\"));}else if(i==="answer"){let a=e.chunk?.trim()||"",u=p.trim();a&&u&&a===u||(p+=e.chunk||"");}else C+=e.chunk||"";e.previous_message_id&&c.onUserMessageIdUpdate(l,e.previous_message_id),s();}else if(e.type==="claude_text"){p+=e.chunk||"";let i=o.find(a=>a.type==="claude_text");i?i.content+=e.chunk||"":o.push({type:"claude_text",content:e.chunk||"",orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_thinking")o.push({type:"claude_thinking",content:e.content||"",orchestrator:"claude_agent_sdk"}),s();else if(e.type==="claude_file_read"){let i={toolUseId:e.tool_use_id,operation:"read",filePath:e.file_path,status:e.status,content:e.content,totalLines:e.total_lines,language:e.language,error:e.error,durationMs:e.duration_ms},a=o.findIndex(u=>u.type==="file_operation"&&u.toolUseId===e.tool_use_id);a>=0?o[a].fileOperationData=i:o.push({type:"file_operation",content:"",toolUseId:e.tool_use_id,fileOperationData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_file_edit"){let i={toolUseId:e.tool_use_id,operation:"edit",filePath:e.file_path,status:e.status,oldString:e.old_string,newString:e.new_string,error:e.error,durationMs:e.duration_ms},a=o.findIndex(u=>u.type==="file_operation"&&u.toolUseId===e.tool_use_id);a>=0?o[a].fileOperationData=i:o.push({type:"file_operation",content:"",toolUseId:e.tool_use_id,fileOperationData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_file_write"){let i={toolUseId:e.tool_use_id,operation:"write",filePath:e.file_path,status:e.status,error:e.error,durationMs:e.duration_ms},a=o.findIndex(u=>u.type==="file_operation"&&u.toolUseId===e.tool_use_id);a>=0?o[a].fileOperationData=i:o.push({type:"file_operation",content:"",toolUseId:e.tool_use_id,fileOperationData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_bash"){let i={toolUseId:e.tool_use_id,command:e.command,description:e.description,status:e.status,stdout:e.stdout,stderr:e.stderr,exitCode:e.exit_code,durationMs:e.duration_ms},a=o.findIndex(u=>u.type==="terminal"&&u.toolUseId===e.tool_use_id);a>=0?o[a].terminalData=i:o.push({type:"terminal",content:"",toolUseId:e.tool_use_id,terminalData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_search"){let i={toolUseId:e.tool_use_id,tool:e.tool,pattern:e.pattern,path:e.path,status:e.status,results:(e.results||[]).map(u=>({filePath:u.file_path,lineNumber:u.line_number,snippet:u.snippet})),totalCount:e.total_count||0,error:e.error,durationMs:e.duration_ms},a=o.findIndex(u=>u.type==="search_results"&&u.toolUseId===e.tool_use_id);a>=0?o[a].searchResultsData=i:o.push({type:"search_results",content:"",toolUseId:e.tool_use_id,searchResultsData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_web_search"||e.type==="claude_web_fetch"){let i={toolUseId:e.tool_use_id,operation:e.type==="claude_web_search"?"search":"fetch",query:e.query,url:e.url,status:e.status,results:e.results,content:e.content,error:e.error,durationMs:e.duration_ms},a=o.findIndex(u=>u.type==="web_operation"&&u.toolUseId===e.tool_use_id);a>=0?o[a].webOperationData=i:o.push({type:"web_operation",content:"",toolUseId:e.tool_use_id,webOperationData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_subagent_start"){let i={subagentId:e.subagent_id,subagentType:e.subagent_type,description:e.description,prompt:e.prompt,status:"running",nestedChunks:[]};o.push({type:"subagent",content:"",toolUseId:e.parent_tool_use_id,subagentData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_subagent_chunk"){let i=o.findIndex(a=>a.type==="subagent"&&a.subagentData?.subagentId===e.subagent_id);i>=0&&o[i].subagentData&&o[i].subagentData.nestedChunks.push({type:e.is_tool?"tool":"answer",content:e.chunk||"",toolName:e.tool_name,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_subagent_complete"){let i=o.findIndex(a=>a.type==="subagent"&&a.subagentData?.subagentId===e.subagent_id);i>=0&&o[i].subagentData&&(o[i].subagentData.status="completed",o[i].subagentData.result=e.result,o[i].subagentData.durationMs=e.duration_ms),s();}else if(e.type==="claude_tool_use"||e.type==="claude_tool_result"){let i={toolUseId:e.tool_use_id,toolName:e.tool_name,toolDescription:e.tool_description,toolInput:e.tool_input,status:e.type==="claude_tool_use"?"pending":e.is_error?"error":"completed",content:e.content,isError:e.is_error,durationMs:e.duration_ms},a=o.findIndex(u=>u.claudeToolData?.toolUseId===e.tool_use_id);a>=0?o[a].claudeToolData=i:o.push({type:"tool",content:e.content||"",toolUseId:e.tool_use_id,toolName:e.tool_name,toolDescription:e.tool_description,status:i.status==="pending"?"planned":"completed",claudeToolData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="clarification_needed"){N();let i={question:e.question||"",options:e.options||[],context:e.context,allowFreeText:e.allow_free_text!==!1,subtaskId:e.subtask_id,subtaskDescription:e.subtask_description,subagentName:e.subagent_name,subagentRole:e.subagent_role,toolCallId:e.tool_call_id};o.push({type:"clarification_needed",content:i.question,clarificationData:i,subtaskId:e.subtask_id}),$=i,p||(p=i.question),s();}else if(e.type==="tool_approval_needed"){N();let i={toolName:e.tool_name||"",toolDescription:e.tool_description||"",toolInputs:e.tool_inputs||{},toolSchema:e.tool_schema,toolCallId:e.tool_call_id};o.push({type:"tool_approval_needed",content:i.toolDescription,toolApprovalData:i}),te=i,s();}else if(e.type==="media"){let i=e.media_data;i&&(R=[...R,{id:i.id,url:i.url,mediaType:i.media_type||"image",altText:i.alt_text}],s());}else if(e.type==="assistant_complete"){N(),b=!0;let i=e.message?.text_content||p,a=e.message?.id,u=e.message?.metadata?.sources,W=(Date.now()-m)/1e3;c.onComplete(h,i,a,o,T,u,$,W,te),p=i,a&&(h=a);break}else if(e.type==="client_tool_invocation"&&e.invocation&&c.onToolInvocation)c.onToolInvocation(e.invocation);else {if(e.type==="error")throw new Error(e.error||"Stream error");if(e.type==="done"){if(h&&!b){N();let i=(Date.now()-m)/1e3;c.onComplete(h,p||"",e.message_id,o,T,void 0,$,i,te);}else e.message_id&&h&&c.onMessageUpdate({id:h,isStreaming:!1});e.message_id&&(h=e.message_id);break}}}catch(e){if(e instanceof Error&&e.message!=="Stream error"&&(e.message.startsWith("Stream error")||e.message.startsWith("HTTP error")))throw e}}}return {assistantMsgId:h,assistantContent:p}}function Xe(t){let[n,l]=useState([]),[c,d]=useState(false),[m,p]=useState(null),[h,o]=useState(null),[T,$]=useState(true),[te,R]=useState(null),b$1=useRef(t);b$1.current=t;let _=useRef(h);_.current=h;let C=useRef(c);C.current=c;let B=useRef(null),P=useRef(new Map),I=useRef(new Map);useEffect(()=>{let r=false;async function s(){try{let f=await me(b$1.current);r||(o(f),$(!1));}catch(f){r||(R(f instanceof Error?f.message:"Failed to initialize"),$(false));}}return s(),()=>{r=true;}},[t.publicKey,t.assistantId]);let L=useMemo(()=>He(h),[h]),H=b(L),j=useRef(new Map),J=useCallback(async r=>{let s=_.current;if(!s)throw new Error("Not initialized");if(r.type.startsWith("image/"))try{r=await Se(r);}catch(g){console.warn("Image compression failed, using original:",g);}let f=await he(b$1.current,s,r);return j.current.set(f,{id:f,filename:r.name,mimeType:r.type,size:r.size,isImage:r.type.startsWith("image/"),isVideo:r.type.startsWith("video/"),isDocument:!r.type.startsWith("image/")&&!r.type.startsWith("video/")}),f},[]),X=useCallback(r=>{j.current.delete(r);},[]),O=useCallback(async r=>{let s=_.current;if(!s)throw new Error("Not initialized");let{invocation_id:f,tool_name:g,parameters:x}=r;console.log(`[Miiflow] Tool invocation received: "${g}" (id: ${f})`);let k=P.current.get(g);if(!k)return false;try{let w=await Promise.race([k(x),new Promise((z,M)=>setTimeout(()=>M(new Error("Tool execution timeout (30s)")),3e4))]);return console.log(`[Miiflow] Tool "${g}" executed successfully (id: ${f})`),await Q(b$1.current,s,{invocation_id:f,result:w}),console.log(`[Miiflow] Tool result sent for "${g}" (id: ${f})`),!0}catch(w){return console.error(`[Miiflow] Tool '${g}' execution failed:`,w),await Q(b$1.current,s,{invocation_id:f,error:w instanceof Error?w.message:String(w)}),true}},[]);useEffect(()=>{if(!h)return;let r=h,s=null,f=null,g=null,x=0,k=false;function w(){if(k)return;let z=Le(b$1.current,r);s=new WebSocket(z),s.onopen=()=>{console.log("[Miiflow] WebSocket connected"),x=0,f=setInterval(()=>{s?.readyState===WebSocket.OPEN&&s.send(JSON.stringify({type:"heartbeat"}));},ze);},s.onmessage=M=>{try{let e=JSON.parse(M.data);e.type==="client_tool_invocation"&&e.invocation&&O(e.invocation).then(async i=>{if(!i){let a=b$1.current.onToolInvocationFallback;a&&await a(e.invocation)||Q(b$1.current,r,{invocation_id:e.invocation.invocation_id,error:`No handler found for tool '${e.invocation.tool_name}'`}).catch(console.error);}}).catch(console.error);}catch{}},s.onclose=()=>{if(f&&(clearInterval(f),f=null),!k){let M=Math.min(We*Math.pow(2,x),qe);x++,g=setTimeout(w,M);}},s.onerror=()=>{};}return w(),()=>{k=true,f&&clearInterval(f),g&&clearTimeout(g),s&&(s.onclose=null,s.close());}},[h,O]);let G=useCallback(async r=>{let s=_.current;if(!s)throw new Error("Not initialized");await _e(b$1.current,s,r);},[]),Y=useCallback(async r=>{let s=_.current;if(!s)throw new Error("Not initialized");await be(b$1.current,s,r);},[]),V=useCallback(async(r,s,f)=>{let g=_.current,x=!!r.trim(),k=s&&s.length>0;if(!x&&!k||C.current||!g)return;C.current=true;let w=`msg-${Date.now()}`,z=!!f?.is_clarification_response,M=s?.map(a=>j.current.get(a)).filter(Boolean);s?.forEach(a=>j.current.delete(a));let e=`assistant-pending-${Date.now()}`,i={id:e,textContent:"",participant:{id:"assistant",name:g.config.branding?.custom_name||g.config.assistant_name,role:"assistant",avatarUrl:g.config.branding?.assistant_avatar},createdAt:new Date().toISOString(),isStreaming:true};if(z)l(a=>[...a,i]);else {let a={id:w,textContent:r,participant:{id:"user",name:b$1.current.userName||"You",role:"user"},createdAt:new Date().toISOString(),attachments:M?.length?M:void 0};l(u=>[...u,a,i]),b$1.current.onUserMessageCreated?.({id:w,content:r});}d(true),p(e);try{let a=A(b$1.current),u=new AbortController;B.current=u;let W=await fetch(`${a}/assistant/message/stream/`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${g.token}`,"x-mii-user-id":U()},body:JSON.stringify({thread_id:g.config.thread_id,text_content:r,message_id:w,metadata:f||{},attachment_ids:s||[]}),signal:u.signal});if(!W.ok)throw new Error(`HTTP error: ${W.status}`);let re=W.body?.getReader();if(!re)throw new Error("No response body");let ie=await Je(re,g,w,{onMessageCreate:S=>{p(S.id),l(D=>[...D.filter(F=>F.id!==e),S]);},onMessageUpdate:S=>{l(D=>D.map(v=>v.id===S.id?{...v,...S}:v));},onUserMessageIdUpdate:(S,D)=>{l(v=>v.map(F=>F.id===S?{...F,id:D}:F));},onComplete:(S,D,v,F,le,xe,De,ve,Ae)=>{S&&l(Me=>Me.map(ue=>ue.id===S?{...ue,id:v||ue.id,textContent:D,isStreaming:!1,reasoning:F,suggestedActions:le,citations:xe,pendingClarification:De,pendingToolApproval:Ae,executionTime:ve}:ue)),b$1.current.onAssistantMessageComplete?.({id:v||S||"",content:D});},onToolInvocation:async S=>{if(!await O(S)){let v=b$1.current.onToolInvocationFallback;if(!(v?await v(S):!1)){let le=_.current;le&&await Q(b$1.current,le,{invocation_id:S.invocation_id,error:`No handler found for tool '${S.tool_name}'`});}}}});ie.assistantMsgId&&l(S=>S.map(D=>D.id===ie.assistantMsgId?{...D,isStreaming:!1}:D));}catch(a){if(a instanceof DOMException&&a.name==="AbortError")return;console.error("[Miiflow] Send error:",a);let u=_.current,W={id:`error-${Date.now()}`,textContent:"Sorry, I encountered an error. Please try again.",participant:{id:"assistant",name:u?.config.branding?.custom_name||u?.config.assistant_name||"Assistant",role:"assistant",avatarUrl:u?.config.branding?.assistant_avatar},createdAt:new Date().toISOString()};l(re=>[...re.filter(ie=>ie.id!==e),W]),R(a instanceof Error?a.message:"Send failed");}finally{B.current=null,d(false),p(null);}},[O]),K=useCallback(()=>{C.current&&(B.current?.abort(),B.current=null,l(r=>r.map(s=>s.isStreaming?{...s,isStreaming:false}:s)),C.current=false,d(false),p(null));},[]),Z=useCallback(async()=>{let r=_.current;if(!r)throw new Error("Not initialized");let s=await ge(b$1.current,r);s.token||console.warn("[Miiflow] CreateThread did not return new token \u2014 tools may register to wrong thread");let f={...r,config:{...r.config,thread_id:s.threadId},token:s.token||r.token};if(_.current=f,o(f),l([]),I.current.size>0){console.log(`[Miiflow] Re-registering ${I.current.size} tools on new thread`);try{await ae(b$1.current,f,Array.from(I.current.values()));}catch(g){console.warn("[Miiflow] Failed to re-register tools:",g);}}return s.threadId},[]),oe=useCallback(async r=>{let s=_.current;if(!s)throw new Error("Not initialized");de(r),P.current.set(r.name,r.handler);let f=pe(r);I.current.set(r.name,f);try{await ae(b$1.current,s,[f]),console.log(`[Miiflow] Tool registered: "${r.name}"`);}catch(g){throw P.current.delete(r.name),I.current.delete(r.name),g}},[]),ne=useCallback(async r=>{let s=_.current;if(!s)throw new Error("Not initialized");for(let k of r)de(k);let f=new Map(P.current),g=new Map(I.current),x=[];for(let k of r){P.current.set(k.name,k.handler);let w=pe(k);I.current.set(k.name,w),x.push(w);}try{await ae(b$1.current,s,x);let k=r.map(w=>w.name);console.log(`[Miiflow] Tools registered: ${JSON.stringify(k)} (${r.length} tools)`);}catch(k){throw P.current=f,I.current=g,k}},[]),se=useMemo(()=>n.filter(r=>r.participant.role!=="system").map(r=>({id:r.id,textContent:r.textContent?.replace(/\[ref:[^\]]+\]/g,"")||r.textContent,participant:r.participant,createdAt:r.createdAt,isStreaming:r.isStreaming,reasoning:r.reasoning,suggestedActions:r.suggestedActions,citations:r.citations,attachments:r.attachments,pendingClarification:r.pendingClarification,pendingToolApproval:r.pendingToolApproval,executionTime:r.executionTime})),[n]),N=useCallback(r=>{o(r);},[]);return {messages:se,isStreaming:c,streamingMessageId:m,sendMessage:V,uploadFile:J,removeUploadedAttachment:X,session:h,loading:T,error:te,branding:L,brandingCSSVars:H,startNewThread:Z,registerTool:oe,registerTools:ne,sendSystemEvent:G,sendPageContext:Y,handleToolInvocation:O,updateSession:N,stopStreaming:K}}function fe(t){try{let n=t.split(".");if(n.length!==3)return null;let l=n[1].replace(/-/g,"+").replace(/_/g,"/"),c=atob(l),d=JSON.parse(c);return typeof d.exp=="number"?d.exp*1e3:null}catch{return null}}function Ge(t,n){let l=fe(t);return l===null?true:l-Date.now()<=n}function Ye(t){let n=fe(t);return n===null?true:Date.now()>=n}function Ve(t){let n=fe(t);return n===null?0:Math.max(0,n-Date.now())}export{y as ToolValidationError,ge as createThread,A as getBackendBaseUrl,U as getOrCreateUserId,Ve as getTimeUntilExpiry,me as initSession,Ye as isTokenExpired,Ge as isTokenExpiringSoon,fe as parseTokenExpiry,ae as registerToolsOnBackend,be as sendPageContext,_e as sendSystemEvent,Q as sendToolResult,pe as serializeToolDefinition,Oe as updateUser,he as uploadFile,Xe as useMiiflowChat,de as validateToolDefinition};//# sourceMappingURL=index.js.map
5
+ }`})});if(!s.ok)throw new Error(`Failed to create thread: ${s.status}`);let l=await s.json(),u=l.data?.createThread?.thread?.id;if(!u)throw new Error("No thread ID returned");return {threadId:u,token:l.token}}async function Ge(e,o,r){let s=O(e);await fetch(`${s}/api/embed/update`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o.token}`},body:JSON.stringify({user_data:r})});}async function Se(e,o,r){let l=`${O(e)}/api/embed/upload-attachment`,u=new FormData;u.append("file",r);let d=await fetch(l,{method:"POST",headers:{Authorization:`Bearer ${o.token}`,"x-mii-user-id":B()},body:u});if(!d.ok){let A=await d.text();throw new Error(`Upload failed: ${d.status} - ${A}`)}let g=(await d.json()).attachment?.id;if(!g)throw new Error("No attachment ID returned");return g}async function Te(e,o,r){let s=O(e),l=await fetch(`${s}/api/embed/system-event`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o.token}`,"x-mii-user-id":B()},body:JSON.stringify({thread_id:o.config.thread_id,system_event:{action:r.action,description:r.description,followUpInstruction:r.followUpInstruction,metadata:r.metadata||{}}})});if(!l.ok){let d=await l.text();throw new Error(`Failed to send system event: ${l.status} - ${d}`)}let u=await l.json();if(!u.success)throw new Error(u.error||"Failed to send system event")}async function Ce(e,o,r){let s=O(e),l=await fetch(`${s}/api/embed/page-context`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o.token}`,"x-mii-user-id":B()},body:JSON.stringify({thread_id:o.config.thread_id,page_context:{action:r.action,content:r.content,metadata:r.metadata||{}}})});if(!l.ok){let d=await l.text();throw new Error(`Failed to send page context: ${l.status} - ${d}`)}let u=await l.json();if(!u.success)throw new Error(u.error||"Failed to send page context")}async function ee(e,o,r){let s=O(e),l=await fetch(`${s}/api/embed/tool-result`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o.token}`},body:JSON.stringify(r)});if(!l.ok){let d=await l.text();throw new Error(`Failed to send tool result: ${l.status} - ${d}`)}let u=await l.json();if(!u.success)throw new Error(`Failed to send tool result: ${u.error}`)}async function te(e,o,r){let s=O(e);if(r.length===1){let l=await fetch(`${s}/api/embed/register-tool`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o.token}`},body:JSON.stringify(r[0])});if(!l.ok){let d=await l.text();throw new Error(`Failed to register tool: ${l.status} - ${d}`)}let u=await l.json();if(!u.success)throw new Error(`Failed to register tool: ${u.error||"Unknown error"}`)}else if(r.length>1){let l=await fetch(`${s}/api/embed/register-tools`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o.token}`},body:JSON.stringify(r)});if(!l.ok){let d=await l.text();throw new Error(`Failed to register tools: ${l.status} - ${d}`)}let u=await l.json();if(!u.success)throw new Error(`Failed to register tools: ${u.error||"Unknown error"}`)}}var De=new Set(["string","number","integer","boolean","array","object","null"]),Ye=/^[a-zA-Z_][a-zA-Z0-9_]*$/,_=class extends Error{constructor(o){super(o),this.name="ToolValidationError";}};function se(e){if(!e.name)throw new _("Tool name is required");if(!e.description)throw new _("Tool description is required");if(!e.parameters)throw new _("Tool parameters schema is required");if(typeof e.handler!="function")throw new _("Tool handler must be a function");Ve(e.name),Ke(e.description),Ze(e.parameters);}function Ve(e){if(typeof e!="string")throw new _("Tool name must be a string");if(e.length===0)throw new _("Tool name cannot be empty");if(e.length>64)throw new _("Tool name too long (max 64 characters)");if(!Ye.test(e))throw new _("Tool name must start with letter/underscore and contain only alphanumeric characters and underscores")}function Ke(e){if(typeof e!="string")throw new _("Tool description must be a string");if(e.trim().length===0)throw new _("Tool description cannot be empty");if(e.length>500)throw new _("Tool description too long (max 500 characters)")}function Ze(e){if(typeof e!="object"||e===null||Array.isArray(e))throw new _("Parameters must be a JSON Schema object");if(e.type!=="object")throw new _("Parameters schema must be of type 'object' (function parameters)");if(e.properties&&typeof e.properties=="object")for(let[o,r]of Object.entries(e.properties))me(o,r);if(e.required!==void 0){if(!Array.isArray(e.required))throw new _("'required' must be an array");for(let o of e.required)if(typeof o!="string")throw new _("'required' array must contain only strings")}if(e.additionalProperties!==void 0&&typeof e.additionalProperties!="boolean"&&(typeof e.additionalProperties!="object"||e.additionalProperties===null))throw new _("'additionalProperties' must be boolean or object")}function me(e,o){if(typeof o!="object"||o===null||Array.isArray(o))throw new _(`Property '${e}' schema must be an object`);if(o.type!==void 0){let r=Array.isArray(o.type)?o.type:[o.type];for(let s of r)if(!De.has(s))throw new _(`Invalid type '${s}' for property '${e}'. Valid types: ${Array.from(De).join(", ")}`)}if(o.enum!==void 0&&!Array.isArray(o.enum))throw new _(`Property '${e}' enum must be an array`);if(o.properties&&typeof o.properties=="object")for(let[r,s]of Object.entries(o.properties))me(`${e}.${r}`,s);o.items&&(Array.isArray(o.items)?o.items.forEach((r,s)=>{me(`${e}[${s}]`,r);}):me(`${e}[]`,o.items));}function ae(e){return {name:e.name,description:e.description,parameters:e.parameters}}var Qe=new Set(["image/jpeg","image/jpg","image/png","image/webp","image/bmp"]);function et(e){return Qe.has(e.type)}function tt(e){return new Promise((o,r)=>{let s=URL.createObjectURL(e),l=new Image;l.onload=()=>{URL.revokeObjectURL(s),o(l);},l.onerror=()=>{URL.revokeObjectURL(s),r(new Error("Failed to load image"));},l.src=s;})}function _e(e,o,r,s){return new Promise((l,u)=>{let d=Math.round(e.naturalWidth*o),y=Math.round(e.naturalHeight*o),g=document.createElement("canvas");g.width=d,g.height=y;let A=g.getContext("2d");if(!A){u(new Error("Canvas 2D context unavailable"));return}A.drawImage(e,0,0,d,y),g.toBlob(U=>{U?l(U):u(new Error("Canvas toBlob returned null"));},s,r);})}async function Pe(e){if(!et(e)||e.size<=4194304)return e;let o=await tt(e),r=Math.min(1,4096/Math.max(o.naturalWidth,o.naturalHeight)),s="image/jpeg",l=[.85,.7,.5,.3,.15],u=[r,r*.75,r*.5,r*.25];for(let y of l){let g=await _e(o,r,y,s);if(g.size<=4194304)return ke(g,e.name,s)}for(let y of u.slice(1))for(let g of l){let A=await _e(o,y,g,s);if(A.size<=4194304)return ke(A,e.name,s)}let d=await _e(o,.1,.1,s);return ke(d,e.name,s)}function ke(e,o,r){let s=o.replace(/\.[^.]+$/,".jpg");return new File([e],s,{type:r,lastModified:Date.now()})}var nt=21e3,Ee=1e3,Ne=3e4,ot=3,rt="miiflow.v1";function it(e,o){if(e.webSocketUrl){let d=new URL(e.webSocketUrl);return d.pathname=`/ws/assistant/thread/${o.config.thread_id}/`,d.searchParams.set("role","user"),d.searchParams.set("user_id",B()),d.toString()}let l=O(e).replace(/\/api$/,"").replace(/^https:/,"wss:").replace(/^http:/,"ws:"),u=B();return `${l}/ws/assistant/thread/${o.config.thread_id}/?role=user&user_id=${encodeURIComponent(u)}`}function st(e){return [rt,`embed-token.${e.token}`]}function Be(e){return e?{customName:e.custom_name,messageFontSize:e.message_font_size,welcomeMessage:e.welcome_message,chatboxPlaceholder:e.chatbox_placeholder,backgroundBubbleColor:e.background_bubble_color,headerBackgroundColor:e.header_background_color,showHeader:e.show_header,rotatingPlaceholders:e.rotating_placeholders,presetQuestions:e.preset_questions,chatbotLogo:e.chatbot_logo,assistantAvatar:e.assistant_avatar}:null}function at(e){return Be(e?.config.branding)}async function lt(e,o,r,s){let l=new TextDecoder,u=Date.now(),d="",y=null,g=[],A,U,ne,j=[],h=false,S="answer",x="",z,$,I,Z,Q,L,X,oe="",G=o.config.branding,W=()=>{(x||S==="tool")&&(g.push({type:S,content:x,toolName:z,toolDescription:$,success:I,status:Z,subtaskId:Q,toolArgs:L,progress:X}),x="",z=void 0,$=void 0,I=void 0,Z=void 0,Q=void 0,L=void 0,X=void 0);},he=()=>{let F=g.map(Y=>Y);return (x||S==="tool")&&F.push({type:S,content:x,toolName:z,toolDescription:$,success:I,status:Z,subtaskId:Q,toolArgs:L,progress:X}),F},M=()=>{let F=he();if(y)s.onMessageUpdate({id:y,textContent:d,reasoning:F,suggestedActions:A,medias:j.length>0?j:void 0});else {y=`assistant-${Date.now()}`;let Y={id:y,textContent:d,participant:{id:"assistant",name:G?.custom_name||o.config.assistant_name,role:"assistant",avatarUrl:G?.assistant_avatar},createdAt:new Date().toISOString(),isStreaming:true,reasoning:F,suggestedActions:A,medias:j.length>0?j:void 0};s.onMessageCreate(Y);}};for(;;){let{done:F,value:Y}=await e.read();if(F)break;let le=l.decode(Y,{stream:true}),ce=(oe+le).split(`
6
+ `);le.endsWith(`
7
+ `)?oe="":oe=ce.pop()||"";for(let de of ce){if(!de.startsWith("data: "))continue;let ue=de.slice(6);if(ue==="[DONE]")break;try{let n=JSON.parse(ue);if(n.type==="assistant_chunk"){if(n.is_tool_planned){(x||S!=="answer")&&(W(),S="answer"),d="",g.push({type:"tool",content:"",toolName:n.tool_name,toolDescription:n.tool_description,status:"planned",subtaskId:n.subtask_id}),M();continue}if(n.is_tool_executing){for(let t=g.length-1;t>=0;t--){let i=g[t];if(i.type==="tool"&&i.toolName===n.tool_name&&(n.subtask_id===void 0||i.subtaskId===n.subtask_id)){g[t].status="executing";break}}M();continue}if(n.is_observation){for(let t=g.length-1;t>=0;t--){let i=g[t];if(i.type==="tool"&&i.toolName===n.tool_name&&(n.subtask_id===void 0||i.subtaskId===n.subtask_id)){g[t].status="completed";break}}M();continue}if(n.suggested_actions){A=n.suggested_actions.map(t=>({id:t.action,label:t.label,value:t.action})),M();continue}n.tool_args&&(L=n.tool_args),n.progress&&(X=n.progress);let f="answer";if(n.is_thinking?f="thinking":n.is_planning?f="planning":n.is_progress_update&&(f="progress"),f!==S&&(W(),S=f),n.tool_name&&(z=n.tool_name),n.success!==void 0&&(I=n.success),n.subtask_id!==void 0&&(Q=n.subtask_id),f==="thinking"){x+=n.chunk||"";let t=x.match(/"thought"\s*:\s*"((?:[^"\\]|\\.)*)"/);t&&(x=t[1].replace(/\\n/g,`
8
+ `).replace(/\\"/g,'"').replace(/\\t/g," ").replace(/\\\\/g,"\\"));}else if(f==="answer"){let t=n.chunk?.trim()||"",i=d.trim();t&&i&&t===i||(d+=n.chunk||"");}else x+=n.chunk||"";n.previous_message_id&&s.onUserMessageIdUpdate(r,n.previous_message_id),M(),M();}else if(n.type==="subagent_dispatch"){let f=n.sub_event||"",t=Array.isArray(n.subagent_path)&&n.subagent_path.length>0?n.subagent_path:[n.subagent_id||""],i=g,p,w=!1;for(let m=0;m<t.length;m++){let a=t[m],c=i.findIndex(b=>b.type==="subagent"&&b.subagentData?.subagentId===a);if(m===t.length-1)if(c>=0)p=i[c];else if(f==="start"){let b={type:"subagent",content:"",subagentData:{subagentId:a,subagentType:n.handle||"",status:"running",result:"",nestedChunks:[]}};i.push(b),p=b;}else w=!0;else {if(c<0){w=!0;break}let b=i[c].subagentData;if(!b){w=!0;break}i=b.nestedChunks;}}if(!w&&p?.subagentData){let m=p.subagentData;if(f==="progress"){let a=n.chunk||"";m.result=(m.result||"")+a;}else if(f==="complete")m.status="completed",n.result&&(m.result=n.result),n.duration_ms!=null&&(m.durationMs=n.duration_ms);else if(f==="failed")m.status="failed",n.error?m.result=(m.result||"")+`
9
+
10
+ Error: ${n.error}`:n.result&&(m.result=n.result),n.duration_ms!=null&&(m.durationMs=n.duration_ms);else if(f==="thinking"){let a=n.chunk||"";if(a){let c=m.nestedChunks,b=c[c.length-1];b&&b.type==="thinking"?b.content=(b.content||"")+a:c.push({type:"thinking",content:a});}}else if(f==="tool"){let a=n.tool_name||"",c=n.tool_description,b=n.status||"planned",T=m.nestedChunks,C=-1;for(let N=T.length-1;N>=0;N--)if(T[N].type==="tool"&&T[N].toolName===a){C=N;break}C>=0?T[C]={...T[C],status:b,toolDescription:c||T[C].toolDescription}:T.push({type:"tool",content:"",toolName:a,toolDescription:c,status:b});}else if(f==="observation"){let a=n.tool_name||"",c=n.success!==!1,b=n.chunk||"",T=m.nestedChunks;for(let C=T.length-1;C>=0;C--)if(T[C].type==="tool"&&T[C].toolName===a){T[C]={...T[C],status:"completed",success:c};break}T.push({type:"observation",content:b,toolName:a,success:c});}}M();}else if(n.type==="clarification_needed"){W();let f={questions:n.questions||[],context:n.context,subtaskId:n.subtask_id,subtaskDescription:n.subtask_description,subagentName:n.subagent_name,subagentRole:n.subagent_role,toolCallId:n.tool_call_id,interruptId:n.interrupt_id,question:n.question||void 0,options:n.options||void 0},t=f.context||f.questions?.[0]?.question||f.question||"";g.push({type:"clarification_needed",content:t,clarificationData:f,subtaskId:n.subtask_id}),U=f,d||(d=t),M();}else if(n.type==="tool_approval_needed"){W();let f={toolName:n.tool_name||"",toolDescription:n.tool_description||"",toolInputs:n.tool_inputs||{},toolSchema:n.tool_schema,toolCallId:n.tool_call_id,interruptId:n.interrupt_id,toolLabel:n.tool_label,preview:n.tool_preview};g.push({type:"tool_approval_needed",content:f.toolDescription,toolApprovalData:f}),ne=f,M();}else if(n.type==="media"){let f=n.media_data;f&&(j=[...j,{id:f.id,url:f.url,mediaType:f.media_type||"image",altText:f.alt_text}],M());}else if(n.type==="assistant_complete"){W(),h=!0;let f=n.message?.text_content||d,t=n.message?.id,i=n.message?.metadata?.sources,p=(Date.now()-u)/1e3;s.onComplete(y,f,t,g,A,i,U,p,ne),d=f,t&&(y=t);break}else if(n.type==="client_tool_invocation"&&n.invocation&&s.onToolInvocation)s.onToolInvocation(n.invocation);else {if(n.type==="error")throw new Error(n.error||"Stream error");if(n.type==="done"){if(y&&!h){W();let f=(Date.now()-u)/1e3;s.onComplete(y,d||"",n.message_id,g,A,void 0,U,f,ne);}else n.message_id&&y&&s.onMessageUpdate({id:y,isStreaming:!1});n.message_id&&(y=n.message_id);break}}}catch(n){if(n instanceof Error&&n.message!=="Stream error"&&(n.message.startsWith("Stream error")||n.message.startsWith("HTTP error")))throw n}}}return {assistantMsgId:y,assistantContent:d}}function ct(e){let[o,r]=useState([]),[s,l]=useState(false),[u,d]=useState(null),[y,g]=useState(null),[A,U]=useState(true),[ne,j]=useState(null),h=useRef(e);h.current=e;let S=useRef(y);S.current=y;let x=useRef(s);x.current=s;let z=useRef(null),$=useRef(new Map),I=useRef(new Map),[Z,Q]=useState(null),L=useRef(null);useEffect(()=>{let t=false,i=Me(h.current);i?.config.branding&&Q(i.config.branding);let w=(h.current.tools??[]).map(a=>{se(a),$.current.set(a.name,a.handler);let c=ae(a);return I.current.set(a.name,c),c});async function m(){try{let a=i?.token,c;try{c=await ie(h.current,{token:a,tools:w});}catch(b){if(a)Ie(h.current),c=await ie(h.current,{tools:w});else throw b}if(t||(Ae(h.current,c),g(c),U(!1)),w.length>0){let b=new Set(c.registeredTools??[]),T=w.filter(C=>!b.has(C.name));T.length>0&&te(h.current,c,T).catch(C=>{console.warn("[Miiflow] Fallback tool registration failed:",C);});}return c}catch(a){return t||(j(a instanceof Error?a.message:"Failed to initialize"),U(false)),null}}return L.current=m(),()=>{t=true;}},[e.publicKey,e.assistantId]);let X=useMemo(()=>at(y)??e.initialBranding??Be(Z),[y,e.initialBranding,Z]),oe=b(X),G=useRef(new Map),W=useCallback(async t=>{let i=S.current;if(!i)throw new Error("Not initialized");if(t.type.startsWith("image/"))try{t=await Pe(t);}catch(w){console.warn("Image compression failed, using original:",w);}let p=await Se(h.current,i,t);return G.current.set(p,{id:p,filename:t.name,mimeType:t.type,size:t.size,isImage:t.type.startsWith("image/"),isVideo:t.type.startsWith("video/"),isDocument:!t.type.startsWith("image/")&&!t.type.startsWith("video/")}),p},[]),he=useCallback(t=>{G.current.delete(t);},[]),M=useCallback(async t=>{let i=S.current;if(!i)throw new Error("Not initialized");let{invocation_id:p,tool_name:w,parameters:m}=t;console.log(`[Miiflow] Tool invocation received: "${w}" (id: ${p})`);let a=$.current.get(w);if(!a)return false;try{let c=await Promise.race([a(m),new Promise((b,T)=>setTimeout(()=>T(new Error("Tool execution timeout (30s)")),3e4))]);return console.log(`[Miiflow] Tool "${w}" executed successfully (id: ${p})`),await ee(h.current,i,{invocation_id:p,result:c}),console.log(`[Miiflow] Tool result sent for "${w}" (id: ${p})`),!0}catch(c){return console.error(`[Miiflow] Tool '${w}' execution failed:`,c),await ee(h.current,i,{invocation_id:p,error:c instanceof Error?c.message:String(c)}),true}},[]);useEffect(()=>{if(!y)return;let t=null,i=null,p=null,w=0,m=0,a=false;function c(){if(a)return;let b=S.current;if(!b)return;let T=it(h.current,b),C=st(b);t=new WebSocket(T,C);let N=false;t.onopen=()=>{console.log("[Miiflow] WebSocket connected"),N=true,w=0,m=0,i=setInterval(()=>{t?.readyState===WebSocket.OPEN&&t.send(JSON.stringify({type:"heartbeat"}));},nt);},t.onmessage=v=>{try{let E=JSON.parse(v.data);E.type==="client_tool_invocation"&&E.invocation&&M(E.invocation).then(async H=>{if(!H){let V=h.current.onToolInvocationFallback;if(!(V?await V(E.invocation):!1)){let k=S.current;k&&ee(h.current,k,{invocation_id:E.invocation.invocation_id,error:`No handler found for tool '${E.invocation.tool_name}'`}).catch(console.error);}}}).catch(console.error);}catch{}},t.onclose=()=>{if(i&&(clearInterval(i),i=null),a)return;if(!N){if(m>=ot){console.error("[Miiflow] WebSocket giving up after repeated handshake failures");return}m++,ie(h.current).then(E=>{a||(S.current=E,g(E),p=setTimeout(c,Ee));}).catch(E=>{if(a)return;console.error("[Miiflow] Session refresh failed",E);let H=Math.min(Ee*Math.pow(2,m),Ne);p=setTimeout(c,H);});return}let v=Math.min(Ee*Math.pow(2,w),Ne);w++,p=setTimeout(c,v);},t.onerror=()=>{};}return c(),()=>{a=true,i&&clearInterval(i),p&&clearTimeout(p),t&&(t.onclose=null,t.close());}},[y,M]);let F=useCallback(async t=>{let i=S.current;if(!i)throw new Error("Not initialized");await Te(h.current,i,t);},[]),Y=useCallback(async t=>{let i=S.current;if(!i)throw new Error("Not initialized");await Ce(h.current,i,t);},[]),le=useCallback(async(t,i,p)=>{let w=!!t.trim(),m=i&&i.length>0;if(!w&&!m||x.current)return;let a=S.current;if(!a&&L.current&&(a=await L.current),!a)return;x.current=true;let c=`msg-${Date.now()}`,b=!!p?.is_clarification_response,T=i?.map(v=>G.current.get(v)).filter(Boolean);i?.forEach(v=>G.current.delete(v));let C=`assistant-pending-${Date.now()}`,N={id:C,textContent:"",participant:{id:"assistant",name:a.config.branding?.custom_name||a.config.assistant_name,role:"assistant",avatarUrl:a.config.branding?.assistant_avatar},createdAt:new Date().toISOString(),isStreaming:true};if(b)r(v=>[...v,N]);else {let v={id:c,textContent:t,participant:{id:"user",name:h.current.userName||"You",role:"user"},createdAt:new Date().toISOString(),attachments:T?.length?T:void 0};r(E=>[...E,v,N]),h.current.onUserMessageCreated?.({id:c,content:t});}l(true),d(C);try{let v=O(h.current),E=new AbortController;z.current=E;let H=await fetch(`${v}/assistant/message/stream/`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a.token}`,"x-mii-user-id":B()},body:JSON.stringify({thread_id:a.config.thread_id,text_content:t,message_id:c,metadata:p||{},attachment_ids:i||[]}),signal:E.signal});if(!H.ok)throw new Error(`HTTP error: ${H.status}`);let V=H.body?.getReader();if(!V)throw new Error("No response body");let re=await lt(V,a,c,{onMessageCreate:k=>{d(k.id),r(D=>[...D.filter(q=>q.id!==C),k]);},onMessageUpdate:k=>{r(D=>D.map(P=>P.id===k.id?{...P,...k}:P));},onUserMessageIdUpdate:(k,D)=>{r(P=>P.map(q=>q.id===k?{...q,id:D}:q));},onComplete:(k,D,P,q,fe,Re,Ue,je,ze)=>{k&&r(Fe=>Fe.map(pe=>pe.id===k?{...pe,id:P||pe.id,textContent:D,isStreaming:!1,reasoning:q,suggestedActions:fe,citations:Re,pendingClarification:Ue,pendingToolApproval:ze,executionTime:je}:pe)),h.current.onAssistantMessageComplete?.({id:P||k||"",content:D});},onToolInvocation:async k=>{if(!await M(k)){let P=h.current.onToolInvocationFallback;if(!(P?await P(k):!1)){let fe=S.current;fe&&await ee(h.current,fe,{invocation_id:k.invocation_id,error:`No handler found for tool '${k.tool_name}'`});}}}});re.assistantMsgId&&r(k=>k.map(D=>D.id===re.assistantMsgId?{...D,isStreaming:!1}:D));}catch(v){if(v instanceof DOMException&&v.name==="AbortError")return;console.error("[Miiflow] Send error:",v);let E=S.current,H={id:`error-${Date.now()}`,textContent:"Sorry, I encountered an error. Please try again.",participant:{id:"assistant",name:E?.config.branding?.custom_name||E?.config.assistant_name||"Assistant",role:"assistant",avatarUrl:E?.config.branding?.assistant_avatar},createdAt:new Date().toISOString()};r(V=>[...V.filter(re=>re.id!==C),H]),j(v instanceof Error?v.message:"Send failed");}finally{z.current=null,l(false),d(null);}},[M]),ve=useCallback(()=>{x.current&&(z.current?.abort(),z.current=null,r(t=>t.map(i=>i.isStreaming?{...i,isStreaming:false}:i)),x.current=false,l(false),d(null));},[]),ce=useCallback(async()=>{let t=S.current;if(!t)throw new Error("Not initialized");let i=await ye(h.current,t);i.token||console.warn("[Miiflow] CreateThread did not return new token \u2014 tools may register to wrong thread");let p={...t,config:{...t.config,thread_id:i.threadId},token:i.token||t.token};if(S.current=p,g(p),r([]),I.current.size>0){console.log(`[Miiflow] Re-registering ${I.current.size} tools on new thread`);try{await te(h.current,p,Array.from(I.current.values()));}catch(w){console.warn("[Miiflow] Failed to re-register tools:",w);}}return i.threadId},[]),de=useCallback(async t=>{let i=S.current;if(!i)throw new Error("Not initialized");se(t),$.current.set(t.name,t.handler);let p=ae(t);I.current.set(t.name,p);try{await te(h.current,i,[p]),console.log(`[Miiflow] Tool registered: "${t.name}"`);}catch(w){throw $.current.delete(t.name),I.current.delete(t.name),w}},[]),ue=useCallback(async t=>{let i=S.current;if(!i)throw new Error("Not initialized");for(let a of t)se(a);let p=new Map($.current),w=new Map(I.current),m=[];for(let a of t){$.current.set(a.name,a.handler);let c=ae(a);I.current.set(a.name,c),m.push(c);}try{await te(h.current,i,m);let a=t.map(c=>c.name);console.log(`[Miiflow] Tools registered: ${JSON.stringify(a)} (${t.length} tools)`);}catch(a){throw $.current=p,I.current=w,a}},[]),n=useMemo(()=>o.filter(t=>t.participant.role!=="system").map(t=>({id:t.id,textContent:t.textContent?.replace(/\[ref:[^\]]+\]/g,"")||t.textContent,participant:t.participant,createdAt:t.createdAt,isStreaming:t.isStreaming,reasoning:t.reasoning,suggestedActions:t.suggestedActions,citations:t.citations,attachments:t.attachments,pendingClarification:t.pendingClarification,pendingToolApproval:t.pendingToolApproval,executionTime:t.executionTime})),[o]),f=useCallback(t=>{g(t);},[]);return {messages:n,isStreaming:s,streamingMessageId:u,sendMessage:le,uploadFile:W,removeUploadedAttachment:he,session:y,loading:A,error:ne,branding:X,brandingCSSVars:oe,startNewThread:ce,registerTool:de,registerTools:ue,sendSystemEvent:F,sendPageContext:Y,handleToolInvocation:M,updateSession:f,stopStreaming:ve}}export{_ as ToolValidationError,ye as createThread,O as getBackendBaseUrl,B as getOrCreateUserId,qe as getTimeUntilExpiry,ie as initSession,We as isTokenExpired,we as isTokenExpiringSoon,ge as parseTokenExpiry,te as registerToolsOnBackend,Ce as sendPageContext,Te as sendSystemEvent,ee as sendToolResult,ae as serializeToolDefinition,Ge as updateUser,Se as uploadFile,ct as useMiiflowChat,se as validateToolDefinition};//# sourceMappingURL=index.js.map
9
11
  //# sourceMappingURL=index.js.map