@polderlabs/bizar 5.2.0 → 5.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bizar-dash/dist/assets/{MobileChat-TCputYzr.js → MobileChat-OidrxXR9.js} +1 -1
- package/bizar-dash/dist/assets/{MobileChat-TCputYzr.js.map → MobileChat-OidrxXR9.js.map} +1 -1
- package/bizar-dash/dist/assets/{MobileSettings-BxcbL5XT.js → MobileSettings-B91gVFii.js} +1 -1
- package/bizar-dash/dist/assets/{MobileSettings-BxcbL5XT.js.map → MobileSettings-B91gVFii.js.map} +1 -1
- package/bizar-dash/dist/assets/{icons-DRDXfbBP.js → icons-Bd8piSb2.js} +18 -13
- package/bizar-dash/dist/assets/icons-Bd8piSb2.js.map +1 -0
- package/bizar-dash/dist/assets/{main-xFpWMd32.css → main-3G6mOhiK.css} +1 -1
- package/bizar-dash/dist/assets/main-6YUZY968.js +19 -0
- package/bizar-dash/dist/assets/main-6YUZY968.js.map +1 -0
- package/bizar-dash/dist/assets/{mobile-j3rOZK6v.js → mobile-CSsp30lr.js} +2 -2
- package/bizar-dash/dist/assets/{mobile-j3rOZK6v.js.map → mobile-CSsp30lr.js.map} +1 -1
- package/bizar-dash/dist/assets/{mobile--17fkfrl.js → mobile-DtwK7DOV.js} +1 -1
- package/bizar-dash/dist/assets/{mobile--17fkfrl.js.map → mobile-DtwK7DOV.js.map} +1 -1
- package/bizar-dash/dist/assets/{useSlashCommands-BG-DhEck.js → useSlashCommands-DEkxEvOO.js} +2 -2
- package/bizar-dash/dist/assets/{useSlashCommands-BG-DhEck.js.map → useSlashCommands-DEkxEvOO.js.map} +1 -1
- package/bizar-dash/dist/index.html +5 -5
- package/bizar-dash/dist/mobile.html +3 -3
- package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/bizar-dash/src/server/auth.mjs +14 -1
- package/bizar-dash/src/server/eval-store.mjs +55 -0
- package/bizar-dash/src/server/eval.mjs +63 -0
- package/bizar-dash/src/server/plugins/permission-audit.mjs +109 -0
- package/bizar-dash/src/server/plugins/sandbox.mjs +76 -2
- package/bizar-dash/src/server/plugins/store.mjs +4 -0
- package/bizar-dash/src/server/routes/eval.mjs +42 -2
- package/bizar-dash/src/server/routes/plugins.mjs +44 -4
- package/bizar-dash/src/server/routes/users.mjs +18 -0
- package/bizar-dash/src/server/schedules-runner.mjs +61 -0
- package/bizar-dash/src/web/components/EvalExportButton.tsx +27 -0
- package/bizar-dash/src/web/components/InstallConfirmDialog.tsx +62 -0
- package/bizar-dash/src/web/components/MarketplacePluginCard.tsx +51 -0
- package/bizar-dash/src/web/components/PluginCard.tsx +2 -2
- package/bizar-dash/src/web/components/PluginPermissions.tsx +1 -1
- package/bizar-dash/src/web/components/ScheduleTemplateCard.tsx +1 -0
- package/bizar-dash/src/web/components/Topbar.tsx +3 -0
- package/bizar-dash/src/web/components/VoiceNotesPanel.tsx +28 -0
- package/bizar-dash/src/web/styles/main.css +139 -0
- package/bizar-dash/src/web/views/Doctor.tsx +3 -3
- package/bizar-dash/src/web/views/Eval.tsx +225 -25
- package/bizar-dash/src/web/views/EvalReport.tsx +7 -3
- package/bizar-dash/src/web/views/Marketplace.tsx +135 -0
- package/bizar-dash/src/web/views/Plugins.tsx +9 -3
- package/bizar-dash/src/web/views/Schedules.tsx +1 -1
- package/bizar-dash/tests/a11y/components.test.tsx +149 -0
- package/bizar-dash/tests/a11y/forms.test.tsx +191 -0
- package/bizar-dash/tests/a11y/navigation.test.tsx +112 -0
- package/bizar-dash/tests/components/marketplace-plugin-card.test.tsx +144 -0
- package/bizar-dash/tests/eval-csv.test.mjs +67 -0
- package/bizar-dash/tests/eval-scheduled.test.mjs +84 -0
- package/bizar-dash/tests/plugins-permissions.test.mjs +525 -0
- package/cli/commands/dash.mjs +5 -0
- package/cli/commands/tailscale.mjs +8 -1
- package/package.json +1 -1
- package/bizar-dash/dist/assets/icons-DRDXfbBP.js.map +0 -1
- package/bizar-dash/dist/assets/main-D5Ditnrd.js +0 -19
- package/bizar-dash/dist/assets/main-D5Ditnrd.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{M as r}from"./mobile-
|
|
1
|
+
import{M as r}from"./mobile-CSsp30lr.js";import{b as e,j as o,r as n}from"./react-vendor-Dn4wqh4Z.js";import"./icons-Bd8piSb2.js";const t=document.getElementById("root");if(!t)throw new Error("Root element #root not found");e(t).render(o.jsx(n.StrictMode,{children:o.jsx(r,{})}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mobile
|
|
1
|
+
{"version":3,"file":"mobile-DtwK7DOV.js","sources":["../../src/web/mobile.tsx"],"sourcesContent":["// src/mobile.tsx — entry point for mobile dashboard.\nimport { StrictMode } from 'react';\nimport { createRoot } from 'react-dom/client';\nimport { MobileApp } from './MobileApp';\nimport './styles/mobile.css';\n\nconst root = document.getElementById('root');\nif (!root) throw new Error('Root element #root not found');\ncreateRoot(root).render(\n <StrictMode>\n <MobileApp />\n </StrictMode>,\n);\n"],"names":["root","createRoot","jsx","StrictMode","MobileApp"],"mappings":"kIAMA,MAAMA,EAAO,SAAS,eAAe,MAAM,EAC3C,GAAI,CAACA,EAAM,MAAM,IAAI,MAAM,8BAA8B,EACzDC,EAAWD,CAAI,EAAE,OACfE,EAAAA,IAACC,EAAAA,WAAA,CACC,SAAAD,EAAAA,IAACE,EAAA,CAAA,CAAU,CAAA,CACb,CACF"}
|
package/bizar-dash/dist/assets/{useSlashCommands-BG-DhEck.js → useSlashCommands-DEkxEvOO.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/mobile-
|
|
2
|
-
import{r as t,j as e}from"./react-vendor-Dn4wqh4Z.js";import{D as Be,C as Ue,E as Pe,I as Fe,X as xe,b as We,d as je,bg as Ge,aR as Ye,bh as qe,bi as He,aF as Ke,R as Qe,bj as Ve,Y as Je,B as Xe,bk as be,i as Ze,Q as es}from"./icons-DRDXfbBP.js";import{b as ss,e as ts,a as M,A as le,_ as ns}from"./mobile-j3rOZK6v.js";import{M as as,r as rs}from"./markdown-C6mXtQxD.js";const we=t.createContext(null);function js(){const r=t.useContext(we);return r||{show:()=>{},info:()=>{},success:()=>{},error:()=>{},warning:()=>{},dismiss:()=>{},toasts:[]}}const os={info:Fe,success:Pe,error:Ue,warning:Be};function ws({children:r}){const[h,u]=t.useState([]),d=t.useRef(1),l=t.useRef(new Map),y=t.useCallback(m=>{u($=>$.filter(k=>k.id!==m));const x=l.current.get(m);x&&(clearTimeout(x),l.current.delete(m))},[]),g=t.useCallback((m,x="info",$=4e3)=>{const k=d.current++;if(u(I=>[...I,{id:k,kind:x,message:m}]),$>0){const I=setTimeout(()=>y(k),$);l.current.set(k,I)}},[y]);t.useEffect(()=>()=>{for(const m of l.current.values())clearTimeout(m);l.current.clear()},[]);const C=t.useMemo(()=>({show:g,info:(m,x)=>g(m,"info",x),success:(m,x)=>g(m,"success",x),error:(m,x)=>g(m,"error",x),warning:(m,x)=>g(m,"warning",x),dismiss:y,toasts:h}),[g,y,h]);return e.jsxs(we.Provider,{value:C,children:[r,e.jsx(cs,{toasts:h,onDismiss:y})]})}function cs({toasts:r,onDismiss:h}){return e.jsx("div",{className:"toast-stack","aria-live":"polite",children:r.map(u=>e.jsx(is,{toast:u,onDismiss:h},u.id))})}function is({toast:r,onDismiss:h}){const u=os[r.kind];return e.jsxs("div",{className:`toast toast-${r.kind}`,role:"alert","aria-live":"assertive","aria-atomic":"true",children:[e.jsx(u,{size:16,className:"toast-icon"}),e.jsx("span",{className:"toast-message",children:r.message}),e.jsx("button",{type:"button",className:"toast-close","aria-label":"Dismiss",onClick:()=>h(r.id),children:e.jsx(xe,{size:14})})]})}function ls({items:r,renderItem:h,itemHeight:u=80,height:d=400,overscan:l=5,className:y}){const[g,C]=t.useState(0),m=t.useRef(null),x=t.useMemo(()=>{const N=Math.max(0,Math.floor(g/u)-l),R=Math.min(r.length,Math.ceil((g+d)/u)+l);return{start:N,end:R}},[g,u,d,l,r.length]),$=r.length*u,k=x.start*u,I=r.slice(x.start,x.end);return e.jsx("div",{ref:m,onScroll:N=>C(N.currentTarget.scrollTop),style:{height:d,overflowY:"auto"},className:y,children:e.jsx("div",{style:{height:$,position:"relative"},children:e.jsx("div",{style:{transform:`translateY(${k}px)`},children:I.map((N,R)=>e.jsx("div",{style:{height:u},children:h(N,x.start+R)},x.start+R))})})})}function Cs({activeProject:r,sessionCount:h,sessionsOpen:u,infoOpen:d,onToggleSessions:l,onToggleInfo:y,onOpenOverview:g}){return e.jsxs("header",{className:"chat-topbar",children:[e.jsxs("button",{type:"button",className:"chat-topbar-project",onClick:g,children:[e.jsx(We,{size:14}),e.jsx("span",{className:"chat-topbar-project-name",children:(r==null?void 0:r.name)??"No project"}),e.jsx(je,{size:12})]}),e.jsx("div",{className:"chat-topbar-spacer"}),e.jsxs("button",{type:"button",className:`chat-topbar-btn ${u?"active":""}`,onClick:l,"aria-pressed":u,children:["Sessions (",h,")"]}),e.jsx("button",{type:"button",className:`chat-topbar-btn ${d?"active":""}`,onClick:y,"aria-pressed":d,children:"Info"})]})}function us({count:r=3}){return e.jsx("div",{className:"chat-loading-skeleton","aria-label":"Loading messages",children:Array.from({length:r}).map((h,u)=>e.jsxs("div",{className:"chat-loading-skeleton-bubble",children:[e.jsx("div",{className:"chat-loading-skeleton-meta"}),e.jsx("div",{className:"chat-loading-skeleton-line"}),e.jsx("div",{className:"chat-loading-skeleton-line short"})]},u))})}function ds({projectName:r,onPickSuggestion:h}){const u=[{icon:e.jsx(Ge,{size:16}),title:r?`Explain ${r}`:"Explain this project",preview:"Give me a tour of the codebase, highlight the architecture, and call out any anti-patterns or hotspots.",prompt:r?`Explain the ${r} project. Give me a tour of the codebase, highlight the architecture, and call out any anti-patterns or hotspots.`:"Explain the current project. Give me a tour of the codebase, highlight the architecture, and call out any anti-patterns or hotspots."},{icon:e.jsx(Ye,{size:16}),title:"Summarize recent sessions",preview:"Read my last 5 chat sessions and give me a 3-bullet summary of what I worked on and what got stuck.",prompt:"Read my last 5 chat sessions and give me a 3-bullet summary of what I worked on and what got stuck."},{icon:e.jsx(qe,{size:16}),title:"Suggest a refactor",preview:"Look for the largest, most painful files in this project and propose a concrete refactor for the worst one.",prompt:"Look for the largest, most painful files in this project and propose a concrete refactor for the worst one."},{icon:e.jsx(He,{size:16}),title:"Find visual regressions",preview:"Open the dashboard, screenshot the Chat tab, and flag any layout problems or anti-patterns you see.",prompt:"Open the dashboard, screenshot the Chat tab, and flag any layout problems or anti-patterns you see."}];return e.jsx("div",{className:"chat-suggestions",children:u.map((d,l)=>e.jsxs("button",{type:"button",className:"chat-suggestion",onClick:()=>h(d.prompt),children:[e.jsxs("div",{className:"chat-suggestion-title",children:[d.icon,e.jsx("span",{children:d.title})]}),e.jsx("div",{className:"chat-suggestion-preview",children:d.preview})]},l))})}function ye({variant:r,projectName:h,onPickSuggestion:u}){if(r==="no-project")return e.jsxs("div",{className:"chat-welcome",children:[e.jsx("h1",{className:"chat-welcome-h1",children:e.jsx("span",{className:"chat-greeting-hello",children:"No project selected."})}),e.jsx("p",{className:"chat-welcome-subtitle",children:"Pick a project in Overview to scope chat sessions."})]});const d=h||"there";return e.jsxs("div",{className:"chat-welcome",children:[e.jsxs("h1",{className:"chat-welcome-h1",children:[e.jsx("span",{className:"chat-greeting-hello",children:"Hello, "}),e.jsxs("span",{className:"chat-greeting-name",children:[d,"."]})]}),e.jsx("p",{className:"chat-welcome-subtitle",children:"How can I help you today?"}),e.jsx(ds,{projectName:h,onPickSuggestion:u})]})}function ms({message:r,pinned:h,onCopy:u,onDelete:d,onTogglePin:l,onRegenerate:y}){const g=(r.role||"assistant").toLowerCase(),C=r.ts?ss(r.ts):"",m=r.content||r.message||"",x=g==="user";return e.jsxs("article",{className:`chat-message ${x?"chat-message-user":"chat-message-assistant"} ${h?"chat-message-pinned":""}`,children:[e.jsxs("header",{className:"chat-message-meta",children:[e.jsx("span",{className:"chat-message-role",children:g}),r.agent&&e.jsxs("span",{className:"chat-message-agent",children:["@",r.agent]}),C&&e.jsx("time",{className:"chat-message-time",children:C}),h&&e.jsx("span",{className:"chat-message-pin",children:"pinned"}),e.jsxs("div",{className:"chat-message-actions",children:[e.jsx("button",{type:"button",className:"chat-msg-action-btn",onClick:u,title:"Copy","aria-label":"Copy",children:e.jsx(Ke,{size:12})}),!x&&e.jsx("button",{type:"button",className:"chat-msg-action-btn",onClick:y,title:"Regenerate","aria-label":"Regenerate",children:e.jsx(Qe,{size:12})}),e.jsx("button",{type:"button",className:"chat-msg-action-btn",onClick:l,title:"Pin","aria-label":"Pin",children:e.jsx(Ve,{size:12})}),e.jsx("button",{type:"button",className:"chat-msg-action-btn chat-msg-action-btn-danger",onClick:d,title:"Delete","aria-label":"Delete",children:e.jsx(Je,{size:12})})]})]}),e.jsx("div",{className:"chat-message-content markdown-body",children:e.jsx(as,{remarkPlugins:[rs],children:m})})]})}function ks({messages:r,loading:h,activeProject:u,sessionId:d,pinned:l,activeSource:y,onPickSuggestion:g,onCopy:C,onDelete:m,onTogglePin:x,onRegenerate:$}){const k=t.useRef(null);t.useEffect(()=>{const N=k.current;if(!N)return;let R=N.parentElement,P=!1;for(;R;){if(R.classList.contains("chat-thread-scroll")){P=!0;break}R=R.parentElement}P||(N.scrollTop=N.scrollHeight)},[r]);const I=y==="opencode"?"opencode":"bizar";return h?e.jsx("div",{className:"chat-thread legacy",ref:k,"data-stream":I,children:e.jsx(us,{count:3})}):u?r.length===0?e.jsx("div",{className:"chat-thread legacy",ref:k,"data-stream":I,children:e.jsx(ye,{variant:"empty",projectName:u.name,onPickSuggestion:g})}):e.jsx("div",{className:"chat-thread legacy",ref:k,children:e.jsx(ls,{items:r,itemHeight:120,height:800,className:"chat-thread-virtual",renderItem:(N,R)=>e.jsx(ms,{message:N,pinned:l.has(R),onCopy:()=>C(N),onDelete:()=>m(R),onTogglePin:()=>x(R),onRegenerate:()=>$(String(N.ts??R))})})}):e.jsx("div",{className:"chat-thread legacy",ref:k,"data-stream":I,children:e.jsx(ye,{variant:"no-project",projectName:"",onPickSuggestion:g})})}function ps({agent:r,setAgent:h,agents:u}){const[d,l]=t.useState(!1),y=t.useRef(null);t.useEffect(()=>{if(!d)return;const m=x=>{y.current&&!y.current.contains(x.target)&&l(!1)};return document.addEventListener("mousedown",m),()=>document.removeEventListener("mousedown",m)},[d]);const g=r||"no agent",C=g.startsWith("@")?g.slice(1):g;return e.jsxs("div",{className:"chat-agent-chip",ref:y,children:[e.jsxs("button",{type:"button",className:"chat-agent-chip-btn",onClick:()=>l(m=>!m),"aria-haspopup":"listbox","aria-expanded":d,children:[e.jsx(Xe,{size:14}),e.jsx("span",{children:C}),e.jsx(je,{size:12,className:d?"rotated":""})]}),d&&e.jsxs("div",{className:"chat-agent-chip-menu",role:"listbox",children:[e.jsx("button",{type:"button",role:"option","aria-selected":!r,onClick:()=>{h(""),l(!1)},children:e.jsx("span",{children:"no agent"})}),u.map(m=>e.jsx("button",{type:"button",role:"option","aria-selected":r===m.name,onClick:()=>{h(m.name),l(!1)},children:e.jsxs("span",{children:["@",m.name]})},m.name))]})]})}function hs(r,h,u=240){t.useLayoutEffect(()=>{const d=r.current;if(!d)return;d.style.height="auto";const l=Math.min(d.scrollHeight,u);d.style.height=`${l}px`,d.style.overflowY=d.scrollHeight>u?"auto":"hidden"},[r,h,u])}function Ss({agent:r,setAgent:h,model:u,setModel:d,text:l,setText:y,sending:g,onSend:C,attachments:m,setAttachments:x,suggestions:$,onPickSuggestion:k,agents:I,onAttach:N}){const R=t.useRef(null),P=t.useRef(null);hs(R,l,160);const F=j=>{if(j.key==="Enter"&&(j.metaKey||j.ctrlKey))j.preventDefault(),C();else if(j.key==="Enter"&&!j.shiftKey)j.preventDefault(),C();else if(j.key==="Tab"&&$.length){j.preventDefault();const E=$[0].cmd.split(" ")[0];y(`${E} `)}},W=j=>{const E=j.target.files;if(!E)return;const A=[];for(let G=0;G<E.length;G++)A.push(E[G].name);x(G=>[...G,...A]),j.target.value=""};return e.jsxs("div",{className:"chat-composer",children:[$.length>0&&e.jsx("div",{className:"chat-composer-suggestions",children:$.map(j=>e.jsxs("button",{type:"button",className:"chat-composer-suggestion",onClick:()=>{var A;const E=j.cmd.split(" ")[0];y(`${E} `),(A=R.current)==null||A.focus()},children:[e.jsx("span",{className:"mono",children:j.cmd}),e.jsx("span",{children:j.desc})]},j.cmd))}),m.length>0&&e.jsx("div",{className:"chat-composer-attachments",children:m.map((j,E)=>e.jsxs("span",{className:"chat-composer-attachment-tag",children:[e.jsx(be,{size:10})," ",j,e.jsx("button",{type:"button",className:"chat-composer-attachment-remove",onClick:()=>x(A=>A.filter((G,Y)=>Y!==E)),"aria-label":`Remove ${j}`,children:e.jsx(xe,{size:10})})]},E))}),e.jsxs("div",{className:"chat-composer-input",children:[e.jsx(ps,{agent:r,setAgent:h,agents:I}),e.jsx("textarea",{ref:R,className:"chat-composer-textarea",placeholder:g?"Sending…":"Send a message…",rows:1,value:l,onChange:j=>y(j.target.value),onKeyDown:F,disabled:g,"aria-label":"Message"}),e.jsx("input",{ref:P,type:"file",multiple:!0,style:{display:"none"},onChange:W,"aria-label":"Attach files",tabIndex:-1}),e.jsx("button",{type:"button",className:"chat-attach-btn",onClick:N,title:"Attach files","aria-label":"Attach files",children:e.jsx(be,{size:14})}),e.jsx("button",{type:"button",className:"chat-attach-btn",onClick:async()=>{if(!l.trim())return;const j=await ts(l);j!==l&&y(j)},title:"Enhance prompt with AI","aria-label":"Enhance prompt",children:e.jsx(Ze,{size:14})}),e.jsx("button",{type:"button",className:"chat-send-btn",onClick:C,disabled:g||!l.trim(),title:"Send (Enter)","aria-label":"Send message",children:e.jsx(es,{size:16})})]})]})}function vs(r,h,u){const[d,l]=t.useState([]),[y,g]=t.useState([]),[C,m]=t.useState(""),[x,$]=t.useState(!0),[k,I]=t.useState({create:!1,send:!1,rename:!1,delete:!1}),[N,R]=t.useState([]),[P,F]=t.useState([]),[W,j]=t.useState(null),[E,A]=t.useState(null),[G,Y]=t.useState(null),[Ce,Z]=t.useState(null),[ke,ee]=t.useState(null),[se,ue]=t.useState({}),[de,me]=t.useState(!0),[Se,ce]=t.useState(0),[ve,pe]=t.useState(new Set),[Ie,he]=t.useState(new Set),Q=t.useRef(null),D=t.useRef(null),O=t.useRef(null),ne=t.useRef(0),z=t.useRef(null),V=t.useRef(null),K=t.useRef(!1),J=t.useCallback(s=>{s&&F(a=>{if(s.id&&a.some(o=>o.id===s.id))return a;const n=a.findIndex(o=>typeof o.id=="string"&&o.id.startsWith("msg_")&&o.role===s.role&&(o.content||"")===(s.content||""));if(n>=0){const o=a.slice();return o[n]={...s,id:s.id??a[n].id},o}return[...a,s]})},[]),X=t.useCallback(s=>{s&&pe(a=>{if(a.has(s))return a;const n=new Set(a);return n.add(s),n})},[]),q=t.useCallback((s,a)=>{ue(n=>{const o=n[s]??{state:"idle",unread:0,pinned:!1};return{...n,[s]:{...o,...a}}})},[]),B=t.useCallback((s,a)=>{q(s,{state:a?"streaming":"idle"})},[q]),Ne=t.useCallback(s=>{D.current=s},[]),H=t.useCallback(async s=>{var a;try{const n=s?`/chat?session=${encodeURIComponent(s)}`:"/chat?limit=200",o=await M.get(n);l(o.messages||[]),g(o.sessions||[])}catch(n){(a=D.current)==null||a.error(`Chat load failed: ${n.message}`)}finally{$(!1)}},[]),ae=t.useCallback(async s=>{var a;$(!0);try{const n=await M.get(`/tasks/${encodeURIComponent(s)}/chat`);l(n.messages||[]),m(n.sessionId||s)}catch(n){(a=D.current)==null||a.error(`Task chat load failed: ${n.message}`)}finally{$(!1)}},[]),ie=t.useCallback(async()=>{try{const s=await M.get("/chat/sessions");g(s.sessions||[])}catch{}},[]),re=t.useCallback(async()=>{try{const a=((await M.get("/opencode-sessions")).sessions||[]).map(n=>({...n,source:"opencode",title:n.title||n.id}));R(a)}catch{}},[]),fe=t.useCallback(s=>{if(O.current){try{O.current.close()}catch{}O.current=null}z.current!==null&&(clearTimeout(z.current),z.current=null);const a=M.getToken(),n=a?`/api/opencode-sessions/${encodeURIComponent(s)}/stream?token=${encodeURIComponent(a)}`:`/api/opencode-sessions/${encodeURIComponent(s)}/stream`;V.current=s,K.current=!0,ne.current=0,Y(null),Z(null),ee(null);const o=()=>{if(!K.current||V.current!==s)return;const c=new EventSource(n);O.current=c;const b=i=>{var S,_,L,U;if(!i||!i.type||i.sessionID&&i.sessionID!==s)return;const f=new Date().toISOString(),w=s;if(i.type==="message.user.created"||i.type==="message.user.updated"){const p=i.data;J({id:(p==null?void 0:p.messageID)??i.messageID,role:"user",content:((S=p==null?void 0:p.data)==null?void 0:S.content)??"",ts:f}),X((p==null?void 0:p.messageID)??i.messageID);return}if(i.type==="message.assistant.created"||i.type==="message.assistant.updated"){const p=i.data;J({id:(p==null?void 0:p.messageID)??i.messageID,role:"assistant",content:((_=p==null?void 0:p.data)==null?void 0:_.content)??"",ts:f}),X((p==null?void 0:p.messageID)??i.messageID),B(w,!0);return}if(i.type==="message.part.updated"){const p=i.data,ge=((L=p==null?void 0:p.part)==null?void 0:L.text)??"";if(!ge)return;J({id:(p==null?void 0:p.id)??(p==null?void 0:p.messageID)??i.messageID,role:"assistant",content:ge,ts:f}),X((p==null?void 0:p.id)??(p==null?void 0:p.messageID)??i.messageID),B(w,!0);return}if(i.type==="session.idle"||i.type==="message.assistant.completed"||i.type==="session.completed"){B(w,!1);return}if(i.type==="session.awaiting"||i.type==="session.awaiting_input"||i.type==="message.assistant.awaiting"){q(w,{state:"awaiting"});return}if(i.type==="session.error"){Y(((U=i.data)==null?void 0:U.message)||"opencode session error");return}},v=i=>{if(!i)return null;try{const f=JSON.parse(i);if(typeof f.type=="string"){const w=f.properties,S=f.data??w,_=typeof f.sessionID=="string"?f.sessionID:typeof(w==null?void 0:w.sessionID)=="string"?w.sessionID:typeof(S==null?void 0:S.sessionID)=="string"?S.sessionID:void 0,L=typeof f.messageID=="string"?f.messageID:typeof(w==null?void 0:w.messageID)=="string"?w.messageID:typeof(S==null?void 0:S.messageID)=="string"?S.messageID:void 0;let U=f.type;const p=/\.\d+$/.exec(U);return p&&(U=U.slice(0,p.index)),{type:U,sessionID:_,messageID:L,data:f}}if(f.type==="sync"&&f.syncEvent&&typeof f.syncEvent=="object"){const w=f.syncEvent;let S=w.type||"";const _=/\.\d+$/.exec(S);_&&(S=S.slice(0,_.index));const L=w.data||{};return{type:S,sessionID:typeof L.sessionID=="string"?L.sessionID:void 0,messageID:typeof L.messageID=="string"?L.messageID:void 0,data:w}}return null}catch{return null}},T=["message.user.created","message.user.updated","message.assistant.created","message.assistant.updated","message.part.updated","session.idle","message.assistant.completed","session.completed","session.awaiting","session.awaiting_input","message.assistant.awaiting","session.error"];for(const i of T)c.addEventListener(i,f=>{b(v(f.data))});c.onerror=()=>{if(V.current!==s)return;if(!K.current){try{c.close()}catch{}O.current=null;return}try{c.close()}catch{}O.current=null;const i=ne.current+1;ne.current=i;const f=Math.min(3e4,1e3*2**(i-1));z.current!==null&&clearTimeout(z.current),z.current=window.setTimeout(()=>{z.current=null,K.current&&V.current===s&&o()},f)},c.onopen=()=>{ne.current=0,Y(null),Z(null),ee(null)}};o()},[J,X,B,q]),te=t.useCallback(()=>{if(K.current=!1,V.current=null,z.current!==null&&(clearTimeout(z.current),z.current=null),O.current){try{O.current.close()}catch{}O.current=null}F([]),pe(new Set),Y(null),Z(null),ee(null),A(null),j("bizar")},[]),oe=t.useCallback(async s=>{var a;if(K.current=!1,O.current){try{O.current.close()}catch{}O.current=null}z.current!==null&&(clearTimeout(z.current),z.current=null),Y(null),Z(null),ee(null),$(!0);try{const n=await M.get(`/opencode-sessions/${encodeURIComponent(s)}/messages`);F(n.messages||[])}catch(n){const o=n.message;let c=null;if(n instanceof le&&n.data&&typeof n.data=="object"){const b=n.data,v=b.error||"unknown",T=v!=="bad_request"&&v!=="too_many_subscribers"&&v!=="unauthorized";c={type:"session_load_failed",code:v,message:b.message||o,cause:b.cause,status:b.status,suggestion:b.suggestion??null,canRetry:T}}else n instanceof le&&(c={type:"session_load_failed",code:"unknown",message:o,suggestion:null,canRetry:!0});Y(c?`Opencode session load failed (${c.code}): ${c.message}`:`Opencode session load failed: ${o}`),Z((c==null?void 0:c.suggestion)??null),ee(c),(a=D.current)==null||a.error(c?`Opencode session load failed: ${c.message}`:`Opencode session load failed: ${o}`),F([])}finally{$(!1)}A(s),j("opencode"),B(s,!1),fe(s)},[B,fe]),Re=t.useCallback(s=>{te(),m(s),j("bizar"),H(s),q(s,{unread:0})},[te,H,q]),De=t.useCallback(async()=>{var a,n,o,c,b;if(k.create)return{ok:!1};const s=h.defaultAgent||"odin";I(v=>({...v,create:!0}));try{try{const T=await M.post("/opencode-sessions/new",{agent:s});return await re(),await oe(T.id),(a=D.current)==null||a.success(`Session ${T.id} created.`),{ok:!0,source:"opencode",id:T.id}}catch(T){if(!(T instanceof le)||T.status!==503)return(n=D.current)==null||n.error(`Create failed: ${T.message}`),{ok:!1}}if(!r.activeProject)return(o=D.current)==null||o.error("Pick a project in Overview to scope chat sessions."),{ok:!1};const v=await M.post("/chat/sessions",{});return m(v.id),l([]),he(new Set),q(v.id,{state:"idle",unread:0}),await H(v.id),ie().catch(()=>{}),(c=D.current)==null||c.success(`Session ${v.id} created.`),{ok:!0,source:"bizar",id:v.id}}catch(v){return(b=D.current)==null||b.error(`Create failed: ${v.message}`),{ok:!1}}finally{I(v=>({...v,create:!1}))}},[k.create,h.defaultAgent,r.activeProject,re,oe,H,ie,q]),Te=t.useCallback(async(s,a,n,o)=>{var v,T,i;if(k.send)return{ok:!1};const c=s.trim();if(!c)return{ok:!1};if(W==="opencode"&&E){const f=E,w=`msg_${Date.now().toString(36)}${Math.random().toString(36).slice(2,8)}`,S={id:w,role:"user",content:c,agent:a,ts:new Date().toISOString()};J(S),X(w),I(_=>({..._,send:!0}));try{return await M.post(`/opencode-sessions/${encodeURIComponent(f)}/send`,{message:c,agent:a}),B(f,!0),{ok:!0}}catch(_){return F(L=>L.filter(U=>U.id!==w)),(v=D.current)==null||v.error(`Send failed: ${_.message}`),{ok:!1}}finally{I(_=>({..._,send:!1}))}}const b={role:"user",content:c,agent:a,ts:new Date().toISOString()};l(f=>[...f,b]),I(f=>({...f,send:!0})),B(C,!0);try{const f=await M.post("/chat",{message:c,agent:a,model:n,attachments:o||[]});if(f!=null&&f.messages)for(const w of f.messages)w.role==="assistant"&&l(S=>S.some(L=>L.ts===w.ts)?S:[...S,w]);else(T=D.current)==null||T.info("Still processing… the response will appear shortly.");return{ok:!0}}catch(f){return l(w=>w.filter(S=>S!==b)),(i=D.current)==null||i.error(`Send failed: ${f.message}`),{ok:!1}}finally{I(f=>({...f,send:!1})),B(C,!1)}},[W,E,J,X,B,C,k.send]),$e=t.useCallback(async s=>{var a,n;if(!C){(a=D.current)==null||a.error("No active session to regenerate.");return}try{await M.post("/chat/regenerate",{sessionId:C,messageId:s}),await H(C)}catch(o){(n=D.current)==null||n.error(`Regenerate failed: ${o.message}`)}},[C,H]),Ee=t.useCallback(s=>{W==="opencode"?F(a=>a.filter((n,o)=>o!==s)):l(a=>a.filter((n,o)=>o!==s))},[W]),ze=t.useCallback(s=>{he(a=>{const n=new Set(a);return n.has(s)?n.delete(s):n.add(s),n})},[]),Oe=t.useCallback(s=>{var n,o;const a=s.content||s.message||"";try{(n=navigator.clipboard)==null||n.writeText(a).then(()=>{var c;return(c=D.current)==null?void 0:c.success("Copied.")},()=>{var c;return(c=D.current)==null?void 0:c.error("Copy failed.")})}catch{(o=D.current)==null||o.error("Copy failed.")}},[]),Me=t.useCallback(()=>{const s=Q.current;if(!s)return;const n=s.scrollHeight-s.scrollTop-s.clientHeight<32;me(n),n&&ce(0)},[]),_e=t.useCallback(()=>{const s=Q.current;s&&(s.scrollTop=s.scrollHeight,me(!0),ce(0))},[]),Le=t.useCallback(async(s,a)=>{var n,o,c;if(k.rename)return!1;I(b=>({...b,rename:!0}));try{const b=a.trim();return b?(N.some(T=>T.id===s)?(await M.patch(`/opencode-sessions/${encodeURIComponent(s)}`,{title:b}),R(T=>T.map(i=>i.id===s?{...i,title:b}:i))):(await M.post(`/chat/sessions/${encodeURIComponent(s)}/rename`,{title:b}),g(T=>T.map(i=>i.id===s?{...i,title:b}:i))),(o=D.current)==null||o.success("Renamed."),!0):((n=D.current)==null||n.error("Title cannot be empty."),!1)}catch(b){return(c=D.current)==null||c.error(`Rename failed: ${b.message}`),!1}finally{I(b=>({...b,rename:!1}))}},[k.rename,N]),Ae=t.useCallback(async s=>{var a,n;if(k.delete)return!1;I(o=>({...o,delete:!0}));try{return N.some(c=>c.id===s)?(await M.del(`/opencode-sessions/${encodeURIComponent(s)}`),R(c=>c.filter(b=>b.id!==s)),E===s&&te()):(await M.del(`/chat/sessions/${encodeURIComponent(s)}`),g(c=>c.filter(b=>b.id!==s)),C===s&&(m(""),l([]))),ue(c=>{const b={...c};return delete b[s],b}),(a=D.current)==null||a.success("Session deleted."),!0}catch(o){return(n=D.current)==null||n.error(`Delete failed: ${o.message}`),!1}finally{I(o=>({...o,delete:!1}))}},[k.delete,N,E,te,C]);return t.useEffect(()=>{Q.current&&(de?Q.current.scrollTop=Q.current.scrollHeight:ce(s=>s+1))},[d,P]),t.useEffect(()=>()=>{if(K.current=!1,V.current=null,z.current!==null&&(clearTimeout(z.current),z.current=null),O.current){try{O.current.close()}catch{}O.current=null}},[]),t.useEffect(()=>{u?ae(u):H(),re()},[]),t.useEffect(()=>{const s=a=>{var o;const n=(o=a.detail)==null?void 0:o.taskId;n&&ae(n)};return window.addEventListener("bizar:setChatTask",s),()=>window.removeEventListener("bizar:setChatTask",s)},[ae]),t.useEffect(()=>{let s=!1;return ns(async()=>{const{Ws:a}=await import("./mobile-j3rOZK6v.js").then(n=>n.w);return{Ws:a}},__vite__mapDeps([0,1,2,3])).then(({Ws:a})=>{if(s)return;new a().on(o=>{if(o.type!=="chat:message")return;const c=o.message;c&&l(b=>b.some(T=>T.ts===c.ts)?b:[...b,c])})}),()=>{s=!0}},[]),{messages:W==="opencode"?P:d,bizarMessages:d,opencodeMessages:P,sessions:y,opencodeSessions:N,sessionId:C,setSessionId:m,loading:x,sending:k.send,pinned:Ie,listRef:Q,activeSource:W,activeOpencodeSessionId:E,opencodeError:G,opencodeSuggestion:Ce,opencodeErrorInfo:ke,retryOpencodeSession:()=>{E&&oe(E)},sessionStates:se,busy:k,getSessionDisplay:s=>{var a,n,o,c;return{...s,state:((a=se[s.id])==null?void 0:a.state)??"idle",unread:((n=se[s.id])==null?void 0:n.unread)??0,pinned:((o=se[s.id])==null?void 0:o.pinned)??!1,tree:(c=se[s.id])==null?void 0:c.tree}},stickToBottom:de,newMessageCount:Se,handleScroll:Me,jumpToLatest:_e,setToast:Ne,loadChat:H,loadTaskChat:ae,refreshSessions:ie,refreshOpencodeSessions:re,loadOpencodeSession:oe,closeOpencodeSession:te,selectBizarSession:Re,onCreateSession:De,onSend:Te,onRegenerate:$e,deleteMessage:Ee,togglePin:ze,copyMessage:Oe,renameSession:Le,deleteSession:Ae,seenOpencodeMessages:ve}}const fs=[{cmd:"/visual-plan [on|off|status]",desc:"Toggle or view visual plan mode"},{cmd:"/plan new <slug> [template]",desc:"Create a new plan"},{cmd:"/plan list",desc:"List all plans"},{cmd:"/plan open <slug>",desc:"Open a plan in the viewer"},{cmd:"/plan status <slug> <status>",desc:"Set plan status"},{cmd:"/plan get <slug>",desc:"Fetch plan canvas"},{cmd:"/plan add <slug> --title T --type kind",desc:"Add element to a plan"},{cmd:"/plan update <slug> <id>",desc:"Update a plan element"},{cmd:"/plan delete <slug> <id>",desc:"Delete a plan element"},{cmd:'/plan comment <slug> [id] "text"',desc:"Add a comment"},{cmd:"/plan comments <slug> [id]",desc:"Read plan comments"},{cmd:"/bizar",desc:"Launch Bizar dashboard"},{cmd:"/bizar <args>",desc:"Route via Bizar menu"},{cmd:"/audit",desc:"Run security audit"},{cmd:"/explain <q>",desc:"Read-only code Q&A"},{cmd:"/init",desc:"Initialize .bizar/ in this project"},{cmd:"/learn",desc:"Extract patterns from session"},{cmd:"/pr-review",desc:"PR review"},{cmd:"/help | /commands",desc:"Show all Bizar commands"}];function Is(r){const[h,u]=t.useState(""),d=t.useMemo(()=>[...fs,...(r.mods||[]).flatMap(y=>{var g;return(g=y.entry)!=null&&g.command?[{cmd:`/${y.id}`,desc:y.description||y.name,mod:y.id}]:[]})],[r.mods]),l=t.useMemo(()=>{if(!h.startsWith("/")||h.includes(" "))return[];const y=h.toLowerCase();return d.filter(g=>g.cmd.toLowerCase().startsWith(y)).slice(0,6)},[h,d]);return{allCommands:d,suggestions:l,setQuery:u}}export{Ss as C,ws as T,ls as V,vs as a,Is as b,Cs as c,ks as d,js as u};
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/mobile-CSsp30lr.js","assets/react-vendor-Dn4wqh4Z.js","assets/icons-Bd8piSb2.js","assets/mobile-CsZQAswA.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{r as t,j as e}from"./react-vendor-Dn4wqh4Z.js";import{E as Be,C as Ue,I as Pe,J as Fe,X as xe,b as Ge,d as je,bh as We,aS as qe,bi as He,bj as Ke,aG as Ye,R as Ve,bk as Je,Z as Qe,B as Xe,bl as be,i as Ze,U as es}from"./icons-Bd8piSb2.js";import{b as ss,e as ts,a as M,A as le,_ as ns}from"./mobile-CSsp30lr.js";import{M as as,r as rs}from"./markdown-C6mXtQxD.js";const we=t.createContext(null);function js(){const r=t.useContext(we);return r||{show:()=>{},info:()=>{},success:()=>{},error:()=>{},warning:()=>{},dismiss:()=>{},toasts:[]}}const os={info:Fe,success:Pe,error:Ue,warning:Be};function ws({children:r}){const[h,u]=t.useState([]),d=t.useRef(1),l=t.useRef(new Map),y=t.useCallback(m=>{u($=>$.filter(k=>k.id!==m));const x=l.current.get(m);x&&(clearTimeout(x),l.current.delete(m))},[]),g=t.useCallback((m,x="info",$=4e3)=>{const k=d.current++;if(u(I=>[...I,{id:k,kind:x,message:m}]),$>0){const I=setTimeout(()=>y(k),$);l.current.set(k,I)}},[y]);t.useEffect(()=>()=>{for(const m of l.current.values())clearTimeout(m);l.current.clear()},[]);const C=t.useMemo(()=>({show:g,info:(m,x)=>g(m,"info",x),success:(m,x)=>g(m,"success",x),error:(m,x)=>g(m,"error",x),warning:(m,x)=>g(m,"warning",x),dismiss:y,toasts:h}),[g,y,h]);return e.jsxs(we.Provider,{value:C,children:[r,e.jsx(cs,{toasts:h,onDismiss:y})]})}function cs({toasts:r,onDismiss:h}){return e.jsx("div",{className:"toast-stack","aria-live":"polite",children:r.map(u=>e.jsx(is,{toast:u,onDismiss:h},u.id))})}function is({toast:r,onDismiss:h}){const u=os[r.kind];return e.jsxs("div",{className:`toast toast-${r.kind}`,role:"alert","aria-live":"assertive","aria-atomic":"true",children:[e.jsx(u,{size:16,className:"toast-icon"}),e.jsx("span",{className:"toast-message",children:r.message}),e.jsx("button",{type:"button",className:"toast-close","aria-label":"Dismiss",onClick:()=>h(r.id),children:e.jsx(xe,{size:14})})]})}function ls({items:r,renderItem:h,itemHeight:u=80,height:d=400,overscan:l=5,className:y}){const[g,C]=t.useState(0),m=t.useRef(null),x=t.useMemo(()=>{const N=Math.max(0,Math.floor(g/u)-l),R=Math.min(r.length,Math.ceil((g+d)/u)+l);return{start:N,end:R}},[g,u,d,l,r.length]),$=r.length*u,k=x.start*u,I=r.slice(x.start,x.end);return e.jsx("div",{ref:m,onScroll:N=>C(N.currentTarget.scrollTop),style:{height:d,overflowY:"auto"},className:y,children:e.jsx("div",{style:{height:$,position:"relative"},children:e.jsx("div",{style:{transform:`translateY(${k}px)`},children:I.map((N,R)=>e.jsx("div",{style:{height:u},children:h(N,x.start+R)},x.start+R))})})})}function Cs({activeProject:r,sessionCount:h,sessionsOpen:u,infoOpen:d,onToggleSessions:l,onToggleInfo:y,onOpenOverview:g}){return e.jsxs("header",{className:"chat-topbar",children:[e.jsxs("button",{type:"button",className:"chat-topbar-project",onClick:g,children:[e.jsx(Ge,{size:14}),e.jsx("span",{className:"chat-topbar-project-name",children:(r==null?void 0:r.name)??"No project"}),e.jsx(je,{size:12})]}),e.jsx("div",{className:"chat-topbar-spacer"}),e.jsxs("button",{type:"button",className:`chat-topbar-btn ${u?"active":""}`,onClick:l,"aria-pressed":u,children:["Sessions (",h,")"]}),e.jsx("button",{type:"button",className:`chat-topbar-btn ${d?"active":""}`,onClick:y,"aria-pressed":d,children:"Info"})]})}function us({count:r=3}){return e.jsx("div",{className:"chat-loading-skeleton","aria-label":"Loading messages",children:Array.from({length:r}).map((h,u)=>e.jsxs("div",{className:"chat-loading-skeleton-bubble",children:[e.jsx("div",{className:"chat-loading-skeleton-meta"}),e.jsx("div",{className:"chat-loading-skeleton-line"}),e.jsx("div",{className:"chat-loading-skeleton-line short"})]},u))})}function ds({projectName:r,onPickSuggestion:h}){const u=[{icon:e.jsx(We,{size:16}),title:r?`Explain ${r}`:"Explain this project",preview:"Give me a tour of the codebase, highlight the architecture, and call out any anti-patterns or hotspots.",prompt:r?`Explain the ${r} project. Give me a tour of the codebase, highlight the architecture, and call out any anti-patterns or hotspots.`:"Explain the current project. Give me a tour of the codebase, highlight the architecture, and call out any anti-patterns or hotspots."},{icon:e.jsx(qe,{size:16}),title:"Summarize recent sessions",preview:"Read my last 5 chat sessions and give me a 3-bullet summary of what I worked on and what got stuck.",prompt:"Read my last 5 chat sessions and give me a 3-bullet summary of what I worked on and what got stuck."},{icon:e.jsx(He,{size:16}),title:"Suggest a refactor",preview:"Look for the largest, most painful files in this project and propose a concrete refactor for the worst one.",prompt:"Look for the largest, most painful files in this project and propose a concrete refactor for the worst one."},{icon:e.jsx(Ke,{size:16}),title:"Find visual regressions",preview:"Open the dashboard, screenshot the Chat tab, and flag any layout problems or anti-patterns you see.",prompt:"Open the dashboard, screenshot the Chat tab, and flag any layout problems or anti-patterns you see."}];return e.jsx("div",{className:"chat-suggestions",children:u.map((d,l)=>e.jsxs("button",{type:"button",className:"chat-suggestion",onClick:()=>h(d.prompt),children:[e.jsxs("div",{className:"chat-suggestion-title",children:[d.icon,e.jsx("span",{children:d.title})]}),e.jsx("div",{className:"chat-suggestion-preview",children:d.preview})]},l))})}function ye({variant:r,projectName:h,onPickSuggestion:u}){if(r==="no-project")return e.jsxs("div",{className:"chat-welcome",children:[e.jsx("h1",{className:"chat-welcome-h1",children:e.jsx("span",{className:"chat-greeting-hello",children:"No project selected."})}),e.jsx("p",{className:"chat-welcome-subtitle",children:"Pick a project in Overview to scope chat sessions."})]});const d=h||"there";return e.jsxs("div",{className:"chat-welcome",children:[e.jsxs("h1",{className:"chat-welcome-h1",children:[e.jsx("span",{className:"chat-greeting-hello",children:"Hello, "}),e.jsxs("span",{className:"chat-greeting-name",children:[d,"."]})]}),e.jsx("p",{className:"chat-welcome-subtitle",children:"How can I help you today?"}),e.jsx(ds,{projectName:h,onPickSuggestion:u})]})}function ms({message:r,pinned:h,onCopy:u,onDelete:d,onTogglePin:l,onRegenerate:y}){const g=(r.role||"assistant").toLowerCase(),C=r.ts?ss(r.ts):"",m=r.content||r.message||"",x=g==="user";return e.jsxs("article",{className:`chat-message ${x?"chat-message-user":"chat-message-assistant"} ${h?"chat-message-pinned":""}`,children:[e.jsxs("header",{className:"chat-message-meta",children:[e.jsx("span",{className:"chat-message-role",children:g}),r.agent&&e.jsxs("span",{className:"chat-message-agent",children:["@",r.agent]}),C&&e.jsx("time",{className:"chat-message-time",children:C}),h&&e.jsx("span",{className:"chat-message-pin",children:"pinned"}),e.jsxs("div",{className:"chat-message-actions",children:[e.jsx("button",{type:"button",className:"chat-msg-action-btn",onClick:u,title:"Copy","aria-label":"Copy",children:e.jsx(Ye,{size:12})}),!x&&e.jsx("button",{type:"button",className:"chat-msg-action-btn",onClick:y,title:"Regenerate","aria-label":"Regenerate",children:e.jsx(Ve,{size:12})}),e.jsx("button",{type:"button",className:"chat-msg-action-btn",onClick:l,title:"Pin","aria-label":"Pin",children:e.jsx(Je,{size:12})}),e.jsx("button",{type:"button",className:"chat-msg-action-btn chat-msg-action-btn-danger",onClick:d,title:"Delete","aria-label":"Delete",children:e.jsx(Qe,{size:12})})]})]}),e.jsx("div",{className:"chat-message-content markdown-body",children:e.jsx(as,{remarkPlugins:[rs],children:m})})]})}function ks({messages:r,loading:h,activeProject:u,sessionId:d,pinned:l,activeSource:y,onPickSuggestion:g,onCopy:C,onDelete:m,onTogglePin:x,onRegenerate:$}){const k=t.useRef(null);t.useEffect(()=>{const N=k.current;if(!N)return;let R=N.parentElement,P=!1;for(;R;){if(R.classList.contains("chat-thread-scroll")){P=!0;break}R=R.parentElement}P||(N.scrollTop=N.scrollHeight)},[r]);const I=y==="opencode"?"opencode":"bizar";return h?e.jsx("div",{className:"chat-thread legacy",ref:k,"data-stream":I,children:e.jsx(us,{count:3})}):u?r.length===0?e.jsx("div",{className:"chat-thread legacy",ref:k,"data-stream":I,children:e.jsx(ye,{variant:"empty",projectName:u.name,onPickSuggestion:g})}):e.jsx("div",{className:"chat-thread legacy",ref:k,children:e.jsx(ls,{items:r,itemHeight:120,height:800,className:"chat-thread-virtual",renderItem:(N,R)=>e.jsx(ms,{message:N,pinned:l.has(R),onCopy:()=>C(N),onDelete:()=>m(R),onTogglePin:()=>x(R),onRegenerate:()=>$(String(N.ts??R))})})}):e.jsx("div",{className:"chat-thread legacy",ref:k,"data-stream":I,children:e.jsx(ye,{variant:"no-project",projectName:"",onPickSuggestion:g})})}function ps({agent:r,setAgent:h,agents:u}){const[d,l]=t.useState(!1),y=t.useRef(null);t.useEffect(()=>{if(!d)return;const m=x=>{y.current&&!y.current.contains(x.target)&&l(!1)};return document.addEventListener("mousedown",m),()=>document.removeEventListener("mousedown",m)},[d]);const g=r||"no agent",C=g.startsWith("@")?g.slice(1):g;return e.jsxs("div",{className:"chat-agent-chip",ref:y,children:[e.jsxs("button",{type:"button",className:"chat-agent-chip-btn",onClick:()=>l(m=>!m),"aria-haspopup":"listbox","aria-expanded":d,children:[e.jsx(Xe,{size:14}),e.jsx("span",{children:C}),e.jsx(je,{size:12,className:d?"rotated":""})]}),d&&e.jsxs("div",{className:"chat-agent-chip-menu",role:"listbox",children:[e.jsx("button",{type:"button",role:"option","aria-selected":!r,onClick:()=>{h(""),l(!1)},children:e.jsx("span",{children:"no agent"})}),u.map(m=>e.jsx("button",{type:"button",role:"option","aria-selected":r===m.name,onClick:()=>{h(m.name),l(!1)},children:e.jsxs("span",{children:["@",m.name]})},m.name))]})]})}function hs(r,h,u=240){t.useLayoutEffect(()=>{const d=r.current;if(!d)return;d.style.height="auto";const l=Math.min(d.scrollHeight,u);d.style.height=`${l}px`,d.style.overflowY=d.scrollHeight>u?"auto":"hidden"},[r,h,u])}function Ss({agent:r,setAgent:h,model:u,setModel:d,text:l,setText:y,sending:g,onSend:C,attachments:m,setAttachments:x,suggestions:$,onPickSuggestion:k,agents:I,onAttach:N}){const R=t.useRef(null),P=t.useRef(null);hs(R,l,160);const F=j=>{if(j.key==="Enter"&&(j.metaKey||j.ctrlKey))j.preventDefault(),C();else if(j.key==="Enter"&&!j.shiftKey)j.preventDefault(),C();else if(j.key==="Tab"&&$.length){j.preventDefault();const E=$[0].cmd.split(" ")[0];y(`${E} `)}},G=j=>{const E=j.target.files;if(!E)return;const A=[];for(let W=0;W<E.length;W++)A.push(E[W].name);x(W=>[...W,...A]),j.target.value=""};return e.jsxs("div",{className:"chat-composer",children:[$.length>0&&e.jsx("div",{className:"chat-composer-suggestions",children:$.map(j=>e.jsxs("button",{type:"button",className:"chat-composer-suggestion",onClick:()=>{var A;const E=j.cmd.split(" ")[0];y(`${E} `),(A=R.current)==null||A.focus()},children:[e.jsx("span",{className:"mono",children:j.cmd}),e.jsx("span",{children:j.desc})]},j.cmd))}),m.length>0&&e.jsx("div",{className:"chat-composer-attachments",children:m.map((j,E)=>e.jsxs("span",{className:"chat-composer-attachment-tag",children:[e.jsx(be,{size:10})," ",j,e.jsx("button",{type:"button",className:"chat-composer-attachment-remove",onClick:()=>x(A=>A.filter((W,q)=>q!==E)),"aria-label":`Remove ${j}`,children:e.jsx(xe,{size:10})})]},E))}),e.jsxs("div",{className:"chat-composer-input",children:[e.jsx(ps,{agent:r,setAgent:h,agents:I}),e.jsx("textarea",{ref:R,className:"chat-composer-textarea",placeholder:g?"Sending…":"Send a message…",rows:1,value:l,onChange:j=>y(j.target.value),onKeyDown:F,disabled:g,"aria-label":"Message"}),e.jsx("input",{ref:P,type:"file",multiple:!0,style:{display:"none"},onChange:G,"aria-label":"Attach files",tabIndex:-1}),e.jsx("button",{type:"button",className:"chat-attach-btn",onClick:N,title:"Attach files","aria-label":"Attach files",children:e.jsx(be,{size:14})}),e.jsx("button",{type:"button",className:"chat-attach-btn",onClick:async()=>{if(!l.trim())return;const j=await ts(l);j!==l&&y(j)},title:"Enhance prompt with AI","aria-label":"Enhance prompt",children:e.jsx(Ze,{size:14})}),e.jsx("button",{type:"button",className:"chat-send-btn",onClick:C,disabled:g||!l.trim(),title:"Send (Enter)","aria-label":"Send message",children:e.jsx(es,{size:16})})]})]})}function vs(r,h,u){const[d,l]=t.useState([]),[y,g]=t.useState([]),[C,m]=t.useState(""),[x,$]=t.useState(!0),[k,I]=t.useState({create:!1,send:!1,rename:!1,delete:!1}),[N,R]=t.useState([]),[P,F]=t.useState([]),[G,j]=t.useState(null),[E,A]=t.useState(null),[W,q]=t.useState(null),[Ce,Z]=t.useState(null),[ke,ee]=t.useState(null),[se,ue]=t.useState({}),[de,me]=t.useState(!0),[Se,ce]=t.useState(0),[ve,pe]=t.useState(new Set),[Ie,he]=t.useState(new Set),V=t.useRef(null),D=t.useRef(null),O=t.useRef(null),ne=t.useRef(0),z=t.useRef(null),J=t.useRef(null),Y=t.useRef(!1),Q=t.useCallback(s=>{s&&F(a=>{if(s.id&&a.some(o=>o.id===s.id))return a;const n=a.findIndex(o=>typeof o.id=="string"&&o.id.startsWith("msg_")&&o.role===s.role&&(o.content||"")===(s.content||""));if(n>=0){const o=a.slice();return o[n]={...s,id:s.id??a[n].id},o}return[...a,s]})},[]),X=t.useCallback(s=>{s&&pe(a=>{if(a.has(s))return a;const n=new Set(a);return n.add(s),n})},[]),H=t.useCallback((s,a)=>{ue(n=>{const o=n[s]??{state:"idle",unread:0,pinned:!1};return{...n,[s]:{...o,...a}}})},[]),B=t.useCallback((s,a)=>{H(s,{state:a?"streaming":"idle"})},[H]),Ne=t.useCallback(s=>{D.current=s},[]),K=t.useCallback(async s=>{var a;try{const n=s?`/chat?session=${encodeURIComponent(s)}`:"/chat?limit=200",o=await M.get(n);l(o.messages||[]),g(o.sessions||[])}catch(n){(a=D.current)==null||a.error(`Chat load failed: ${n.message}`)}finally{$(!1)}},[]),ae=t.useCallback(async s=>{var a;$(!0);try{const n=await M.get(`/tasks/${encodeURIComponent(s)}/chat`);l(n.messages||[]),m(n.sessionId||s)}catch(n){(a=D.current)==null||a.error(`Task chat load failed: ${n.message}`)}finally{$(!1)}},[]),ie=t.useCallback(async()=>{try{const s=await M.get("/chat/sessions");g(s.sessions||[])}catch{}},[]),re=t.useCallback(async()=>{try{const a=((await M.get("/opencode-sessions")).sessions||[]).map(n=>({...n,source:"opencode",title:n.title||n.id}));R(a)}catch{}},[]),fe=t.useCallback(s=>{if(O.current){try{O.current.close()}catch{}O.current=null}z.current!==null&&(clearTimeout(z.current),z.current=null);const a=M.getToken(),n=a?`/api/opencode-sessions/${encodeURIComponent(s)}/stream?token=${encodeURIComponent(a)}`:`/api/opencode-sessions/${encodeURIComponent(s)}/stream`;J.current=s,Y.current=!0,ne.current=0,q(null),Z(null),ee(null);const o=()=>{if(!Y.current||J.current!==s)return;const c=new EventSource(n);O.current=c;const b=i=>{var S,_,L,U;if(!i||!i.type||i.sessionID&&i.sessionID!==s)return;const f=new Date().toISOString(),w=s;if(i.type==="message.user.created"||i.type==="message.user.updated"){const p=i.data;Q({id:(p==null?void 0:p.messageID)??i.messageID,role:"user",content:((S=p==null?void 0:p.data)==null?void 0:S.content)??"",ts:f}),X((p==null?void 0:p.messageID)??i.messageID);return}if(i.type==="message.assistant.created"||i.type==="message.assistant.updated"){const p=i.data;Q({id:(p==null?void 0:p.messageID)??i.messageID,role:"assistant",content:((_=p==null?void 0:p.data)==null?void 0:_.content)??"",ts:f}),X((p==null?void 0:p.messageID)??i.messageID),B(w,!0);return}if(i.type==="message.part.updated"){const p=i.data,ge=((L=p==null?void 0:p.part)==null?void 0:L.text)??"";if(!ge)return;Q({id:(p==null?void 0:p.id)??(p==null?void 0:p.messageID)??i.messageID,role:"assistant",content:ge,ts:f}),X((p==null?void 0:p.id)??(p==null?void 0:p.messageID)??i.messageID),B(w,!0);return}if(i.type==="session.idle"||i.type==="message.assistant.completed"||i.type==="session.completed"){B(w,!1);return}if(i.type==="session.awaiting"||i.type==="session.awaiting_input"||i.type==="message.assistant.awaiting"){H(w,{state:"awaiting"});return}if(i.type==="session.error"){q(((U=i.data)==null?void 0:U.message)||"opencode session error");return}},v=i=>{if(!i)return null;try{const f=JSON.parse(i);if(typeof f.type=="string"){const w=f.properties,S=f.data??w,_=typeof f.sessionID=="string"?f.sessionID:typeof(w==null?void 0:w.sessionID)=="string"?w.sessionID:typeof(S==null?void 0:S.sessionID)=="string"?S.sessionID:void 0,L=typeof f.messageID=="string"?f.messageID:typeof(w==null?void 0:w.messageID)=="string"?w.messageID:typeof(S==null?void 0:S.messageID)=="string"?S.messageID:void 0;let U=f.type;const p=/\.\d+$/.exec(U);return p&&(U=U.slice(0,p.index)),{type:U,sessionID:_,messageID:L,data:f}}if(f.type==="sync"&&f.syncEvent&&typeof f.syncEvent=="object"){const w=f.syncEvent;let S=w.type||"";const _=/\.\d+$/.exec(S);_&&(S=S.slice(0,_.index));const L=w.data||{};return{type:S,sessionID:typeof L.sessionID=="string"?L.sessionID:void 0,messageID:typeof L.messageID=="string"?L.messageID:void 0,data:w}}return null}catch{return null}},T=["message.user.created","message.user.updated","message.assistant.created","message.assistant.updated","message.part.updated","session.idle","message.assistant.completed","session.completed","session.awaiting","session.awaiting_input","message.assistant.awaiting","session.error"];for(const i of T)c.addEventListener(i,f=>{b(v(f.data))});c.onerror=()=>{if(J.current!==s)return;if(!Y.current){try{c.close()}catch{}O.current=null;return}try{c.close()}catch{}O.current=null;const i=ne.current+1;ne.current=i;const f=Math.min(3e4,1e3*2**(i-1));z.current!==null&&clearTimeout(z.current),z.current=window.setTimeout(()=>{z.current=null,Y.current&&J.current===s&&o()},f)},c.onopen=()=>{ne.current=0,q(null),Z(null),ee(null)}};o()},[Q,X,B,H]),te=t.useCallback(()=>{if(Y.current=!1,J.current=null,z.current!==null&&(clearTimeout(z.current),z.current=null),O.current){try{O.current.close()}catch{}O.current=null}F([]),pe(new Set),q(null),Z(null),ee(null),A(null),j("bizar")},[]),oe=t.useCallback(async s=>{var a;if(Y.current=!1,O.current){try{O.current.close()}catch{}O.current=null}z.current!==null&&(clearTimeout(z.current),z.current=null),q(null),Z(null),ee(null),$(!0);try{const n=await M.get(`/opencode-sessions/${encodeURIComponent(s)}/messages`);F(n.messages||[])}catch(n){const o=n.message;let c=null;if(n instanceof le&&n.data&&typeof n.data=="object"){const b=n.data,v=b.error||"unknown",T=v!=="bad_request"&&v!=="too_many_subscribers"&&v!=="unauthorized";c={type:"session_load_failed",code:v,message:b.message||o,cause:b.cause,status:b.status,suggestion:b.suggestion??null,canRetry:T}}else n instanceof le&&(c={type:"session_load_failed",code:"unknown",message:o,suggestion:null,canRetry:!0});q(c?`Opencode session load failed (${c.code}): ${c.message}`:`Opencode session load failed: ${o}`),Z((c==null?void 0:c.suggestion)??null),ee(c),(a=D.current)==null||a.error(c?`Opencode session load failed: ${c.message}`:`Opencode session load failed: ${o}`),F([])}finally{$(!1)}A(s),j("opencode"),B(s,!1),fe(s)},[B,fe]),Re=t.useCallback(s=>{te(),m(s),j("bizar"),K(s),H(s,{unread:0})},[te,K,H]),De=t.useCallback(async()=>{var a,n,o,c,b;if(k.create)return{ok:!1};const s=h.defaultAgent||"odin";I(v=>({...v,create:!0}));try{try{const T=await M.post("/opencode-sessions/new",{agent:s});return await re(),await oe(T.id),(a=D.current)==null||a.success(`Session ${T.id} created.`),{ok:!0,source:"opencode",id:T.id}}catch(T){if(!(T instanceof le)||T.status!==503)return(n=D.current)==null||n.error(`Create failed: ${T.message}`),{ok:!1}}if(!r.activeProject)return(o=D.current)==null||o.error("Pick a project in Overview to scope chat sessions."),{ok:!1};const v=await M.post("/chat/sessions",{});return m(v.id),l([]),he(new Set),H(v.id,{state:"idle",unread:0}),await K(v.id),ie().catch(()=>{}),(c=D.current)==null||c.success(`Session ${v.id} created.`),{ok:!0,source:"bizar",id:v.id}}catch(v){return(b=D.current)==null||b.error(`Create failed: ${v.message}`),{ok:!1}}finally{I(v=>({...v,create:!1}))}},[k.create,h.defaultAgent,r.activeProject,re,oe,K,ie,H]),Te=t.useCallback(async(s,a,n,o)=>{var v,T,i;if(k.send)return{ok:!1};const c=s.trim();if(!c)return{ok:!1};if(G==="opencode"&&E){const f=E,w=`msg_${Date.now().toString(36)}${Math.random().toString(36).slice(2,8)}`,S={id:w,role:"user",content:c,agent:a,ts:new Date().toISOString()};Q(S),X(w),I(_=>({..._,send:!0}));try{return await M.post(`/opencode-sessions/${encodeURIComponent(f)}/send`,{message:c,agent:a}),B(f,!0),{ok:!0}}catch(_){return F(L=>L.filter(U=>U.id!==w)),(v=D.current)==null||v.error(`Send failed: ${_.message}`),{ok:!1}}finally{I(_=>({..._,send:!1}))}}const b={role:"user",content:c,agent:a,ts:new Date().toISOString()};l(f=>[...f,b]),I(f=>({...f,send:!0})),B(C,!0);try{const f=await M.post("/chat",{message:c,agent:a,model:n,attachments:o||[]});if(f!=null&&f.messages)for(const w of f.messages)w.role==="assistant"&&l(S=>S.some(L=>L.ts===w.ts)?S:[...S,w]);else(T=D.current)==null||T.info("Still processing… the response will appear shortly.");return{ok:!0}}catch(f){return l(w=>w.filter(S=>S!==b)),(i=D.current)==null||i.error(`Send failed: ${f.message}`),{ok:!1}}finally{I(f=>({...f,send:!1})),B(C,!1)}},[G,E,Q,X,B,C,k.send]),$e=t.useCallback(async s=>{var a,n;if(!C){(a=D.current)==null||a.error("No active session to regenerate.");return}try{await M.post("/chat/regenerate",{sessionId:C,messageId:s}),await K(C)}catch(o){(n=D.current)==null||n.error(`Regenerate failed: ${o.message}`)}},[C,K]),Ee=t.useCallback(s=>{G==="opencode"?F(a=>a.filter((n,o)=>o!==s)):l(a=>a.filter((n,o)=>o!==s))},[G]),ze=t.useCallback(s=>{he(a=>{const n=new Set(a);return n.has(s)?n.delete(s):n.add(s),n})},[]),Oe=t.useCallback(s=>{var n,o;const a=s.content||s.message||"";try{(n=navigator.clipboard)==null||n.writeText(a).then(()=>{var c;return(c=D.current)==null?void 0:c.success("Copied.")},()=>{var c;return(c=D.current)==null?void 0:c.error("Copy failed.")})}catch{(o=D.current)==null||o.error("Copy failed.")}},[]),Me=t.useCallback(()=>{const s=V.current;if(!s)return;const n=s.scrollHeight-s.scrollTop-s.clientHeight<32;me(n),n&&ce(0)},[]),_e=t.useCallback(()=>{const s=V.current;s&&(s.scrollTop=s.scrollHeight,me(!0),ce(0))},[]),Le=t.useCallback(async(s,a)=>{var n,o,c;if(k.rename)return!1;I(b=>({...b,rename:!0}));try{const b=a.trim();return b?(N.some(T=>T.id===s)?(await M.patch(`/opencode-sessions/${encodeURIComponent(s)}`,{title:b}),R(T=>T.map(i=>i.id===s?{...i,title:b}:i))):(await M.post(`/chat/sessions/${encodeURIComponent(s)}/rename`,{title:b}),g(T=>T.map(i=>i.id===s?{...i,title:b}:i))),(o=D.current)==null||o.success("Renamed."),!0):((n=D.current)==null||n.error("Title cannot be empty."),!1)}catch(b){return(c=D.current)==null||c.error(`Rename failed: ${b.message}`),!1}finally{I(b=>({...b,rename:!1}))}},[k.rename,N]),Ae=t.useCallback(async s=>{var a,n;if(k.delete)return!1;I(o=>({...o,delete:!0}));try{return N.some(c=>c.id===s)?(await M.del(`/opencode-sessions/${encodeURIComponent(s)}`),R(c=>c.filter(b=>b.id!==s)),E===s&&te()):(await M.del(`/chat/sessions/${encodeURIComponent(s)}`),g(c=>c.filter(b=>b.id!==s)),C===s&&(m(""),l([]))),ue(c=>{const b={...c};return delete b[s],b}),(a=D.current)==null||a.success("Session deleted."),!0}catch(o){return(n=D.current)==null||n.error(`Delete failed: ${o.message}`),!1}finally{I(o=>({...o,delete:!1}))}},[k.delete,N,E,te,C]);return t.useEffect(()=>{V.current&&(de?V.current.scrollTop=V.current.scrollHeight:ce(s=>s+1))},[d,P]),t.useEffect(()=>()=>{if(Y.current=!1,J.current=null,z.current!==null&&(clearTimeout(z.current),z.current=null),O.current){try{O.current.close()}catch{}O.current=null}},[]),t.useEffect(()=>{u?ae(u):K(),re()},[]),t.useEffect(()=>{const s=a=>{var o;const n=(o=a.detail)==null?void 0:o.taskId;n&&ae(n)};return window.addEventListener("bizar:setChatTask",s),()=>window.removeEventListener("bizar:setChatTask",s)},[ae]),t.useEffect(()=>{let s=!1;return ns(async()=>{const{Ws:a}=await import("./mobile-CSsp30lr.js").then(n=>n.w);return{Ws:a}},__vite__mapDeps([0,1,2,3])).then(({Ws:a})=>{if(s)return;new a().on(o=>{if(o.type!=="chat:message")return;const c=o.message;c&&l(b=>b.some(T=>T.ts===c.ts)?b:[...b,c])})}),()=>{s=!0}},[]),{messages:G==="opencode"?P:d,bizarMessages:d,opencodeMessages:P,sessions:y,opencodeSessions:N,sessionId:C,setSessionId:m,loading:x,sending:k.send,pinned:Ie,listRef:V,activeSource:G,activeOpencodeSessionId:E,opencodeError:W,opencodeSuggestion:Ce,opencodeErrorInfo:ke,retryOpencodeSession:()=>{E&&oe(E)},sessionStates:se,busy:k,getSessionDisplay:s=>{var a,n,o,c;return{...s,state:((a=se[s.id])==null?void 0:a.state)??"idle",unread:((n=se[s.id])==null?void 0:n.unread)??0,pinned:((o=se[s.id])==null?void 0:o.pinned)??!1,tree:(c=se[s.id])==null?void 0:c.tree}},stickToBottom:de,newMessageCount:Se,handleScroll:Me,jumpToLatest:_e,setToast:Ne,loadChat:K,loadTaskChat:ae,refreshSessions:ie,refreshOpencodeSessions:re,loadOpencodeSession:oe,closeOpencodeSession:te,selectBizarSession:Re,onCreateSession:De,onSend:Te,onRegenerate:$e,deleteMessage:Ee,togglePin:ze,copyMessage:Oe,renameSession:Le,deleteSession:Ae,seenOpencodeMessages:ve}}const fs=[{cmd:"/visual-plan [on|off|status]",desc:"Toggle or view visual plan mode"},{cmd:"/plan new <slug> [template]",desc:"Create a new plan"},{cmd:"/plan list",desc:"List all plans"},{cmd:"/plan open <slug>",desc:"Open a plan in the viewer"},{cmd:"/plan status <slug> <status>",desc:"Set plan status"},{cmd:"/plan get <slug>",desc:"Fetch plan canvas"},{cmd:"/plan add <slug> --title T --type kind",desc:"Add element to a plan"},{cmd:"/plan update <slug> <id>",desc:"Update a plan element"},{cmd:"/plan delete <slug> <id>",desc:"Delete a plan element"},{cmd:'/plan comment <slug> [id] "text"',desc:"Add a comment"},{cmd:"/plan comments <slug> [id]",desc:"Read plan comments"},{cmd:"/bizar",desc:"Launch Bizar dashboard"},{cmd:"/bizar <args>",desc:"Route via Bizar menu"},{cmd:"/audit",desc:"Run security audit"},{cmd:"/explain <q>",desc:"Read-only code Q&A"},{cmd:"/init",desc:"Initialize .bizar/ in this project"},{cmd:"/learn",desc:"Extract patterns from session"},{cmd:"/pr-review",desc:"PR review"},{cmd:"/help | /commands",desc:"Show all Bizar commands"}];function Is(r){const[h,u]=t.useState(""),d=t.useMemo(()=>[...fs,...(r.mods||[]).flatMap(y=>{var g;return(g=y.entry)!=null&&g.command?[{cmd:`/${y.id}`,desc:y.description||y.name,mod:y.id}]:[]})],[r.mods]),l=t.useMemo(()=>{if(!h.startsWith("/")||h.includes(" "))return[];const y=h.toLowerCase();return d.filter(g=>g.cmd.toLowerCase().startsWith(y)).slice(0,6)},[h,d]);return{allCommands:d,suggestions:l,setQuery:u}}export{Ss as C,ws as T,ls as V,vs as a,Is as b,Cs as c,ks as d,js as u};
|