@nextclaw/ui 0.9.17 → 0.9.18

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 (32) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/assets/{ChannelsList-D75wfbDS.js → ChannelsList-BrUyWJt-.js} +1 -1
  3. package/dist/assets/{ChatPage-gWZ3rDTy.js → ChatPage-BkVleCOF.js} +24 -27
  4. package/dist/assets/{DocBrowser-CebTdor0.js → DocBrowser-DiLg-99Z.js} +1 -1
  5. package/dist/assets/{LogoBadge-gdbraoaZ.js → LogoBadge-B0RCYFfk.js} +1 -1
  6. package/dist/assets/{MarketplacePage-C-zz0lBT.js → MarketplacePage-CS2QbUvK.js} +1 -1
  7. package/dist/assets/{McpMarketplacePage-tfpLh6Zz.js → McpMarketplacePage-C9AxrIdJ.js} +1 -1
  8. package/dist/assets/{ModelConfig-j74dn-5k.js → ModelConfig-Cns1fRR4.js} +1 -1
  9. package/dist/assets/{ProvidersList-BGI9EgVV.js → ProvidersList-BeKvkVyz.js} +1 -1
  10. package/dist/assets/{RemoteAccessPage-CusGQmZE.js → RemoteAccessPage-BVph-WSP.js} +1 -1
  11. package/dist/assets/{RuntimeConfig-pmhW8ifz.js → RuntimeConfig-BhBUz1gc.js} +1 -1
  12. package/dist/assets/{SearchConfig-rrD2_F5u.js → SearchConfig-D8t1on1b.js} +1 -1
  13. package/dist/assets/{SecretsConfig-D7onb-hv.js → SecretsConfig-BoOaUo2a.js} +1 -1
  14. package/dist/assets/{SessionsConfig-m-6RSeja.js → SessionsConfig-B-LZan9R.js} +1 -1
  15. package/dist/assets/{chat-message-BO-s2mvl.js → chat-message-C8oGQU2P.js} +1 -1
  16. package/dist/assets/{index-BsL1YIJ1.js → index-D45Vnh0I.js} +2 -2
  17. package/dist/assets/{label-CDSYExvV.js → label-D8x2fgJm.js} +1 -1
  18. package/dist/assets/{page-layout-BMCVAnQM.js → page-layout-Bxdxpr9D.js} +1 -1
  19. package/dist/assets/{popover-DfywyUDH.js → popover-Daq39m2s.js} +1 -1
  20. package/dist/assets/{security-config-BU-K2EOM.js → security-config-Bd51WlxA.js} +1 -1
  21. package/dist/assets/{skeleton-Cg9CRkOt.js → skeleton-CAcIFczu.js} +1 -1
  22. package/dist/assets/{status-dot-2vau2Xtc.js → status-dot-D11eQRlx.js} +1 -1
  23. package/dist/assets/{switch-CJRPF2V6.js → switch-DizAKjZa.js} +1 -1
  24. package/dist/assets/{tabs-custom-B-2uSCfW.js → tabs-custom-Daa81i4V.js} +1 -1
  25. package/dist/assets/{useConfirmDialog-CfOpdypA.js → useConfirmDialog-DS-q2zMX.js} +1 -1
  26. package/dist/index.html +1 -1
  27. package/package.json +4 -4
  28. package/src/components/chat/adapters/chat-input-bar.adapter.test.ts +32 -1
  29. package/src/components/chat/adapters/chat-input-bar.adapter.ts +6 -3
  30. package/src/components/chat/ncp/ncp-app-client-fetch.test.ts +50 -33
  31. package/src/components/chat/ncp/ncp-app-client-fetch.ts +5 -123
  32. package/src/components/chat/ncp/ncp-chat-page-data.test.ts +8 -0
