@nextclaw/ui 0.9.10 → 0.9.11
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/CHANGELOG.md +6 -0
- package/dist/assets/{ChannelsList-BgJbR6E9.js → ChannelsList-Brc1qLSU.js} +1 -1
- package/dist/assets/{ChatPage-Bv9UJPse.js → ChatPage-DmGI776q.js} +1 -1
- package/dist/assets/{DocBrowser-Dw9BGO1m.js → DocBrowser-xLVf1p4L.js} +1 -1
- package/dist/assets/{LogoBadge-CLc2B6st.js → LogoBadge-CcTyimdr.js} +1 -1
- package/dist/assets/{MarketplacePage-ChqCNL7k.js → MarketplacePage-Bk-qXxyh.js} +1 -1
- package/dist/assets/{McpMarketplacePage-B3PF-7ED.js → McpMarketplacePage-gFqAYekc.js} +1 -1
- package/dist/assets/{ModelConfig-Dqz_NOow.js → ModelConfig-DnKNTuw6.js} +1 -1
- package/dist/assets/{ProvidersList-D2WaZShJ.js → ProvidersList-Cjr8EFu_.js} +1 -1
- package/dist/assets/{RemoteAccessPage-D_l9irp4.js → RemoteAccessPage-Rzi5a6Gc.js} +1 -1
- package/dist/assets/{RuntimeConfig-TDxQLuGy.js → RuntimeConfig-CttN--Tv.js} +1 -1
- package/dist/assets/{SearchConfig-gba64nGn.js → SearchConfig-D-GzinsL.js} +1 -1
- package/dist/assets/{SecretsConfig-DpL8wgly.js → SecretsConfig-BvqQq4Ds.js} +1 -1
- package/dist/assets/{SessionsConfig-CAODVTNW.js → SessionsConfig-DbtnLmI6.js} +1 -1
- package/dist/assets/{chat-message-CSG50nNb.js → chat-message-DYQjL1tD.js} +1 -1
- package/dist/assets/{index-DaEflNCE.js → index-ClLy_7T2.js} +5 -5
- package/dist/assets/{label-3T28q3PJ.js → label-DBSKOMGE.js} +1 -1
- package/dist/assets/{page-layout-BrXOQeua.js → page-layout-B5th9UzR.js} +1 -1
- package/dist/assets/{popover-BrBJjElY.js → popover-BEIWRoeP.js} +1 -1
- package/dist/assets/{security-config-oGAhN4Zf.js → security-config-D72JskP5.js} +1 -1
- package/dist/assets/{skeleton-CIPQUKo2.js → skeleton-B_Pn9x0i.js} +1 -1
- package/dist/assets/{status-dot-QL3hmT1d.js → status-dot-CU5ZpOn1.js} +1 -1
- package/dist/assets/{switch-Dbt2kUg2.js → switch-BdaXEtXk.js} +1 -1
- package/dist/assets/{tabs-custom-y5hdkzXk.js → tabs-custom-BVhSoteN.js} +1 -1
- package/dist/assets/{useConfirmDialog-B4zwBVbl.js → useConfirmDialog-Dugi9V-Z.js} +1 -1
- package/dist/index.html +1 -1
- package/package.json +4 -4
- package/src/api/config.ts +1 -4
- package/src/hooks/use-realtime-query-bridge.ts +77 -71
- package/src/transport/local.transport.ts +5 -123
- package/src/transport/remote.transport.ts +39 -74
- package/src/transport/sse-stream.ts +114 -0
- package/src/transport/transport-websocket-url.ts +24 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as s,j as o}from"./vendor-CmQZsDAE.js";import{c as t}from"./index-
|
|
1
|
+
import{r as s,j as o}from"./vendor-CmQZsDAE.js";import{c as t}from"./index-ClLy_7T2.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-CmQZsDAE.js";import{c as l}from"./index-
|
|
1
|
+
import{j as e}from"./vendor-CmQZsDAE.js";import{c as l}from"./index-ClLy_7T2.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,aJ as L,j as c,aK as z,aL as G,aM as A,aN as O,aO as P,aP as _,aQ as w,aR as b,aS as H,aT as K,aU as U,aV as V,aW as W,aX as Z,aY as J,aZ as Q,a_ as X,a$ as Y}from"./vendor-CmQZsDAE.js";import{c as q}from"./index-
|
|
1
|
+
import{r as l,aJ as L,j as c,aK as z,aL as G,aM as A,aN as O,aO as P,aP as _,aQ as w,aR as b,aS as H,aT as K,aU as U,aV as V,aW as W,aX as Z,aY as J,aZ as Q,a_ as X,a$ as Y}from"./vendor-CmQZsDAE.js";import{c as q}from"./index-ClLy_7T2.js";var m="Popover",[E]=K(m,[w]),g=w(),[B,d]=E(m),j=e=>{const{__scopePopover:a,children:t,open:n,defaultOpen:o,onOpenChange:r,modal:s=!1}=e,i=g(a),p=l.useRef(null),[u,h]=l.useState(!1),[C,f]=L({prop:n,defaultProp:o??!1,onChange:r,caller:m});return c.jsx(z,{...i,children:c.jsx(B,{scope:a,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,a)=>{const{__scopePopover:t,...n}=e,o=d(N,t),r=g(t),{onCustomAnchorAdd:s,onCustomAnchorRemove:i}=o;return l.useEffect(()=>(s(),()=>i()),[s,i]),c.jsx(_,{...r,...n,ref:a})});y.displayName=N;var F="PopoverTrigger",S=l.forwardRef((e,a)=>{const{__scopePopover:t,...n}=e,o=d(F,t),r=g(t),s=A(a,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),...n,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:a,forceMount:t,children:n,container:o}=e,r=d(R,a);return c.jsx(ee,{scope:a,forceMount:t,children:c.jsx(b,{present:t||r.open,children:c.jsx(H,{asChild:!0,container:o,children:n})})})};M.displayName=R;var v="PopoverContent",T=l.forwardRef((e,a)=>{const t=oe(v,e.__scopePopover),{forceMount:n=t.forceMount,...o}=e,r=d(v,e.__scopePopover);return c.jsx(b,{present:n||r.open,children:r.modal?c.jsx(re,{...o,ref:a}):c.jsx(ae,{...o,ref:a})})});T.displayName=v;var te=W("PopoverContent.RemoveScroll"),re=l.forwardRef((e,a)=>{const t=d(v,e.__scopePopover),n=l.useRef(null),o=A(a,n),r=l.useRef(!1);return l.useEffect(()=>{const s=n.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})})})}),ae=l.forwardRef((e,a)=>{const t=d(v,e.__scopePopover),n=l.useRef(!1),o=l.useRef(!1);return c.jsx(D,{...e,ref:a,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:r=>{var s,i;(s=e.onCloseAutoFocus)==null||s.call(e,r),r.defaultPrevented||(n.current||(i=t.triggerRef.current)==null||i.focus(),r.preventDefault()),n.current=!1,o.current=!1},onInteractOutside:r=>{var p,u;(p=e.onInteractOutside)==null||p.call(e,r),r.defaultPrevented||(n.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,a)=>{const{__scopePopover:t,trapFocus:n,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(J,{asChild:!0,loop:!0,trapped:n,onMountAutoFocus:o,onUnmountAutoFocus:r,children:c.jsx(Q,{asChild:!0,disableOutsidePointerEvents:s,onInteractOutside:h,onEscapeKeyDown:i,onPointerDownOutside:p,onFocusOutside:u,onDismiss:()=>f.onOpenChange(!1),children:c.jsx(X,{"data-state":I(f.open),role:"dialog",id:f.contentId,...x,...C,ref:a,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",ne=l.forwardRef((e,a)=>{const{__scopePopover:t,...n}=e,o=d(k,t);return c.jsx(O.button,{type:"button",...n,ref:a,onClick:P(e.onClick,()=>o.onOpenChange(!1))})});ne.displayName=k;var se="PopoverArrow",ce=l.forwardRef((e,a)=>{const{__scopePopover:t,...n}=e,o=g(t);return c.jsx(Y,{...o,...n,ref:a})});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:a=8,align:t="start",...n},o)=>c.jsx(pe,{children:c.jsx($,{ref:o,sideOffset:a,align:t,className:q("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),...n})}));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-CmQZsDAE.js";import{a5 as O,a6 as R,a7 as I,a8 as B,a9 as _,C as u,a2 as h,a3 as x,t as s,a4 as m,z as p,B as j,I as l}from"./index-
|
|
1
|
+
import{r as c,j as e,e as M}from"./vendor-CmQZsDAE.js";import{a5 as O,a6 as R,a7 as I,a8 as B,a9 as _,C as u,a2 as h,a3 as x,t as s,a4 as m,z as p,B as j,I as l}from"./index-ClLy_7T2.js";import{L as o}from"./label-DBSKOMGE.js";import{S as z}from"./switch-BdaXEtXk.js";import{P as G,a as V}from"./page-layout-B5th9UzR.js";const W=8;function A(r){return r.trim().length>=W}function L(r,n){return r!==n?(M.error(s("authPasswordMismatch")),!1):!0}function q(){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(z,{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(G,{className:"space-y-6",children:[e.jsx(V,{title:s("authSecurityTitle"),description:s("authSecurityDescription")}),e.jsx(q,{})]})}export{Z as SecurityConfig};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as t}from"./vendor-CmQZsDAE.js";import{c as o}from"./index-
|
|
1
|
+
import{j as t}from"./vendor-CmQZsDAE.js";import{c as o}from"./index-ClLy_7T2.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-CmQZsDAE.js";import{c as a}from"./index-
|
|
1
|
+
import{j as e}from"./vendor-CmQZsDAE.js";import{c as a}from"./index-ClLy_7T2.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-CmQZsDAE.js";import{c as t}from"./index-
|
|
1
|
+
import{r as e,j as i}from"./vendor-CmQZsDAE.js";import{c as t}from"./index-ClLy_7T2.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-CmQZsDAE.js";import{ap as m,c as a}from"./index-
|
|
1
|
+
import{j as e}from"./vendor-CmQZsDAE.js";import{ap as m,c as a}from"./index-ClLy_7T2.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-CmQZsDAE.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-
|
|
1
|
+
import{j as a,r as t}from"./vendor-CmQZsDAE.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-ClLy_7T2.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-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-ClLy_7T2.js"></script>
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/vendor-CmQZsDAE.js">
|
|
11
11
|
<link rel="stylesheet" crossorigin href="/assets/index-DfEAJJsA.css">
|
|
12
12
|
</head>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/ui",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.11",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"tailwind-merge": "^2.5.4",
|
|
28
28
|
"zod": "^3.23.8",
|
|
29
29
|
"zustand": "^5.0.2",
|
|
30
|
-
"@nextclaw/agent-chat": "0.1.1",
|
|
31
30
|
"@nextclaw/ncp-http-agent-client": "0.3.1",
|
|
31
|
+
"@nextclaw/agent-chat": "0.1.1",
|
|
32
|
+
"@nextclaw/ncp": "0.3.1",
|
|
32
33
|
"@nextclaw/agent-chat-ui": "0.2.1",
|
|
33
|
-
"@nextclaw/ncp-react": "0.3.2"
|
|
34
|
-
"@nextclaw/ncp": "0.3.1"
|
|
34
|
+
"@nextclaw/ncp-react": "0.3.2"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@testing-library/react": "^16.3.0",
|
package/src/api/config.ts
CHANGED
|
@@ -142,10 +142,7 @@ export async function fetchConfigSchema(): Promise<ConfigSchemaResponse> {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
// PUT /api/config/model
|
|
145
|
-
export async function updateModel(data: {
|
|
146
|
-
model: string;
|
|
147
|
-
workspace?: string;
|
|
148
|
-
}): Promise<{ model: string; workspace?: string }> {
|
|
145
|
+
export async function updateModel(data: { model: string; workspace?: string }): Promise<{ model: string; workspace?: string }> {
|
|
149
146
|
const response = await api.put<{ model: string; workspace?: string }>('/api/config/model', data);
|
|
150
147
|
if (!response.ok) {
|
|
151
148
|
throw new Error(response.error.message);
|
|
@@ -3,6 +3,9 @@ import { appClient } from '@/transport';
|
|
|
3
3
|
import { useUiStore } from '@/stores/ui.store';
|
|
4
4
|
import type { QueryClient } from '@tanstack/react-query';
|
|
5
5
|
|
|
6
|
+
type ConnectionStatus = 'connected' | 'disconnected' | 'connecting';
|
|
7
|
+
type SetConnectionStatus = (status: ConnectionStatus) => void;
|
|
8
|
+
|
|
6
9
|
function shouldInvalidateConfigQuery(configPath: string) {
|
|
7
10
|
const normalized = configPath.trim().toLowerCase();
|
|
8
11
|
if (!normalized) {
|
|
@@ -27,82 +30,85 @@ function invalidateMarketplaceQueries(queryClient: QueryClient | undefined, conf
|
|
|
27
30
|
}
|
|
28
31
|
}
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
queryClient.invalidateQueries({ queryKey: ['session-history'] });
|
|
46
|
-
queryClient.invalidateQueries({ queryKey: ['ncp-session-messages'] });
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
setConnectionStatus('connecting');
|
|
50
|
-
|
|
51
|
-
return appClient.subscribe((event) => {
|
|
52
|
-
if (event.type === 'connection.open') {
|
|
53
|
-
setConnectionStatus('connected');
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
33
|
+
function invalidateSessionQueries(queryClient: QueryClient | undefined, sessionKey?: string): void {
|
|
34
|
+
if (!queryClient) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
queryClient.invalidateQueries({ queryKey: ['sessions'] });
|
|
38
|
+
queryClient.invalidateQueries({ queryKey: ['ncp-sessions'] });
|
|
39
|
+
if (sessionKey && sessionKey.trim().length > 0) {
|
|
40
|
+
queryClient.invalidateQueries({ queryKey: ['session-history', sessionKey.trim()] });
|
|
41
|
+
queryClient.invalidateQueries({ queryKey: ['ncp-session-messages', sessionKey.trim()] });
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
queryClient.invalidateQueries({ queryKey: ['session-history'] });
|
|
45
|
+
queryClient.invalidateQueries({ queryKey: ['ncp-session-messages'] });
|
|
46
|
+
}
|
|
56
47
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
48
|
+
function handleConfigUpdatedEvent(queryClient: QueryClient | undefined, path: string): void {
|
|
49
|
+
if (queryClient && shouldInvalidateConfigQuery(path)) {
|
|
50
|
+
queryClient.invalidateQueries({ queryKey: ['config'] });
|
|
51
|
+
}
|
|
52
|
+
if (path.startsWith('session')) {
|
|
53
|
+
invalidateSessionQueries(queryClient);
|
|
54
|
+
}
|
|
55
|
+
invalidateMarketplaceQueries(queryClient, path);
|
|
56
|
+
}
|
|
61
57
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
function handleRunUpdatedEvent(queryClient: QueryClient | undefined, payload: { run: { sessionKey?: string; runId?: string } }): void {
|
|
59
|
+
if (!queryClient) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const { sessionKey, runId } = payload.run;
|
|
63
|
+
queryClient.invalidateQueries({ queryKey: ['chat-runs'] });
|
|
64
|
+
if (sessionKey) {
|
|
65
|
+
queryClient.invalidateQueries({ queryKey: ['sessions'] });
|
|
66
|
+
queryClient.invalidateQueries({ queryKey: ['session-history', sessionKey] });
|
|
67
|
+
} else {
|
|
68
|
+
queryClient.invalidateQueries({ queryKey: ['session-history'] });
|
|
69
|
+
}
|
|
70
|
+
if (runId) {
|
|
71
|
+
queryClient.invalidateQueries({ queryKey: ['chat-run', runId] });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
66
74
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
function handleRealtimeEvent(
|
|
76
|
+
queryClient: QueryClient | undefined,
|
|
77
|
+
setConnectionStatus: SetConnectionStatus,
|
|
78
|
+
event: Parameters<Parameters<typeof appClient.subscribe>[0]>[0]
|
|
79
|
+
): void {
|
|
80
|
+
if (event.type === 'connection.open') {
|
|
81
|
+
setConnectionStatus('connected');
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (event.type === 'connection.close' || event.type === 'connection.error') {
|
|
85
|
+
setConnectionStatus('disconnected');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (event.type === 'config.updated') {
|
|
89
|
+
const configPath = typeof event.payload?.path === 'string' ? event.payload.path : '';
|
|
90
|
+
handleConfigUpdatedEvent(queryClient, configPath);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (event.type === 'run.updated') {
|
|
94
|
+
handleRunUpdatedEvent(queryClient, event.payload);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (event.type === 'session.updated') {
|
|
98
|
+
invalidateSessionQueries(queryClient, event.payload.sessionKey);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (event.type === 'error') {
|
|
102
|
+
console.error('Realtime transport error:', event.payload.message);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
78
105
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
const sessionKey = event.payload.run.sessionKey;
|
|
84
|
-
const runId = event.payload.run.runId;
|
|
85
|
-
queryClient.invalidateQueries({ queryKey: ['chat-runs'] });
|
|
86
|
-
if (sessionKey) {
|
|
87
|
-
queryClient.invalidateQueries({ queryKey: ['sessions'] });
|
|
88
|
-
queryClient.invalidateQueries({ queryKey: ['session-history', sessionKey] });
|
|
89
|
-
} else {
|
|
90
|
-
queryClient.invalidateQueries({ queryKey: ['session-history'] });
|
|
91
|
-
}
|
|
92
|
-
if (runId) {
|
|
93
|
-
queryClient.invalidateQueries({ queryKey: ['chat-run', runId] });
|
|
94
|
-
}
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
106
|
+
export function useRealtimeQueryBridge(queryClient?: QueryClient) {
|
|
107
|
+
const { setConnectionStatus } = useUiStore();
|
|
97
108
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
setConnectionStatus('connecting');
|
|
102
111
|
|
|
103
|
-
|
|
104
|
-
console.error('Realtime transport error:', event.payload.message);
|
|
105
|
-
}
|
|
106
|
-
});
|
|
112
|
+
return appClient.subscribe((event) => handleRealtimeEvent(queryClient, setConnectionStatus, event));
|
|
107
113
|
}, [queryClient, setConnectionStatus]);
|
|
108
114
|
}
|
|
@@ -1,34 +1,11 @@
|
|
|
1
1
|
import { API_BASE, requestApiResponse } from '@/api/client';
|
|
2
2
|
import type { ApiResponse } from '@/api/types';
|
|
3
|
-
import type { AppEvent, AppTransport, RequestInput,
|
|
3
|
+
import type { AppEvent, AppTransport, RequestInput, StreamInput, StreamSession } from './transport.types';
|
|
4
|
+
import { readSseStreamResult } from './sse-stream';
|
|
5
|
+
import { resolveTransportWebSocketUrl } from './transport-websocket-url';
|
|
4
6
|
|
|
5
7
|
type EventHandler = (event: AppEvent) => void;
|
|
6
8
|
|
|
7
|
-
function toWebSocketUrl(base: string, path: string): string {
|
|
8
|
-
const normalizedBase = base.replace(/\/$/, '');
|
|
9
|
-
try {
|
|
10
|
-
const resolved = new URL(normalizedBase, window.location.origin);
|
|
11
|
-
const protocol =
|
|
12
|
-
resolved.protocol === 'https:'
|
|
13
|
-
? 'wss:'
|
|
14
|
-
: resolved.protocol === 'http:'
|
|
15
|
-
? 'ws:'
|
|
16
|
-
: resolved.protocol;
|
|
17
|
-
return `${protocol}//${resolved.host}${path}`;
|
|
18
|
-
} catch {
|
|
19
|
-
if (normalizedBase.startsWith('wss://') || normalizedBase.startsWith('ws://')) {
|
|
20
|
-
return `${normalizedBase}${path}`;
|
|
21
|
-
}
|
|
22
|
-
if (normalizedBase.startsWith('https://')) {
|
|
23
|
-
return `${normalizedBase.replace(/^https:/, 'wss:')}${path}`;
|
|
24
|
-
}
|
|
25
|
-
if (normalizedBase.startsWith('http://')) {
|
|
26
|
-
return `${normalizedBase.replace(/^http:/, 'ws:')}${path}`;
|
|
27
|
-
}
|
|
28
|
-
return `${normalizedBase}${path}`;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
9
|
function createTransportError(response: ApiResponse<unknown>, fallback: string): Error {
|
|
33
10
|
if (!response.ok) {
|
|
34
11
|
return new Error(response.error.message);
|
|
@@ -36,43 +13,6 @@ function createTransportError(response: ApiResponse<unknown>, fallback: string):
|
|
|
36
13
|
return new Error(fallback);
|
|
37
14
|
}
|
|
38
15
|
|
|
39
|
-
function parseSseFrame(frame: string): StreamEvent | null {
|
|
40
|
-
const lines = frame.split('\n');
|
|
41
|
-
let name = '';
|
|
42
|
-
const dataLines: string[] = [];
|
|
43
|
-
for (const raw of lines) {
|
|
44
|
-
const line = raw.trimEnd();
|
|
45
|
-
if (!line || line.startsWith(':')) {
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
if (line.startsWith('event:')) {
|
|
49
|
-
name = line.slice(6).trim();
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
if (line.startsWith('data:')) {
|
|
53
|
-
dataLines.push(line.slice(5).trimStart());
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
if (!name) {
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
let payload: unknown = undefined;
|
|
61
|
-
const data = dataLines.join('\n');
|
|
62
|
-
if (data) {
|
|
63
|
-
try {
|
|
64
|
-
payload = JSON.parse(data);
|
|
65
|
-
} catch {
|
|
66
|
-
payload = data;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return {
|
|
71
|
-
name,
|
|
72
|
-
payload
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
16
|
class LocalRealtimeGateway {
|
|
77
17
|
private socket: WebSocket | null = null;
|
|
78
18
|
private reconnectTimer: number | null = null;
|
|
@@ -168,7 +108,7 @@ export class LocalAppTransport implements AppTransport {
|
|
|
168
108
|
} = {}
|
|
169
109
|
) {
|
|
170
110
|
const apiBase = options.apiBase ?? API_BASE;
|
|
171
|
-
this.realtimeGateway = new LocalRealtimeGateway(
|
|
111
|
+
this.realtimeGateway = new LocalRealtimeGateway(resolveTransportWebSocketUrl(apiBase, options.wsPath ?? '/ws'));
|
|
172
112
|
}
|
|
173
113
|
|
|
174
114
|
async request<T>(input: RequestInput): Promise<T> {
|
|
@@ -209,69 +149,11 @@ export class LocalAppTransport implements AppTransport {
|
|
|
209
149
|
const text = await response.text();
|
|
210
150
|
throw new Error(text.trim() || `HTTP ${response.status}`);
|
|
211
151
|
}
|
|
212
|
-
|
|
213
|
-
const reader = response.body?.getReader();
|
|
214
|
-
if (!reader) {
|
|
215
|
-
throw new Error('SSE response body unavailable');
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const decoder = new TextDecoder();
|
|
219
|
-
let buffer = '';
|
|
220
|
-
let finalResult: unknown;
|
|
221
|
-
|
|
222
152
|
try {
|
|
223
|
-
|
|
224
|
-
const { value, done } = await reader.read();
|
|
225
|
-
if (done) {
|
|
226
|
-
break;
|
|
227
|
-
}
|
|
228
|
-
buffer += decoder.decode(value, { stream: true });
|
|
229
|
-
let boundary = buffer.indexOf('\n\n');
|
|
230
|
-
while (boundary !== -1) {
|
|
231
|
-
const frame = parseSseFrame(buffer.slice(0, boundary));
|
|
232
|
-
buffer = buffer.slice(boundary + 2);
|
|
233
|
-
if (frame) {
|
|
234
|
-
if (frame.name === 'final') {
|
|
235
|
-
finalResult = frame.payload;
|
|
236
|
-
} else if (frame.name === 'error') {
|
|
237
|
-
const errorPayload = frame.payload as { message?: string } | string | undefined;
|
|
238
|
-
const message = typeof errorPayload === 'string'
|
|
239
|
-
? errorPayload
|
|
240
|
-
: errorPayload?.message ?? 'chat stream failed';
|
|
241
|
-
throw new Error(message);
|
|
242
|
-
} else {
|
|
243
|
-
input.onEvent(frame);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
boundary = buffer.indexOf('\n\n');
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
if (buffer.trim()) {
|
|
251
|
-
const frame = parseSseFrame(buffer);
|
|
252
|
-
if (frame) {
|
|
253
|
-
if (frame.name === 'final') {
|
|
254
|
-
finalResult = frame.payload;
|
|
255
|
-
} else if (frame.name === 'error') {
|
|
256
|
-
const errorPayload = frame.payload as { message?: string } | string | undefined;
|
|
257
|
-
const message = typeof errorPayload === 'string'
|
|
258
|
-
? errorPayload
|
|
259
|
-
: errorPayload?.message ?? 'chat stream failed';
|
|
260
|
-
throw new Error(message);
|
|
261
|
-
} else {
|
|
262
|
-
input.onEvent(frame);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
153
|
+
return await readSseStreamResult<TFinal>(response, input.onEvent);
|
|
266
154
|
} finally {
|
|
267
|
-
reader.releaseLock();
|
|
268
155
|
input.signal?.removeEventListener('abort', abort);
|
|
269
156
|
}
|
|
270
|
-
|
|
271
|
-
if (finalResult === undefined) {
|
|
272
|
-
throw new Error('stream ended without final event');
|
|
273
|
-
}
|
|
274
|
-
return finalResult as TFinal;
|
|
275
157
|
})();
|
|
276
158
|
|
|
277
159
|
return {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { API_BASE } from '@/api/client';
|
|
2
2
|
import type { ApiError } from '@/api/types';
|
|
3
3
|
import type { AppEvent, AppTransport, RemoteRuntimeInfo, RequestInput, StreamInput, StreamSession } from './transport.types';
|
|
4
|
+
import { resolveTransportWebSocketUrl } from './transport-websocket-url';
|
|
4
5
|
|
|
5
6
|
type RemoteTarget = {
|
|
6
7
|
method: string;
|
|
@@ -34,31 +35,6 @@ type PendingStream = {
|
|
|
34
35
|
reject: (error: Error) => void;
|
|
35
36
|
};
|
|
36
37
|
|
|
37
|
-
function createWsUrl(apiBase: string, wsPath: string): string {
|
|
38
|
-
const normalizedBase = apiBase.replace(/\/$/, '');
|
|
39
|
-
try {
|
|
40
|
-
const resolved = new URL(normalizedBase, window.location.origin);
|
|
41
|
-
const protocol =
|
|
42
|
-
resolved.protocol === 'https:'
|
|
43
|
-
? 'wss:'
|
|
44
|
-
: resolved.protocol === 'http:'
|
|
45
|
-
? 'ws:'
|
|
46
|
-
: resolved.protocol;
|
|
47
|
-
return `${protocol}//${resolved.host}${wsPath}`;
|
|
48
|
-
} catch {
|
|
49
|
-
if (normalizedBase.startsWith('wss://') || normalizedBase.startsWith('ws://')) {
|
|
50
|
-
return `${normalizedBase}${wsPath}`;
|
|
51
|
-
}
|
|
52
|
-
if (normalizedBase.startsWith('https://')) {
|
|
53
|
-
return `${normalizedBase.replace(/^https:/, 'wss:')}${wsPath}`;
|
|
54
|
-
}
|
|
55
|
-
if (normalizedBase.startsWith('http://')) {
|
|
56
|
-
return `${normalizedBase.replace(/^http:/, 'ws:')}${wsPath}`;
|
|
57
|
-
}
|
|
58
|
-
return `${normalizedBase}${wsPath}`;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
38
|
function normalizeApiError(body: unknown, status: number, fallback: string): Error {
|
|
63
39
|
if (typeof body === 'object' && body && 'ok' in body) {
|
|
64
40
|
const typed = body as { ok?: boolean; error?: ApiError; data?: unknown };
|
|
@@ -243,7 +219,7 @@ export class RemoteSessionMultiplexTransport implements AppTransport {
|
|
|
243
219
|
return await this.connectPromise;
|
|
244
220
|
}
|
|
245
221
|
|
|
246
|
-
const wsUrl =
|
|
222
|
+
const wsUrl = resolveTransportWebSocketUrl(this.apiBase, this.runtime.wsPath);
|
|
247
223
|
this.manualClose = false;
|
|
248
224
|
this.connectPromise = new Promise<void>((innerResolve, innerReject) => {
|
|
249
225
|
const socket = new WebSocket(wsUrl);
|
|
@@ -330,69 +306,58 @@ export class RemoteSessionMultiplexTransport implements AppTransport {
|
|
|
330
306
|
}
|
|
331
307
|
|
|
332
308
|
private handleFrame(frame: RemoteBrowserFrame): void {
|
|
333
|
-
if (frame.type === 'response') {
|
|
334
|
-
|
|
335
|
-
if (!pending) {
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
this.pendingRequests.delete(frame.id);
|
|
339
|
-
if (frame.status >= 400) {
|
|
340
|
-
pending.reject(normalizeApiError(frame.body, frame.status, 'Remote request failed.'));
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
try {
|
|
344
|
-
pending.resolve(unwrapApiBody(frame.body));
|
|
345
|
-
} catch (error) {
|
|
346
|
-
pending.reject(error instanceof Error ? error : new Error(String(error)));
|
|
347
|
-
}
|
|
309
|
+
if (frame.type === 'response' || frame.type === 'request.error') {
|
|
310
|
+
this.handleRequestFrame(frame);
|
|
348
311
|
return;
|
|
349
312
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
const pending = this.pendingRequests.get(frame.id);
|
|
353
|
-
if (!pending) {
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
this.pendingRequests.delete(frame.id);
|
|
357
|
-
pending.reject(new Error(frame.message));
|
|
313
|
+
if (frame.type === 'stream.event' || frame.type === 'stream.end' || frame.type === 'stream.error') {
|
|
314
|
+
this.handleStreamFrame(frame);
|
|
358
315
|
return;
|
|
359
316
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
this.pendingStreams.get(frame.streamId)?.onEvent({
|
|
363
|
-
name: frame.event,
|
|
364
|
-
payload: frame.payload
|
|
365
|
-
});
|
|
317
|
+
if (frame.type === 'event') {
|
|
318
|
+
this.emit(frame.event);
|
|
366
319
|
return;
|
|
367
320
|
}
|
|
321
|
+
if (frame.type === 'connection.error') {
|
|
322
|
+
this.emit({ type: 'connection.error', payload: { message: frame.message } });
|
|
323
|
+
}
|
|
324
|
+
}
|
|
368
325
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
this.pendingStreams.delete(frame.streamId);
|
|
375
|
-
pending.resolve(frame.result);
|
|
326
|
+
private handleRequestFrame(frame: Extract<RemoteBrowserFrame, { type: 'response' | 'request.error' }>): void {
|
|
327
|
+
const pending = this.pendingRequests.get(frame.id);
|
|
328
|
+
if (!pending) {
|
|
376
329
|
return;
|
|
377
330
|
}
|
|
378
|
-
|
|
379
|
-
if (frame.type === '
|
|
380
|
-
const pending = this.pendingStreams.get(frame.streamId);
|
|
381
|
-
if (!pending) {
|
|
382
|
-
return;
|
|
383
|
-
}
|
|
384
|
-
this.pendingStreams.delete(frame.streamId);
|
|
331
|
+
this.pendingRequests.delete(frame.id);
|
|
332
|
+
if (frame.type === 'request.error') {
|
|
385
333
|
pending.reject(new Error(frame.message));
|
|
386
334
|
return;
|
|
387
335
|
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
this.emit(frame.event);
|
|
336
|
+
if (frame.status >= 400) {
|
|
337
|
+
pending.reject(normalizeApiError(frame.body, frame.status, 'Remote request failed.'));
|
|
391
338
|
return;
|
|
392
339
|
}
|
|
340
|
+
try {
|
|
341
|
+
pending.resolve(unwrapApiBody(frame.body));
|
|
342
|
+
} catch (error) {
|
|
343
|
+
pending.reject(error instanceof Error ? error : new Error(String(error)));
|
|
344
|
+
}
|
|
345
|
+
}
|
|
393
346
|
|
|
394
|
-
|
|
395
|
-
|
|
347
|
+
private handleStreamFrame(frame: Extract<RemoteBrowserFrame, { type: 'stream.event' | 'stream.end' | 'stream.error' }>): void {
|
|
348
|
+
const pending = this.pendingStreams.get(frame.streamId);
|
|
349
|
+
if (!pending) {
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
if (frame.type === 'stream.event') {
|
|
353
|
+
pending.onEvent({ name: frame.event, payload: frame.payload });
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
this.pendingStreams.delete(frame.streamId);
|
|
357
|
+
if (frame.type === 'stream.end') {
|
|
358
|
+
pending.resolve(frame.result);
|
|
359
|
+
return;
|
|
396
360
|
}
|
|
361
|
+
pending.reject(new Error(frame.message));
|
|
397
362
|
}
|
|
398
363
|
}
|