@@ -1 +1 @@
1
- import{r as s,j as o}from"./vendor-DJt0Azq5.js";import{c as t}from"./index-BsL1YIJ1.js";const l=s.forwardRef(({className:e,...a},r)=>o.jsx("label",{ref:r,className:t("text-sm font-medium leading-none text-gray-700 peer-disabled:cursor-not-allowed peer-disabled:opacity-70",e),...a}));l.displayName="Label";export{l as L};
1
+ import{r as s,j as o}from"./vendor-DJt0Azq5.js";import{c as t}from"./index-D45Vnh0I.js";const l=s.forwardRef(({className:e,...a},r)=>o.jsx("label",{ref:r,className:t("text-sm font-medium leading-none text-gray-700 peer-disabled:cursor-not-allowed peer-disabled:opacity-70",e),...a}));l.displayName="Label";export{l as L};
@@ -1 +1 @@
1
- import{j as e}from"./vendor-DJt0Azq5.js";import{c as l}from"./index-BsL1YIJ1.js";function x({children:t,fullHeight:s=!1,className:a}){return e.jsx("div",{className:l("animate-fade-in",s?"h-[calc(100vh-80px)] w-full flex flex-col":"pb-16",a),children:t})}function c({title:t,description:s,actions:a,className:r}){return e.jsxs("div",{className:l("flex items-center justify-between mb-6 shrink-0",r),children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-900",children:t}),s&&e.jsx("p",{className:"text-sm text-gray-500 mt-1",children:s})]}),a&&e.jsx("div",{className:"flex items-center gap-2 shrink-0",children:a})]})}export{x as P,c as a};
1
+ import{j as e}from"./vendor-DJt0Azq5.js";import{c as l}from"./index-D45Vnh0I.js";function x({children:t,fullHeight:s=!1,className:a}){return e.jsx("div",{className:l("animate-fade-in",s?"h-[calc(100vh-80px)] w-full flex flex-col":"pb-16",a),children:t})}function c({title:t,description:s,actions:a,className:r}){return e.jsxs("div",{className:l("flex items-center justify-between mb-6 shrink-0",r),children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-900",children:t}),s&&e.jsx("p",{className:"text-sm text-gray-500 mt-1",children:s})]}),a&&e.jsx("div",{className:"flex items-center gap-2 shrink-0",children:a})]})}export{x as P,c as a};
@@ -1 +1 @@
1
- import{r as l,aK as L,j as c,aL as z,aM as G,aN as A,aO as O,aP as P,aQ as _,aR as w,aS as b,aT as H,aU as K,aV as U,aW as V,aX as W,aY as Z,aZ as Q,a_ as X,a$ as Y,b0 as q}from"./vendor-DJt0Azq5.js";import{c as B}from"./index-BsL1YIJ1.js";var m="Popover",[E]=K(m,[w]),g=w(),[J,d]=E(m),j=e=>{const{__scopePopover:n,children:t,open:a,defaultOpen:o,onOpenChange:r,modal:s=!1}=e,i=g(n),p=l.useRef(null),[u,h]=l.useState(!1),[C,f]=L({prop:a,defaultProp:o??!1,onChange:r,caller:m});return c.jsx(z,{...i,children:c.jsx(J,{scope:n,contentId:G(),triggerRef:p,open:C,onOpenChange:f,onOpenToggle:l.useCallback(()=>f(x=>!x),[f]),hasCustomAnchor:u,onCustomAnchorAdd:l.useCallback(()=>h(!0),[]),onCustomAnchorRemove:l.useCallback(()=>h(!1),[]),modal:s,children:t})})};j.displayName=m;var N="PopoverAnchor",y=l.forwardRef((e,n)=>{const{__scopePopover:t,...a}=e,o=d(N,t),r=g(t),{onCustomAnchorAdd:s,onCustomAnchorRemove:i}=o;return l.useEffect(()=>(s(),()=>i()),[s,i]),c.jsx(_,{...r,...a,ref:n})});y.displayName=N;var F="PopoverTrigger",S=l.forwardRef((e,n)=>{const{__scopePopover:t,...a}=e,o=d(F,t),r=g(t),s=A(n,o.triggerRef),i=c.jsx(O.button,{type:"button","aria-haspopup":"dialog","aria-expanded":o.open,"aria-controls":o.contentId,"data-state":I(o.open),...a,ref:s,onClick:P(e.onClick,o.onOpenToggle)});return o.hasCustomAnchor?i:c.jsx(_,{asChild:!0,...r,children:i})});S.displayName=F;var R="PopoverPortal",[ee,oe]=E(R,{forceMount:void 0}),M=e=>{const{__scopePopover:n,forceMount:t,children:a,container:o}=e,r=d(R,n);return c.jsx(ee,{scope:n,forceMount:t,children:c.jsx(b,{present:t||r.open,children:c.jsx(H,{asChild:!0,container:o,children:a})})})};M.displayName=R;var v="PopoverContent",T=l.forwardRef((e,n)=>{const t=oe(v,e.__scopePopover),{forceMount:a=t.forceMount,...o}=e,r=d(v,e.__scopePopover);return c.jsx(b,{present:a||r.open,children:r.modal?c.jsx(re,{...o,ref:n}):c.jsx(ne,{...o,ref:n})})});T.displayName=v;var te=W("PopoverContent.RemoveScroll"),re=l.forwardRef((e,n)=>{const t=d(v,e.__scopePopover),a=l.useRef(null),o=A(n,a),r=l.useRef(!1);return l.useEffect(()=>{const s=a.current;if(s)return U(s)},[]),c.jsx(V,{as:te,allowPinchZoom:!0,children:c.jsx(D,{...e,ref:o,trapFocus:t.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:P(e.onCloseAutoFocus,s=>{var i;s.preventDefault(),r.current||(i=t.triggerRef.current)==null||i.focus()}),onPointerDownOutside:P(e.onPointerDownOutside,s=>{const i=s.detail.originalEvent,p=i.button===0&&i.ctrlKey===!0,u=i.button===2||p;r.current=u},{checkForDefaultPrevented:!1}),onFocusOutside:P(e.onFocusOutside,s=>s.preventDefault(),{checkForDefaultPrevented:!1})})})}),ne=l.forwardRef((e,n)=>{const t=d(v,e.__scopePopover),a=l.useRef(!1),o=l.useRef(!1);return c.jsx(D,{...e,ref:n,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:r=>{var s,i;(s=e.onCloseAutoFocus)==null||s.call(e,r),r.defaultPrevented||(a.current||(i=t.triggerRef.current)==null||i.focus(),r.preventDefault()),a.current=!1,o.current=!1},onInteractOutside:r=>{var p,u;(p=e.onInteractOutside)==null||p.call(e,r),r.defaultPrevented||(a.current=!0,r.detail.originalEvent.type==="pointerdown"&&(o.current=!0));const s=r.target;((u=t.triggerRef.current)==null?void 0:u.contains(s))&&r.preventDefault(),r.detail.originalEvent.type==="focusin"&&o.current&&r.preventDefault()}})}),D=l.forwardRef((e,n)=>{const{__scopePopover:t,trapFocus:a,onOpenAutoFocus:o,onCloseAutoFocus:r,disableOutsidePointerEvents:s,onEscapeKeyDown:i,onPointerDownOutside:p,onFocusOutside:u,onInteractOutside:h,...C}=e,f=d(v,t),x=g(t);return Z(),c.jsx(Q,{asChild:!0,loop:!0,trapped:a,onMountAutoFocus:o,onUnmountAutoFocus:r,children:c.jsx(X,{asChild:!0,disableOutsidePointerEvents:s,onInteractOutside:h,onEscapeKeyDown:i,onPointerDownOutside:p,onFocusOutside:u,onDismiss:()=>f.onOpenChange(!1),children:c.jsx(Y,{"data-state":I(f.open),role:"dialog",id:f.contentId,...x,...C,ref:n,style:{...C.style,"--radix-popover-content-transform-origin":"var(--radix-popper-transform-origin)","--radix-popover-content-available-width":"var(--radix-popper-available-width)","--radix-popover-content-available-height":"var(--radix-popper-available-height)","--radix-popover-trigger-width":"var(--radix-popper-anchor-width)","--radix-popover-trigger-height":"var(--radix-popper-anchor-height)"}})})})}),k="PopoverClose",ae=l.forwardRef((e,n)=>{const{__scopePopover:t,...a}=e,o=d(k,t);return c.jsx(O.button,{type:"button",...a,ref:n,onClick:P(e.onClick,()=>o.onOpenChange(!1))})});ae.displayName=k;var se="PopoverArrow",ce=l.forwardRef((e,n)=>{const{__scopePopover:t,...a}=e,o=g(t);return c.jsx(q,{...o,...a,ref:n})});ce.displayName=se;function I(e){return e?"open":"closed"}var ie=j,ve=y,le=S,pe=M,$=T;const Pe=ie,ge=le,ue=l.forwardRef(({className:e,sideOffset:n=8,align:t="start",...a},o)=>c.jsx(pe,{children:c.jsx($,{ref:o,sideOffset:n,align:t,className:B("z-[var(--z-popover,50)] w-72 overflow-hidden rounded-2xl border border-gray-200/50 bg-white p-4 shadow-lg animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",e),...a})}));ue.displayName=$.displayName;export{ve as A,$ as C,pe as P,ie as R,le as T,Pe as a,ge as b,ue as c};
1
+ import{r as l,aK as L,j as c,aL as z,aM as G,aN as A,aO as O,aP as P,aQ as _,aR as w,aS as b,aT as H,aU as K,aV as U,aW as V,aX as W,aY as Z,aZ as Q,a_ as X,a$ as Y,b0 as q}from"./vendor-DJt0Azq5.js";import{c as B}from"./index-D45Vnh0I.js";var m="Popover",[E]=K(m,[w]),g=w(),[J,d]=E(m),j=e=>{const{__scopePopover:n,children:t,open:a,defaultOpen:o,onOpenChange:r,modal:s=!1}=e,i=g(n),p=l.useRef(null),[u,h]=l.useState(!1),[C,f]=L({prop:a,defaultProp:o??!1,onChange:r,caller:m});return c.jsx(z,{...i,children:c.jsx(J,{scope:n,contentId:G(),triggerRef:p,open:C,onOpenChange:f,onOpenToggle:l.useCallback(()=>f(x=>!x),[f]),hasCustomAnchor:u,onCustomAnchorAdd:l.useCallback(()=>h(!0),[]),onCustomAnchorRemove:l.useCallback(()=>h(!1),[]),modal:s,children:t})})};j.displayName=m;var N="PopoverAnchor",y=l.forwardRef((e,n)=>{const{__scopePopover:t,...a}=e,o=d(N,t),r=g(t),{onCustomAnchorAdd:s,onCustomAnchorRemove:i}=o;return l.useEffect(()=>(s(),()=>i()),[s,i]),c.jsx(_,{...r,...a,ref:n})});y.displayName=N;var F="PopoverTrigger",S=l.forwardRef((e,n)=>{const{__scopePopover:t,...a}=e,o=d(F,t),r=g(t),s=A(n,o.triggerRef),i=c.jsx(O.button,{type:"button","aria-haspopup":"dialog","aria-expanded":o.open,"aria-controls":o.contentId,"data-state":I(o.open),...a,ref:s,onClick:P(e.onClick,o.onOpenToggle)});return o.hasCustomAnchor?i:c.jsx(_,{asChild:!0,...r,children:i})});S.displayName=F;var R="PopoverPortal",[ee,oe]=E(R,{forceMount:void 0}),M=e=>{const{__scopePopover:n,forceMount:t,children:a,container:o}=e,r=d(R,n);return c.jsx(ee,{scope:n,forceMount:t,children:c.jsx(b,{present:t||r.open,children:c.jsx(H,{asChild:!0,container:o,children:a})})})};M.displayName=R;var v="PopoverContent",T=l.forwardRef((e,n)=>{const t=oe(v,e.__scopePopover),{forceMount:a=t.forceMount,...o}=e,r=d(v,e.__scopePopover);return c.jsx(b,{present:a||r.open,children:r.modal?c.jsx(re,{...o,ref:n}):c.jsx(ne,{...o,ref:n})})});T.displayName=v;var te=W("PopoverContent.RemoveScroll"),re=l.forwardRef((e,n)=>{const t=d(v,e.__scopePopover),a=l.useRef(null),o=A(n,a),r=l.useRef(!1);return l.useEffect(()=>{const s=a.current;if(s)return U(s)},[]),c.jsx(V,{as:te,allowPinchZoom:!0,children:c.jsx(D,{...e,ref:o,trapFocus:t.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:P(e.onCloseAutoFocus,s=>{var i;s.preventDefault(),r.current||(i=t.triggerRef.current)==null||i.focus()}),onPointerDownOutside:P(e.onPointerDownOutside,s=>{const i=s.detail.originalEvent,p=i.button===0&&i.ctrlKey===!0,u=i.button===2||p;r.current=u},{checkForDefaultPrevented:!1}),onFocusOutside:P(e.onFocusOutside,s=>s.preventDefault(),{checkForDefaultPrevented:!1})})})}),ne=l.forwardRef((e,n)=>{const t=d(v,e.__scopePopover),a=l.useRef(!1),o=l.useRef(!1);return c.jsx(D,{...e,ref:n,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:r=>{var s,i;(s=e.onCloseAutoFocus)==null||s.call(e,r),r.defaultPrevented||(a.current||(i=t.triggerRef.current)==null||i.focus(),r.preventDefault()),a.current=!1,o.current=!1},onInteractOutside:r=>{var p,u;(p=e.onInteractOutside)==null||p.call(e,r),r.defaultPrevented||(a.current=!0,r.detail.originalEvent.type==="pointerdown"&&(o.current=!0));const s=r.target;((u=t.triggerRef.current)==null?void 0:u.contains(s))&&r.preventDefault(),r.detail.originalEvent.type==="focusin"&&o.current&&r.preventDefault()}})}),D=l.forwardRef((e,n)=>{const{__scopePopover:t,trapFocus:a,onOpenAutoFocus:o,onCloseAutoFocus:r,disableOutsidePointerEvents:s,onEscapeKeyDown:i,onPointerDownOutside:p,onFocusOutside:u,onInteractOutside:h,...C}=e,f=d(v,t),x=g(t);return Z(),c.jsx(Q,{asChild:!0,loop:!0,trapped:a,onMountAutoFocus:o,onUnmountAutoFocus:r,children:c.jsx(X,{asChild:!0,disableOutsidePointerEvents:s,onInteractOutside:h,onEscapeKeyDown:i,onPointerDownOutside:p,onFocusOutside:u,onDismiss:()=>f.onOpenChange(!1),children:c.jsx(Y,{"data-state":I(f.open),role:"dialog",id:f.contentId,...x,...C,ref:n,style:{...C.style,"--radix-popover-content-transform-origin":"var(--radix-popper-transform-origin)","--radix-popover-content-available-width":"var(--radix-popper-available-width)","--radix-popover-content-available-height":"var(--radix-popper-available-height)","--radix-popover-trigger-width":"var(--radix-popper-anchor-width)","--radix-popover-trigger-height":"var(--radix-popper-anchor-height)"}})})})}),k="PopoverClose",ae=l.forwardRef((e,n)=>{const{__scopePopover:t,...a}=e,o=d(k,t);return c.jsx(O.button,{type:"button",...a,ref:n,onClick:P(e.onClick,()=>o.onOpenChange(!1))})});ae.displayName=k;var se="PopoverArrow",ce=l.forwardRef((e,n)=>{const{__scopePopover:t,...a}=e,o=g(t);return c.jsx(q,{...o,...a,ref:n})});ce.displayName=se;function I(e){return e?"open":"closed"}var ie=j,ve=y,le=S,pe=M,$=T;const Pe=ie,ge=le,ue=l.forwardRef(({className:e,sideOffset:n=8,align:t="start",...a},o)=>c.jsx(pe,{children:c.jsx($,{ref:o,sideOffset:n,align:t,className:B("z-[var(--z-popover,50)] w-72 overflow-hidden rounded-2xl border border-gray-200/50 bg-white p-4 shadow-lg animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",e),...a})}));ue.displayName=$.displayName;export{ve as A,$ as C,pe as P,ie as R,le as T,Pe as a,ge as b,ue as c};
@@ -1 +1 @@
1
- import{r as c,j as e,e as M}from"./vendor-DJt0Azq5.js";import{a6 as O,a7 as R,a8 as I,a9 as B,aa as _,C as u,a3 as h,a4 as x,t as s,a5 as m,E as p,B as j,I as l}from"./index-BsL1YIJ1.js";import{L as o}from"./label-CDSYExvV.js";import{S as G}from"./switch-CJRPF2V6.js";import{P as V,a as W}from"./page-layout-BMCVAnQM.js";const q=8;function A(r){return r.trim().length>=q}function L(r,n){return r!==n?(M.error(s("authPasswordMismatch")),!1):!0}function z(){const r=O(),n=R(),S=I(),g=B(),y=_(),[f,U]=c.useState(""),[i,N]=c.useState(""),[w,b]=c.useState(""),[d,v]=c.useState(""),[P,C]=c.useState(""),t=r.data,E=f.trim().length>0&&A(i)&&i===w&&!n.isPending,D=A(d)&&d===P&&!g.isPending,T=async()=>{if(L(i,w))try{await n.mutateAsync({username:f.trim(),password:i}),N(""),b("")}catch{}},F=async()=>{if(L(d,P))try{await g.mutateAsync({password:d}),v(""),C("")}catch{}},H=async a=>{try{await S.mutateAsync({enabled:a})}catch{}},k=async()=>{try{await y.mutateAsync()}catch{}};return r.isLoading&&!t?e.jsxs(u,{children:[e.jsxs(h,{children:[e.jsx(x,{children:s("authSecurityTitle")}),e.jsx(m,{children:s("authSecurityDescription")})]}),e.jsx(p,{className:"text-sm text-gray-500",children:s("loading")})]}):r.isError||!t?e.jsxs(u,{children:[e.jsxs(h,{children:[e.jsx(x,{children:s("authSecurityTitle")}),e.jsx(m,{children:s("authSecurityDescription")})]}),e.jsxs(p,{className:"space-y-4",children:[e.jsx("p",{className:"text-sm text-gray-500",children:s("authStatusLoadFailed")}),e.jsx(j,{variant:"outline",onClick:()=>{r.refetch()},children:s("authRetryStatus")})]})]}):t.configured?e.jsxs(u,{children:[e.jsxs(h,{children:[e.jsx(x,{children:s("authSecurityTitle")}),e.jsx(m,{children:s("authSecurityDescription")})]}),e.jsxs(p,{className:"space-y-6",children:[e.jsxs("div",{className:"rounded-xl border border-gray-200 p-4",children:[e.jsxs("div",{className:"flex flex-col gap-4 md:flex-row md:items-start md:justify-between",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm font-medium text-gray-900",children:s("authStatusLabel")}),e.jsx("p",{className:"text-sm text-gray-600",children:s("authStatusConfiguredUser").replace("{username}",t.username??"")}),e.jsx("p",{className:"text-xs text-gray-500",children:s("authUsernameFixedHelp")})]}),e.jsx("span",{className:"inline-flex items-center rounded-full bg-gray-100 px-3 py-1 text-xs font-medium text-gray-700",children:t.enabled?s("enabled"):s("disabled")})]}),e.jsxs("div",{className:"mt-4 flex flex-col gap-4 border-t border-gray-200 pt-4 md:flex-row md:items-center md:justify-between",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm font-medium text-gray-900",children:s("authEnableLabel")}),e.jsx("p",{className:"text-xs text-gray-500",children:t.enabled?s("authEnableOnHelp"):s("authEnableOffHelp")})]}),e.jsx(G,{checked:t.enabled,disabled:S.isPending,onCheckedChange:a=>{H(a)}})]})]}),e.jsxs("div",{className:"rounded-xl border border-gray-200 p-4 space-y-4",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm font-medium text-gray-900",children:s("authPasswordSectionTitle")}),e.jsx("p",{className:"text-xs text-gray-500",children:s("authPasswordSectionDescription")})]}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"auth-password-next",children:s("authPassword")}),e.jsx(l,{id:"auth-password-next",type:"password",value:d,onChange:a=>v(a.target.value),placeholder:s("authPasswordPlaceholder")})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"auth-password-confirm",children:s("authConfirmPassword")}),e.jsx(l,{id:"auth-password-confirm",type:"password",value:P,onChange:a=>C(a.target.value),placeholder:s("authConfirmPasswordPlaceholder")})]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx(j,{type:"button",disabled:!D,onClick:()=>void F(),children:g.isPending?s("authPasswordUpdating"):s("authPasswordAction")}),t.enabled&&t.authenticated?e.jsx(j,{type:"button",variant:"outline",disabled:y.isPending,onClick:()=>void k(),children:y.isPending?s("authLoggingOut"):s("authLogoutAction")}):null]}),e.jsx("p",{className:"text-xs text-gray-500",children:s("authSessionMemoryNotice")})]})]})]}):e.jsxs(u,{children:[e.jsxs(h,{children:[e.jsx(x,{children:s("authSecurityTitle")}),e.jsx(m,{children:s("authSecurityDescription")})]}),e.jsxs(p,{className:"space-y-5",children:[e.jsxs("div",{className:"rounded-xl border border-dashed border-gray-200 bg-gray-50/70 p-4",children:[e.jsx("p",{className:"text-sm font-medium text-gray-900",children:s("authSetupTitle")}),e.jsx("p",{className:"mt-1 text-sm text-gray-500",children:s("authSetupDescription")})]}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"auth-setup-username",children:s("authUsername")}),e.jsx(l,{id:"auth-setup-username",value:f,onChange:a=>U(a.target.value),placeholder:s("authUsernamePlaceholder")})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"auth-setup-password",children:s("authPassword")}),e.jsx(l,{id:"auth-setup-password",type:"password",value:i,onChange:a=>N(a.target.value),placeholder:s("authPasswordPlaceholder")})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"auth-setup-confirm",children:s("authConfirmPassword")}),e.jsx(l,{id:"auth-setup-confirm",type:"password",value:w,onChange:a=>b(a.target.value),placeholder:s("authConfirmPasswordPlaceholder")}),e.jsx("p",{className:"text-xs text-gray-500",children:s("authPasswordMinLengthHint")})]}),e.jsx(j,{type:"button",disabled:!E,onClick:()=>void T(),children:n.isPending?s("authSettingUp"):s("authSetupAction")})]})]})}function Z(){return e.jsxs(V,{className:"space-y-6",children:[e.jsx(W,{title:s("authSecurityTitle"),description:s("authSecurityDescription")}),e.jsx(z,{})]})}export{Z as SecurityConfig};
1
+ import{r as c,j as e,e as M}from"./vendor-DJt0Azq5.js";import{a6 as O,a7 as R,a8 as I,a9 as B,aa as _,C as u,a3 as h,a4 as x,t as s,a5 as m,E as p,B as j,I as l}from"./index-D45Vnh0I.js";import{L as o}from"./label-D8x2fgJm.js";import{S as G}from"./switch-DizAKjZa.js";import{P as V,a as W}from"./page-layout-Bxdxpr9D.js";const q=8;function A(r){return r.trim().length>=q}function L(r,n){return r!==n?(M.error(s("authPasswordMismatch")),!1):!0}function z(){const r=O(),n=R(),S=I(),g=B(),y=_(),[f,U]=c.useState(""),[i,N]=c.useState(""),[w,b]=c.useState(""),[d,v]=c.useState(""),[P,C]=c.useState(""),t=r.data,E=f.trim().length>0&&A(i)&&i===w&&!n.isPending,D=A(d)&&d===P&&!g.isPending,T=async()=>{if(L(i,w))try{await n.mutateAsync({username:f.trim(),password:i}),N(""),b("")}catch{}},F=async()=>{if(L(d,P))try{await g.mutateAsync({password:d}),v(""),C("")}catch{}},H=async a=>{try{await S.mutateAsync({enabled:a})}catch{}},k=async()=>{try{await y.mutateAsync()}catch{}};return r.isLoading&&!t?e.jsxs(u,{children:[e.jsxs(h,{children:[e.jsx(x,{children:s("authSecurityTitle")}),e.jsx(m,{children:s("authSecurityDescription")})]}),e.jsx(p,{className:"text-sm text-gray-500",children:s("loading")})]}):r.isError||!t?e.jsxs(u,{children:[e.jsxs(h,{children:[e.jsx(x,{children:s("authSecurityTitle")}),e.jsx(m,{children:s("authSecurityDescription")})]}),e.jsxs(p,{className:"space-y-4",children:[e.jsx("p",{className:"text-sm text-gray-500",children:s("authStatusLoadFailed")}),e.jsx(j,{variant:"outline",onClick:()=>{r.refetch()},children:s("authRetryStatus")})]})]}):t.configured?e.jsxs(u,{children:[e.jsxs(h,{children:[e.jsx(x,{children:s("authSecurityTitle")}),e.jsx(m,{children:s("authSecurityDescription")})]}),e.jsxs(p,{className:"space-y-6",children:[e.jsxs("div",{className:"rounded-xl border border-gray-200 p-4",children:[e.jsxs("div",{className:"flex flex-col gap-4 md:flex-row md:items-start md:justify-between",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm font-medium text-gray-900",children:s("authStatusLabel")}),e.jsx("p",{className:"text-sm text-gray-600",children:s("authStatusConfiguredUser").replace("{username}",t.username??"")}),e.jsx("p",{className:"text-xs text-gray-500",children:s("authUsernameFixedHelp")})]}),e.jsx("span",{className:"inline-flex items-center rounded-full bg-gray-100 px-3 py-1 text-xs font-medium text-gray-700",children:t.enabled?s("enabled"):s("disabled")})]}),e.jsxs("div",{className:"mt-4 flex flex-col gap-4 border-t border-gray-200 pt-4 md:flex-row md:items-center md:justify-between",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm font-medium text-gray-900",children:s("authEnableLabel")}),e.jsx("p",{className:"text-xs text-gray-500",children:t.enabled?s("authEnableOnHelp"):s("authEnableOffHelp")})]}),e.jsx(G,{checked:t.enabled,disabled:S.isPending,onCheckedChange:a=>{H(a)}})]})]}),e.jsxs("div",{className:"rounded-xl border border-gray-200 p-4 space-y-4",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm font-medium text-gray-900",children:s("authPasswordSectionTitle")}),e.jsx("p",{className:"text-xs text-gray-500",children:s("authPasswordSectionDescription")})]}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"auth-password-next",children:s("authPassword")}),e.jsx(l,{id:"auth-password-next",type:"password",value:d,onChange:a=>v(a.target.value),placeholder:s("authPasswordPlaceholder")})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"auth-password-confirm",children:s("authConfirmPassword")}),e.jsx(l,{id:"auth-password-confirm",type:"password",value:P,onChange:a=>C(a.target.value),placeholder:s("authConfirmPasswordPlaceholder")})]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx(j,{type:"button",disabled:!D,onClick:()=>void F(),children:g.isPending?s("authPasswordUpdating"):s("authPasswordAction")}),t.enabled&&t.authenticated?e.jsx(j,{type:"button",variant:"outline",disabled:y.isPending,onClick:()=>void k(),children:y.isPending?s("authLoggingOut"):s("authLogoutAction")}):null]}),e.jsx("p",{className:"text-xs text-gray-500",children:s("authSessionMemoryNotice")})]})]})]}):e.jsxs(u,{children:[e.jsxs(h,{children:[e.jsx(x,{children:s("authSecurityTitle")}),e.jsx(m,{children:s("authSecurityDescription")})]}),e.jsxs(p,{className:"space-y-5",children:[e.jsxs("div",{className:"rounded-xl border border-dashed border-gray-200 bg-gray-50/70 p-4",children:[e.jsx("p",{className:"text-sm font-medium text-gray-900",children:s("authSetupTitle")}),e.jsx("p",{className:"mt-1 text-sm text-gray-500",children:s("authSetupDescription")})]}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"auth-setup-username",children:s("authUsername")}),e.jsx(l,{id:"auth-setup-username",value:f,onChange:a=>U(a.target.value),placeholder:s("authUsernamePlaceholder")})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"auth-setup-password",children:s("authPassword")}),e.jsx(l,{id:"auth-setup-password",type:"password",value:i,onChange:a=>N(a.target.value),placeholder:s("authPasswordPlaceholder")})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"auth-setup-confirm",children:s("authConfirmPassword")}),e.jsx(l,{id:"auth-setup-confirm",type:"password",value:w,onChange:a=>b(a.target.value),placeholder:s("authConfirmPasswordPlaceholder")}),e.jsx("p",{className:"text-xs text-gray-500",children:s("authPasswordMinLengthHint")})]}),e.jsx(j,{type:"button",disabled:!E,onClick:()=>void T(),children:n.isPending?s("authSettingUp"):s("authSetupAction")})]})]})}function Z(){return e.jsxs(V,{className:"space-y-6",children:[e.jsx(W,{title:s("authSecurityTitle"),description:s("authSecurityDescription")}),e.jsx(z,{})]})}export{Z as SecurityConfig};
@@ -1 +1 @@
1
- import{j as t}from"./vendor-DJt0Azq5.js";import{c as o}from"./index-BsL1YIJ1.js";function m({className:e,...s}){return t.jsx("div",{className:o("animate-pulse rounded-md bg-slate-200",e),...s})}export{m as S};
1
+ import{j as t}from"./vendor-DJt0Azq5.js";import{c as o}from"./index-D45Vnh0I.js";function m({className:e,...s}){return t.jsx("div",{className:o("animate-pulse rounded-md bg-slate-200",e),...s})}export{m as S};
@@ -1 +1 @@
1
- import{j as e}from"./vendor-DJt0Azq5.js";import{c as a}from"./index-BsL1YIJ1.js";const n={active:{dot:"bg-emerald-500",text:"text-emerald-600",bg:"bg-emerald-50"},ready:{dot:"bg-emerald-500",text:"text-emerald-600",bg:"bg-emerald-50"},inactive:{dot:"bg-gray-300",text:"text-gray-400",bg:"bg-gray-100/80"},setup:{dot:"bg-gray-300",text:"text-gray-400",bg:"bg-gray-100/80"},warning:{dot:"bg-amber-400",text:"text-amber-600",bg:"bg-amber-50"}};function m({status:r,label:s,className:g}){const t=n[r];return e.jsxs("div",{className:a("inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap rounded-full px-2 py-0.5",t.bg,g),children:[e.jsx("span",{className:a("h-1.5 w-1.5 rounded-full",t.dot)}),e.jsx("span",{className:a("text-[11px] font-medium",t.text),children:s})]})}export{m as S};
1
+ import{j as e}from"./vendor-DJt0Azq5.js";import{c as a}from"./index-D45Vnh0I.js";const n={active:{dot:"bg-emerald-500",text:"text-emerald-600",bg:"bg-emerald-50"},ready:{dot:"bg-emerald-500",text:"text-emerald-600",bg:"bg-emerald-50"},inactive:{dot:"bg-gray-300",text:"text-gray-400",bg:"bg-gray-100/80"},setup:{dot:"bg-gray-300",text:"text-gray-400",bg:"bg-gray-100/80"},warning:{dot:"bg-amber-400",text:"text-amber-600",bg:"bg-amber-50"}};function m({status:r,label:s,className:g}){const t=n[r];return e.jsxs("div",{className:a("inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap rounded-full px-2 py-0.5",t.bg,g),children:[e.jsx("span",{className:a("h-1.5 w-1.5 rounded-full",t.dot)}),e.jsx("span",{className:a("text-[11px] font-medium",t.text),children:s})]})}export{m as S};
@@ -1 +1 @@
1
- import{r as e,j as i}from"./vendor-DJt0Azq5.js";import{c as t}from"./index-BsL1YIJ1.js";const l=e.forwardRef(({className:o,checked:r=!1,onCheckedChange:s,...a},n)=>i.jsx("button",{type:"button",role:"switch","aria-checked":r,ref:n,className:t("peer inline-flex h-[22px] w-10 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors duration-fast focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-white disabled:cursor-not-allowed disabled:opacity-50",r?"bg-primary":"bg-gray-200/80 hover:bg-gray-300/80",o),onClick:()=>s==null?void 0:s(!r),...a,children:i.jsx("span",{className:t("pointer-events-none block h-5 w-5 rounded-full bg-white shadow-md ring-0 transition-transform duration-fast",r?"translate-x-5":"translate-x-0")})}));l.displayName="Switch";export{l as S};
1
+ import{r as e,j as i}from"./vendor-DJt0Azq5.js";import{c as t}from"./index-D45Vnh0I.js";const l=e.forwardRef(({className:o,checked:r=!1,onCheckedChange:s,...a},n)=>i.jsx("button",{type:"button",role:"switch","aria-checked":r,ref:n,className:t("peer inline-flex h-[22px] w-10 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors duration-fast focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-white disabled:cursor-not-allowed disabled:opacity-50",r?"bg-primary":"bg-gray-200/80 hover:bg-gray-300/80",o),onClick:()=>s==null?void 0:s(!r),...a,children:i.jsx("span",{className:t("pointer-events-none block h-5 w-5 rounded-full bg-white shadow-md ring-0 transition-transform duration-fast",r?"translate-x-5":"translate-x-0")})}));l.displayName="Switch";export{l as S};
@@ -1 +1 @@
1
- import{j as e}from"./vendor-DJt0Azq5.js";import{ap as m,c as a}from"./index-BsL1YIJ1.js";function c({tabs:s,activeTab:i,onChange:o,className:n}){return e.jsx("div",{className:a("flex items-center gap-6 border-b border-gray-200/60 mb-6",n),children:s.map(t=>{const r=i===t.id;return e.jsxs("button",{onClick:()=>o(t.id),className:a("relative pb-3 text-[14px] font-medium transition-all duration-fast flex items-center gap-1.5",r?"text-gray-900":"text-gray-600 hover:text-gray-900"),children:[t.label,t.count!==void 0&&e.jsx("span",{className:a("text-[11px] font-medium","text-gray-500"),children:m(t.count)}),r&&e.jsx("div",{className:"absolute bottom-0 left-0 right-0 h-[2px] bg-primary rounded-full"})]},t.id)})})}export{c as T};
1
+ import{j as e}from"./vendor-DJt0Azq5.js";import{ap as m,c as a}from"./index-D45Vnh0I.js";function c({tabs:s,activeTab:i,onChange:o,className:n}){return e.jsx("div",{className:a("flex items-center gap-6 border-b border-gray-200/60 mb-6",n),children:s.map(t=>{const r=i===t.id;return e.jsxs("button",{onClick:()=>o(t.id),className:a("relative pb-3 text-[14px] font-medium transition-all duration-fast flex items-center gap-1.5",r?"text-gray-900":"text-gray-600 hover:text-gray-900"),children:[t.label,t.count!==void 0&&e.jsx("span",{className:a("text-[11px] font-medium","text-gray-500"),children:m(t.count)}),r&&e.jsx("div",{className:"absolute bottom-0 left-0 right-0 h-[2px] bg-primary rounded-full"})]},t.id)})})}export{c as T};
@@ -1 +1 @@
1
- import{j as a,r as t}from"./vendor-DJt0Azq5.js";import{aj as C,ak as p,al as h,am as x,an as g,ao as j,B as d,t as r}from"./index-BsL1YIJ1.js";const D=({open:l,onOpenChange:i,title:c,description:o,confirmLabel:s=r("confirm"),cancelLabel:e=r("cancel"),variant:n="default",onConfirm:u,onCancel:f})=>{const m=()=>{u(),i(!1)},v=()=>{f(),i(!1)};return a.jsx(C,{open:l,onOpenChange:i,children:a.jsxs(p,{className:"[&>:last-child]:hidden",onCloseAutoFocus:b=>b.preventDefault(),children:[a.jsxs(h,{children:[a.jsx(x,{children:c}),o?a.jsx(g,{children:o}):null]}),a.jsxs(j,{className:"gap-2 sm:gap-0",children:[a.jsx(d,{type:"button",variant:"outline",onClick:v,children:e}),a.jsx(d,{type:"button",variant:n==="destructive"?"destructive":"default",onClick:m,children:s})]})]})})},L={open:!1,title:"",description:"",confirmLabel:r("confirm"),cancelLabel:r("cancel"),variant:"default",resolve:null};function y(){const[l,i]=t.useState(L),c=t.useCallback(e=>new Promise(n=>{i({open:!0,title:e.title,description:e.description??"",confirmLabel:e.confirmLabel??r("confirm"),cancelLabel:e.cancelLabel??r("cancel"),variant:e.variant??"default",resolve:u=>{n(u),i(f=>({...f,open:!1,resolve:null}))}})}),[]),o=t.useCallback(e=>{i(n=>(!e&&n.resolve&&n.resolve(!1),{...n,open:e,resolve:e?n.resolve:null}))},[]),s=t.useCallback(()=>a.jsx(D,{open:l.open,onOpenChange:o,title:l.title,description:l.description||void 0,confirmLabel:l.confirmLabel,cancelLabel:l.cancelLabel,variant:l.variant,onConfirm:()=>{var e;return(e=l.resolve)==null?void 0:e.call(l,!0)},onCancel:()=>{var e;return(e=l.resolve)==null?void 0:e.call(l,!1)}}),[l,o]);return{confirm:c,ConfirmDialog:s}}export{y as u};
1
+ import{j as a,r as t}from"./vendor-DJt0Azq5.js";import{aj as C,ak as p,al as h,am as x,an as g,ao as j,B as d,t as r}from"./index-D45Vnh0I.js";const D=({open:l,onOpenChange:i,title:c,description:o,confirmLabel:s=r("confirm"),cancelLabel:e=r("cancel"),variant:n="default",onConfirm:u,onCancel:f})=>{const m=()=>{u(),i(!1)},v=()=>{f(),i(!1)};return a.jsx(C,{open:l,onOpenChange:i,children:a.jsxs(p,{className:"[&>:last-child]:hidden",onCloseAutoFocus:b=>b.preventDefault(),children:[a.jsxs(h,{children:[a.jsx(x,{children:c}),o?a.jsx(g,{children:o}):null]}),a.jsxs(j,{className:"gap-2 sm:gap-0",children:[a.jsx(d,{type:"button",variant:"outline",onClick:v,children:e}),a.jsx(d,{type:"button",variant:n==="destructive"?"destructive":"default",onClick:m,children:s})]})]})})},L={open:!1,title:"",description:"",confirmLabel:r("confirm"),cancelLabel:r("cancel"),variant:"default",resolve:null};function y(){const[l,i]=t.useState(L),c=t.useCallback(e=>new Promise(n=>{i({open:!0,title:e.title,description:e.description??"",confirmLabel:e.confirmLabel??r("confirm"),cancelLabel:e.cancelLabel??r("cancel"),variant:e.variant??"default",resolve:u=>{n(u),i(f=>({...f,open:!1,resolve:null}))}})}),[]),o=t.useCallback(e=>{i(n=>(!e&&n.resolve&&n.resolve(!1),{...n,open:e,resolve:e?n.resolve:null}))},[]),s=t.useCallback(()=>a.jsx(D,{open:l.open,onOpenChange:o,title:l.title,description:l.description||void 0,confirmLabel:l.confirmLabel,cancelLabel:l.cancelLabel,variant:l.variant,onConfirm:()=>{var e;return(e=l.resolve)==null?void 0:e.call(l,!0)},onCancel:()=>{var e;return(e=l.resolve)==null?void 0:e.call(l,!1)}}),[l,o]);return{confirm:c,ConfirmDialog:s}}export{y as u};
package/dist/index.html CHANGED
@@ -6,7 +6,7 @@
6
6
  <link rel="icon" type="image/svg+xml" href="/logo.svg" />
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
8
  <title>NextClaw - 系统配置</title>
9
- <script type="module" crossorigin src="/assets/index-BsL1YIJ1.js"></script>
9
+ <script type="module" crossorigin src="/assets/index-D45Vnh0I.js"></script>
10
10
  <link rel="modulepreload" crossorigin href="/assets/vendor-DJt0Azq5.js">
11
11
  <link rel="stylesheet" crossorigin href="/assets/index-C63mHRbE.css">
12
12
  </head>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/ui",
3
- "version": "0.9.17",
3
+ "version": "0.9.18",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -28,11 +28,11 @@
28
28
  "tailwind-merge": "^2.5.4",
29
29
  "zod": "^3.23.8",
30
30
  "zustand": "^5.0.2",
31
- "@nextclaw/agent-chat": "0.1.2",
32
- "@nextclaw/agent-chat-ui": "0.2.2",
33
31
  "@nextclaw/ncp": "0.3.2",
34
32
  "@nextclaw/ncp-http-agent-client": "0.3.2",
35
- "@nextclaw/ncp-react": "0.3.3"
33
+ "@nextclaw/agent-chat": "0.1.2",
34
+ "@nextclaw/ncp-react": "0.3.3",
35
+ "@nextclaw/agent-chat-ui": "0.2.2"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@testing-library/react": "^16.3.0",
@@ -1,4 +1,9 @@
1
- import { buildChatSlashItems, buildSelectedSkillItems, buildSkillPickerModel } from '@/components/chat/adapters/chat-input-bar.adapter';
1
+ import {
2
+ buildChatSlashItems,
3
+ buildModelToolbarSelect,
4
+ buildSelectedSkillItems,
5
+ buildSkillPickerModel
6
+ } from '@/components/chat/adapters/chat-input-bar.adapter';
2
7
  import type { ChatSkillRecord } from '@/components/chat/adapters/chat-input-bar.adapter';
3
8
 
4
9
  function createSkillRecord(partial: Partial<ChatSkillRecord>): ChatSkillRecord {
@@ -78,3 +83,29 @@ describe('buildSkillPickerModel', () => {
78
83
  });
79
84
  });
80
85
  });
86
+
87
+ describe('buildModelToolbarSelect', () => {
88
+ it('falls back to the first available option when the selected model is missing', () => {
89
+ const onValueChange = vi.fn();
90
+ const select = buildModelToolbarSelect({
91
+ modelOptions: [
92
+ {
93
+ value: 'minimax/MiniMax-M2.7',
94
+ modelLabel: 'MiniMax-M2.7',
95
+ providerLabel: 'MiniMax'
96
+ }
97
+ ],
98
+ selectedModel: 'dashscope/qwen3-coder-next',
99
+ isModelOptionsLoading: false,
100
+ hasModelOptions: true,
101
+ onValueChange,
102
+ texts: {
103
+ modelSelectPlaceholder: 'Select model',
104
+ modelNoOptionsLabel: 'No models'
105
+ }
106
+ });
107
+
108
+ expect(select.value).toBe('minimax/MiniMax-M2.7');
109
+ expect(select.selectedLabel).toBe('MiniMax/MiniMax-M2.7');
110
+ });
111
+ });
@@ -238,13 +238,16 @@ export function buildModelToolbarSelect(params: {
238
238
  texts: Pick<ChatInputBarAdapterTexts, 'modelSelectPlaceholder' | 'modelNoOptionsLabel'>;
239
239
  }): ChatToolbarSelect {
240
240
  const selectedModelOption = params.modelOptions.find((option) => option.value === params.selectedModel);
241
+ const fallbackModelOption = params.modelOptions[0];
242
+ const resolvedModelOption = selectedModelOption ?? fallbackModelOption;
243
+ const resolvedValue = params.hasModelOptions ? resolvedModelOption?.value : undefined;
241
244
 
242
245
  return {
243
246
  key: 'model',
244
- value: params.hasModelOptions ? params.selectedModel : undefined,
247
+ value: resolvedValue,
245
248
  placeholder: params.texts.modelSelectPlaceholder,
246
- selectedLabel: selectedModelOption
247
- ? `${selectedModelOption.providerLabel}/${selectedModelOption.modelLabel}`
249
+ selectedLabel: resolvedModelOption
250
+ ? `${resolvedModelOption.providerLabel}/${resolvedModelOption.modelLabel}`
248
251
  : undefined,
249
252
  icon: 'sparkles',
250
253
  options: params.modelOptions.map((option) => ({
@@ -1,25 +1,25 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
1
2
  import { createNcpAppClientFetch } from '@/components/chat/ncp/ncp-app-client-fetch';
2
3
 
3
- const mocks = vi.hoisted(() => ({
4
- request: vi.fn(),
5
- openStream: vi.fn()
6
- }));
7
-
8
- vi.mock('@/transport', () => ({
9
- appClient: {
10
- request: mocks.request,
11
- openStream: mocks.openStream
12
- }
13
- }));
4
+ const fetchMock = vi.fn<typeof fetch>();
14
5
 
15
6
  describe('ncp-app-client-fetch', () => {
16
7
  beforeEach(() => {
17
- mocks.request.mockReset();
18
- mocks.openStream.mockReset();
8
+ fetchMock.mockReset();
9
+ vi.stubGlobal('fetch', fetchMock);
10
+ });
11
+
12
+ afterEach(() => {
13
+ vi.unstubAllGlobals();
19
14
  });
20
15
 
21
- it('routes JSON requests through appClient.request', async () => {
22
- mocks.request.mockResolvedValue({ stopped: true });
16
+ it('keeps native fetch semantics and only injects credentials', async () => {
17
+ fetchMock.mockResolvedValue(new Response(JSON.stringify({ ok: true }), {
18
+ status: 200,
19
+ headers: {
20
+ 'content-type': 'application/json'
21
+ }
22
+ }));
23
23
  const fetchImpl = createNcpAppClientFetch();
24
24
 
25
25
  const response = await fetchImpl('http://127.0.0.1:55667/api/ncp/agent/abort', {
@@ -31,22 +31,40 @@ describe('ncp-app-client-fetch', () => {
31
31
  body: JSON.stringify({ sessionId: 's1' })
32
32
  });
33
33
 
34
- expect(mocks.request).toHaveBeenCalledWith({
34
+ expect(fetchMock).toHaveBeenCalledWith('http://127.0.0.1:55667/api/ncp/agent/abort', {
35
35
  method: 'POST',
36
- path: '/api/ncp/agent/abort',
37
- body: { sessionId: 's1' }
36
+ headers: {
37
+ accept: 'application/json',
38
+ 'content-type': 'application/json'
39
+ },
40
+ body: JSON.stringify({ sessionId: 's1' }),
41
+ credentials: 'include'
38
42
  });
39
43
  expect(response.ok).toBe(true);
44
+ expect(await response.json()).toEqual({ ok: true });
40
45
  });
41
46
 
42
- it('re-encodes appClient stream events as SSE frames', async () => {
43
- mocks.openStream.mockImplementation(({ onEvent }) => {
44
- onEvent({ name: 'ncp-event', payload: { type: 'message.chunk', payload: { text: 'hello' } } });
45
- return {
46
- finished: Promise.resolve(undefined),
47
- cancel: vi.fn()
48
- };
49
- });
47
+ it('does not synthesize fake HTTP 500 responses for fetch failures', async () => {
48
+ fetchMock.mockRejectedValue(new Error('Failed to fetch'));
49
+ const fetchImpl = createNcpAppClientFetch();
50
+
51
+ await expect(fetchImpl('http://127.0.0.1:55667/api/ncp/agent/abort', {
52
+ method: 'POST',
53
+ headers: {
54
+ accept: 'application/json',
55
+ 'content-type': 'application/json'
56
+ },
57
+ body: JSON.stringify({ sessionId: 's1' })
58
+ })).rejects.toThrow('Failed to fetch');
59
+ });
60
+
61
+ it('preserves native SSE request headers', async () => {
62
+ fetchMock.mockResolvedValue(new Response('event: ncp-event\ndata: {"ok":true}\n\n', {
63
+ status: 200,
64
+ headers: {
65
+ 'content-type': 'text/event-stream'
66
+ }
67
+ }));
50
68
  const fetchImpl = createNcpAppClientFetch();
51
69
 
52
70
  const response = await fetchImpl('http://127.0.0.1:55667/api/ncp/agent/stream?sessionId=s1', {
@@ -55,15 +73,14 @@ describe('ncp-app-client-fetch', () => {
55
73
  accept: 'text/event-stream'
56
74
  }
57
75
  });
58
- const text = await response.text();
59
76
 
60
- expect(mocks.openStream).toHaveBeenCalledWith({
77
+ expect(fetchMock).toHaveBeenCalledWith('http://127.0.0.1:55667/api/ncp/agent/stream?sessionId=s1', {
61
78
  method: 'GET',
62
- path: '/api/ncp/agent/stream?sessionId=s1',
63
- signal: undefined,
64
- onEvent: expect.any(Function)
79
+ headers: {
80
+ accept: 'text/event-stream'
81
+ },
82
+ credentials: 'include'
65
83
  });
66
- expect(text).toContain('event: ncp-event');
67
- expect(text).toContain('"text":"hello"');
84
+ expect(await response.text()).toContain('event: ncp-event');
68
85
  });
69
86
  });
@@ -1,127 +1,9 @@
1
- import { API_BASE } from '@/api/api-base';
2
- import { appClient } from '@/transport';
3
-
4
1
  type FetchLike = typeof fetch;
5
2
 
6
3
  export function createNcpAppClientFetch(): FetchLike {
7
- return async (input, init) => {
8
- const request = toRequestSnapshot(input, init);
9
- if (isSseRequest(request)) {
10
- return createSseResponse(request);
11
- }
12
-
13
- try {
14
- const data = await appClient.request<unknown>({
15
- method: request.method,
16
- path: request.path,
17
- ...(request.body !== undefined ? { body: request.body } : {})
18
- });
19
- return new Response(JSON.stringify(data ?? {}), {
20
- status: 200,
21
- headers: {
22
- 'content-type': 'application/json'
23
- }
24
- });
25
- } catch (error) {
26
- return new Response(error instanceof Error ? error.message : String(error), {
27
- status: 500,
28
- headers: {
29
- 'content-type': 'text/plain; charset=utf-8'
30
- }
31
- });
32
- }
33
- };
34
- }
35
-
36
- type RequestSnapshot = {
37
- method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
38
- path: string;
39
- body?: unknown;
40
- signal?: AbortSignal;
41
- headers: Headers;
42
- };
43
-
44
- function toRequestSnapshot(input: URL | string | Request, init?: RequestInit): RequestSnapshot {
45
- const request = input instanceof Request ? input : null;
46
- const url = new URL(
47
- typeof input === 'string'
48
- ? input
49
- : input instanceof URL
50
- ? input.toString()
51
- : input.url,
52
- API_BASE
53
- );
54
- const headers = new Headers(init?.headers ?? request?.headers);
55
- const method = ((init?.method ?? request?.method ?? 'GET').toUpperCase()) as RequestSnapshot['method'];
56
- return {
57
- method,
58
- path: `${url.pathname}${url.search}`,
59
- body: parseRequestBody(init?.body),
60
- signal: init?.signal ?? request?.signal ?? undefined,
61
- headers
62
- };
63
- }
64
-
65
- function parseRequestBody(body: BodyInit | null | undefined): unknown {
66
- if (body === undefined || body === null) {
67
- return undefined;
68
- }
69
- if (typeof body === 'string') {
70
- try {
71
- return JSON.parse(body);
72
- } catch {
73
- return body;
74
- }
75
- }
76
- return body;
77
- }
78
-
79
- function isSseRequest(request: RequestSnapshot): boolean {
80
- const accept = request.headers.get('accept')?.toLowerCase() ?? '';
81
- return accept.includes('text/event-stream');
82
- }
83
-
84
- function createSseResponse(request: RequestSnapshot): Response {
85
- const encoder = new TextEncoder();
86
- let session: ReturnType<typeof appClient.openStream<unknown>> | null = null;
87
-
88
- const stream = new ReadableStream<Uint8Array>({
89
- start(controller) {
90
- session = appClient.openStream<unknown>({
91
- method: request.method === 'GET' ? 'GET' : 'POST',
92
- path: request.path,
93
- ...(request.body !== undefined ? { body: request.body } : {}),
94
- signal: request.signal,
95
- onEvent: (event) => {
96
- controller.enqueue(encoder.encode(encodeSseFrame(event.name, event.payload)));
97
- }
98
- });
99
-
100
- void session.finished
101
- .then(() => {
102
- controller.close();
103
- })
104
- .catch((error) => {
105
- controller.enqueue(encoder.encode(encodeSseFrame('error', {
106
- message: error instanceof Error ? error.message : String(error)
107
- })));
108
- controller.close();
109
- });
110
- },
111
- cancel() {
112
- session?.cancel();
113
- }
114
- });
115
-
116
- return new Response(stream, {
117
- status: 200,
118
- headers: {
119
- 'content-type': 'text/event-stream'
120
- }
121
- });
122
- }
123
-
124
- function encodeSseFrame(event: string, payload: unknown): string {
125
- const data = payload === undefined ? '' : JSON.stringify(payload);
126
- return `event: ${event}\ndata: ${data}\n\n`;
4
+ return (input, init) =>
5
+ fetch(input, {
6
+ credentials: 'include',
7
+ ...init
8
+ });
127
9
  }
@@ -16,6 +16,14 @@ const modelOptions: ChatModelOption[] = [
16
16
  ];
17
17
 
18
18
  describe('filterModelOptionsBySessionType', () => {
19
+ it('keeps the full model catalog when the session type does not publish a supportedModels whitelist', () => {
20
+ expect(
21
+ filterModelOptionsBySessionType({
22
+ modelOptions
23
+ })
24
+ ).toEqual(modelOptions);
25
+ });
26
+
19
27
  it('keeps only session-type-supported models when the runtime publishes a filtered list', () => {
20
28
  expect(
21
29
  filterModelOptionsBySessionType({