@augmentd-labs/canvas-web 2.26.38 → 2.26.39
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/dist/assets/{CalendarApplet-7wqNCpcs.js → CalendarApplet-DVUCGIPB.js} +1 -1
- package/dist/assets/{FileForm-C35drQ_R.js → FileForm-CMuWZbUX.js} +1 -1
- package/dist/assets/{FiltersApplet-Dh4SUfjN.js → FiltersApplet-CvdFlyn1.js} +1 -1
- package/dist/assets/{HomeFab-W7y591CD.js → HomeFab-DRmbW2Uu.js} +1 -1
- package/dist/assets/{IdentityFields-DZRqtnIG.js → IdentityFields-C7sv9pMk.js} +1 -1
- package/dist/assets/{LensApplet-CddpZXRw.js → LensApplet-gIiGSdLb.js} +1 -1
- package/dist/assets/{LinkToCard-BQ1yoFDr.js → LinkToCard-DGpvNE_V.js} +1 -1
- package/dist/assets/{NextShell-BfQHKEKO.js → NextShell-DiyMsTp5.js} +1 -1
- package/dist/assets/{NotesApplet-Cyuirnp1.js → NotesApplet-BUXkez68.js} +1 -1
- package/dist/assets/ObjectPropertiesCard-pE3IL82x.js +8 -0
- package/dist/assets/{PathPickerField-B4yFUjgD.js → PathPickerField-D7SubxSh.js} +1 -1
- package/dist/assets/{PickDocumentsCard-CFDQL70e.js → PickDocumentsCard-BhJbPlxk.js} +1 -1
- package/dist/assets/{SketchApplet-14xrogy3.js → SketchApplet-CQexRECa.js} +1 -1
- package/dist/assets/{SketchEditor-B2LYe_MO.js → SketchEditor-DxIN-6wI.js} +1 -1
- package/dist/assets/{TerminalApplet-BNeLmNFF.js → TerminalApplet-D-F4-4Zt.js} +1 -1
- package/dist/assets/{TextDocumentEditor-CU5ersd_.js → TextDocumentEditor-YAeo69K7.js} +1 -1
- package/dist/assets/{TodosApplet-ASG9wXjL.js → TodosApplet-OBi0XUdm.js} +1 -1
- package/dist/assets/{TodosWidget-CYK5RbYD.js → TodosWidget-B_R-vHxf.js} +1 -1
- package/dist/assets/{UploadProgressList-Ci1akl_D.js → UploadProgressList-C9teR7r-.js} +1 -1
- package/dist/assets/{_agentId_-Dy7lgkJK.js → _agentId_-CYfkXrJk.js} +0 -0
- package/dist/assets/{_contextId_-BBpL3f_T.js → _contextId_-CkahAS5d.js} +1 -1
- package/dist/assets/{_workspaceName_-CU-hpvv7.js → _workspaceName_--lNvJpY1.js} +1 -1
- package/dist/assets/{about-Cns4GXCX.js → about-CCShKl-5.js} +1 -1
- package/dist/assets/{add-jGjbB0x1.js → add-G2dEzOng.js} +1 -1
- package/dist/assets/{agents-DsaNiZJc.js → agents-vx49b2X5.js} +1 -1
- package/dist/assets/{appearance-C1xkguK7.js → appearance-Dmzr0s9n.js} +1 -1
- package/dist/assets/{applet-target-I8w6EPj0.js → applet-target-DYrCD8BZ.js} +1 -1
- package/dist/assets/{apps-BCy4q37-.js → apps-B6DG6ZpO.js} +1 -1
- package/dist/assets/{backend-sync-progress-tUU2XWtW.js → backend-sync-progress-m7wUKTJn.js} +1 -1
- package/dist/assets/{context-DZ1Hn7tt.js → context-1vR30CeC.js} +1 -1
- package/dist/assets/{contexts-Df-cWUlj2.js → contexts-DFYjIhsj2.js} +1 -1
- package/dist/assets/{date-time-picker-txVhlNO0.js → date-time-picker-C40sYmga.js} +1 -1
- package/dist/assets/{document-CTvT2Qa5.js → document-BiNwuf1n.js} +1 -1
- package/dist/assets/document-list-ASCemk7T.js +2 -0
- package/dist/assets/{home-C8Wq8hsp.js → home-B1ilyR89.js} +1 -1
- package/dist/assets/index-Bi5-zGgp.css +2 -0
- package/dist/assets/{index-Cp75myNf.js → index-CXPA9Fj8.js} +4 -4
- package/dist/assets/{key-bindings-CA_ePKGA.js → key-bindings-DXepopri.js} +1 -1
- package/dist/assets/{offline-sNCjxnp-.js → offline-DonGsRsw.js} +1 -1
- package/dist/assets/{public-share-D5yz-Pmo.js → public-share-DLXh7Ie6.js} +1 -1
- package/dist/assets/{query-debug-CQ0I3cXX.js → query-debug-DhboV3qX.js} +1 -1
- package/dist/assets/{registry-QDfCL8gg.js → registry-eFbDXN9w.js} +2 -2
- package/dist/assets/{roles-DoR2drD1.js → roles-DDiKiRii.js} +1 -1
- package/dist/assets/{settings-Bz400KLm.js → settings-CcdxMKot.js} +1 -1
- package/dist/assets/{settings-aOogFA9n.js → settings-CgjGE01m.js} +1 -1
- package/dist/assets/{settings-jIm9JVC-.js → settings-CwyGwKFU.js} +1 -1
- package/dist/assets/{settings-tgfewl6I.js → settings-D-yPOLZk.js} +1 -1
- package/dist/assets/{share-target-cRZICq5X.js → share-target-BhGDitlj.js} +1 -1
- package/dist/assets/{shared-eIOEFQRM.js → shared-DimeKqW8.js} +1 -1
- package/dist/assets/{shared-BnpwVpxG.js → shared-XYVtCrC8.js} +1 -1
- package/dist/assets/{sketch-lazy-BbNgGbR3.js → sketch-lazy-6eEi8GIA.js} +2 -2
- package/dist/assets/{text-documents-BaXhu3ra.js → text-documents-DxVsu9zG.js} +1 -1
- package/dist/assets/{tree-folders-cmsIS19Z.js → tree-folders-whK_PK4c.js} +1 -1
- package/dist/assets/{use-applet-docs-B2dk__vk.js → use-applet-docs-FqhvvOWx.js} +1 -1
- package/dist/assets/{use-applet-target-ffIGaAqT.js → use-applet-target-1DU4mgJH.js} +1 -1
- package/dist/assets/{use-canvas-pins-DkWN9oEd.js → use-canvas-pins-DqkSe_aU.js} +1 -1
- package/dist/assets/{use-workspace-identity-B8gOMGj4.js → use-workspace-identity-KEG0VpcX.js} +1 -1
- package/dist/assets/{useAddTarget-B3b6TyZr.js → useAddTarget-BEgKjqGj.js} +1 -1
- package/dist/assets/{useAgentModels-B10Tbl6D.js → useAgentModels-CI7iZlUR.js} +1 -1
- package/dist/assets/{useDocumentThumbnail-wW0lSOEy.js → useDocumentThumbnail-DutrNFK3.js} +1 -1
- package/dist/assets/{useEditNoteFields-DXLTFEqL.js → useEditNoteFields-HAsbBak7.js} +1 -1
- package/dist/assets/{workspace-area-menu-BFw2yUHk.js → workspace-area-menu-CUqTxXmz.js} +1 -1
- package/dist/assets/{workspace-content-gate-NLuRPvbm.js → workspace-content-gate-B6T3nLfW.js} +1 -1
- package/dist/assets/workspace-cv6Hrfhh.js +1 -0
- package/dist/assets/{workspace-import-form-Bb6z42nw.js → workspace-import-form-D5qPcNFq.js} +1 -1
- package/dist/assets/{workspaces-DC19HlpI.js → workspaces-yHyufXqs.js} +1 -1
- package/dist/index.html +26 -26
- package/dist/sw.js +1 -1
- package/package.json +2 -2
- package/dist/assets/ObjectPropertiesCard-BTTwYnN9.js +0 -8
- package/dist/assets/document-list-CQ1_7Sja.js +0 -2
- package/dist/assets/index-_0FSwEvG.css +0 -2
- package/dist/assets/workspace-BJELPCNs.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{a as t,i as n,l as r,n as i,r as a,t as o,u as s}from"./code-editor-BOIngd5F.js";import{_t as c}from"./react-BHzhHVTZ.js";import{_ as l,g as u,v as d}from"./chunk-62JRHF6Z-vspAGgtK.js";import{An as f,Bn as p,Bt as m,Cn as h,Ct as g,Fn as _,G as v,H as y,It as b,J as x,Jn as S,Kt as C,L as w,Lr as T,Mt as E,Nt as ee,Pt as D,Qt as te,Tr as O,Tt as ne,U as k,Ur as re,Vr as A,Wn as ie,Wr as j,X as M,Xn as ae,Xt as N,Z as P,Zn as F,_i as oe,_t as se,an as ce,bi as le,br as I,bt as ue,cn as de,ct as fe,fr as pe,ft as L,kt as R,mr as me,ni as he,pn as z,pr as ge,pt as _e,rt as ve,st as ye,vn as B,vr as V}from"./ui-CDoK3F3U.js";import{t as be}from"./utils-2pl1SbIp.js";import{t as H}from"./button-SeUZ_Pvi.js";import{t as U}from"./input-BOtCd4HP.js";import{t as W}from"./label-BSTdjCWU.js";import{c as xe,l as Se,t as G}from"./api-CA6WiiYM.js";import{t as Ce}from"./socket-CtH3EU9m.js";import{n as K}from"./use-toast-BlLDqSUO.js";import{t as we}from"./LinkToCard-BQ1yoFDr.js";import{$ as Te,A as Ee,Ct as De,Et as Oe,H as q,Ht as ke,I as Ae,Kt as je,L as Me,Nt as Ne,Ot as Pe,P as J,T as Fe,Ut as Ie,W as Y,_n as Le,an as Re,at as ze,ct as Be,d as Ve,dn as He,en as Ue,et as X,f as We,fn as Ge,gn as Ke,ht as qe,in as Je,k as Ye,n as Xe,on as Ze,r as Qe,tn as $e,tt as et,un as tt,vt as nt,yn as rt,yt as it}from"./workspace-BJELPCNs.js";import{a as at,c as ot,i as st,n as ct,o as lt,r as ut,s as dt,t as ft}from"./alert-dialog-CFeuDt0T.js";import{t as pt}from"./use-mobile-Db-vWu9Y.js";import{t as mt}from"./useEscapeClose-DR_xKT_k.js";import{o as ht}from"./layer-style-Byl5LNFR.js";import{i as gt,t as _t}from"./color-DFEH4BfK.js";import{a as vt,o as yt,s as bt,t as xt}from"./MessageComposerDialog-CdPp-3GR.js";import{n as St}from"./LinkToSidePanel-eCy3nW4R.js";import{n as Ct}from"./use-document-modal-PG8bQyIB.js";import{A as wt,B as Tt,D as Et,E as Dt,F as Ot,H as kt,I as At,L as jt,M as Mt,N as Nt,O as Pt,P as Ft,R as It,S as Lt,T as Rt,U as zt,V as Bt,b as Vt,d as Ht,f as Ut,h as Wt,j as Gt,m as Kt,p as qt,t as Jt,w as Yt,x as Xt}from"./backend-sync-progress-tUU2XWtW.js";import{t as Zt}from"./workspace-access-C9nZlBBZ.js";import{i as Qt}from"./use-menu-DIP1zh7I.js";import{t as $t}from"./use-theme-DaxpiICf.js";import{_t as en,at as tn,bt as nn,ct as rn,it as an,lt as on,ot as sn,st as cn,ut as ln,wt as un}from"./index-Cp75myNf.js";import{n as dn}from"./page-header-DrDt1sQ2.js";import{c as fn,f as pn,l as mn,m as hn,n as gn,o as _n,p as vn,r as yn,s as bn,t as xn}from"./inferd-config-editor-B8x_XPOt.js";import{n as Sn,t as Cn}from"./useSocketSubscription-ifW-vnlb.js";import{a as wn,n as Tn,o as En,r as Dn,t as On}from"./devices-CAa1bRxk.js";import{a as kn,i as An,n as jn,s as Mn,t as Nn}from"./query-debug-CQ0I3cXX.js";import{a as Pn,i as Fn,r as In,t as Ln}from"./workspace-import-form-Bb6z42nw.js";var Z=e(s(),1),Rn=`workspace:backups`,zn=e=>`${xe.workspaces}/${encodeURIComponent(e)}/db/backups`,Bn=e=>G.get(zn(e)),Vn=e=>G.post(zn(e),{action:`backup`}),Hn=(e,t)=>G.post(zn(e),{action:`restore`,backupId:t,confirm:!0}),Un=new Map;function Wn(e,t,n){let r=JSON.stringify([t,n.id]),i=Un.get(r);if(i)return i;let a=(async()=>{let r=n.action===`restore`,i=e({title:r?`Restoring workspace database`:`Backing up workspace database`,description:r?`Stopping the workspace and preserving its current database…`:`Copying and verifying all datasets…`});try{let e=n;for(;e.status===`running`;){let n=await Bn(t),r=n.jobs.find(t=>t.id===e.id);if(!r)throw Error(`The server restarted. Refresh the backup list to check the result.`);e=r,window.dispatchEvent(new CustomEvent(Rn,{detail:{workspace:t,status:n}})),e.status===`running`&&await new Promise(e=>setTimeout(e,1500))}if(e.status===`failed`)throw Error(e.error||`Database operation failed`);i.done({title:r?`Workspace database restored`:`Workspace backup verified`,description:r?`The workspace is stopped. Start it when you are ready; search indexes will rebuild.`:`Documents, relations and virtual tree placements are saved.`})}catch(e){throw i.fail({title:`Workspace backup needs attention`,description:e instanceof Error?e.message:String(e),variant:`destructive`}),e}})();return Un.set(r,a),a.finally(()=>Un.delete(r)).catch(()=>{}),a}var Q=r(),Gn={startup:`Startup`,hourly:`Hourly`,manual:`Manual`,"pre-restore":`Before restore`};function Kn({workspaceId:e,onRestored:t}){let{showToast:n,showProgress:r}=K(),[i,a]=(0,Z.useState)(null),[o,s]=(0,Z.useState)(null),[c,l]=(0,Z.useState)(null),[u,d]=(0,Z.useState)(!1),f=(0,Z.useRef)(!1),p=(0,Z.useRef)(!1),m=(0,Z.useRef)(0),h=(0,Z.useCallback)(()=>{let t=++m.current;return Bn(e).then(n=>{if(!(!f.current||t!==m.current)){a(n),s(null);for(let t of n.jobs.filter(e=>e.status===`running`))Wn(r,e,t).catch(()=>{})}}).catch(e=>{f.current&&t===m.current&&s(e instanceof Error?e.message:String(e))})},[e,r]);(0,Z.useEffect)(()=>{f.current=!0,h();let t=t=>{let n=t.detail;n.workspace===e&&a(n.status)};return window.addEventListener(Rn,t),()=>{f.current=!1,window.removeEventListener(Rn,t)}},[e,h]);let g=async i=>{if(!p.current){p.current=!0,d(!0);try{let n=i?await Hn(e,i.id):await Vn(e);f.current&&a(e=>e&&{...e,jobs:[n,...e.jobs]}),await Wn(r,e,n),i&&t()}catch(e){n({title:`Database operation did not complete`,description:e instanceof Error?e.message:String(e),variant:`destructive`})}finally{p.current=!1,f.current&&(d(!1),h())}}},_=u||!!i?.jobs.some(e=>e.status===`running`),v=i?.jobs[0];return(0,Q.jsxs)(`div`,{className:`min-w-0 space-y-5`,children:[(0,Q.jsxs)(`section`,{className:`space-y-4 rounded border p-4`,children:[(0,Q.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,Q.jsx)(oe,{className:`h-5 w-5 text-muted-foreground`}),(0,Q.jsx)(`h2`,{className:`font-semibold`,children:`Workspace checkpoints`}),(0,Q.jsxs)(H,{variant:`outline`,size:`sm`,className:`ml-auto`,disabled:_||!i||!!o,onClick:()=>void g(),children:[_?(0,Q.jsx)(z,{className:`mr-2 h-4 w-4 animate-spin`}):(0,Q.jsx)(oe,{className:`mr-2 h-4 w-4`}),`Back up now`]})]}),(0,Q.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Save a checkpoint before a bulk action. Each backup includes every document, relation and virtual tree placement in this workspace’s database.`}),(0,Q.jsxs)(`div`,{className:`flex flex-wrap gap-x-5 gap-y-2 text-sm`,children:[(0,Q.jsxs)(`span`,{children:[(0,Q.jsx)(`strong`,{children:i?.retention.hourly??24}),` hourly backups`]}),(0,Q.jsxs)(`span`,{children:[(0,Q.jsx)(`strong`,{children:i?.retention.startup??14}),` startup backups`]}),(0,Q.jsx)(`span`,{children:`Manual checkpoints kept`})]}),(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Hourly backups run while the workspace is active. These checkpoints cover the database only; files in storage backends and workspace settings need their own backups.`})]}),(0,Q.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,Q.jsxs)(`h2`,{className:`text-sm font-semibold`,children:[`Verified checkpoints`,i?` · ${i.backups.length}`:``]}),(0,Q.jsx)(H,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:()=>void h(),"aria-label":`Refresh backups`,children:(0,Q.jsx)(R,{className:`h-4 w-4`})})]}),o&&(0,Q.jsx)(`p`,{role:`alert`,className:`text-sm text-destructive`,children:o}),v&&(0,Q.jsx)(`p`,{role:`status`,className:`text-sm ${v.status===`failed`?`text-destructive`:`text-muted-foreground`}`,children:v.status===`running`?`Database operation in progress…`:v.status===`failed`?v.error:v.action===`restore`?`Database restored. The workspace is stopped and ready to start.`:`Backup complete and verified.`}),!i&&!o&&(0,Q.jsx)(`p`,{role:`status`,className:`text-sm text-muted-foreground`,children:`Loading backups…`}),i?.backups.length===0&&(0,Q.jsx)(`p`,{className:`rounded border border-dashed p-6 text-sm text-muted-foreground`,children:`No verified checkpoints yet. Create one before your next bulk action.`}),(0,Q.jsx)(`div`,{className:`space-y-2`,children:i?.backups.map(e=>(0,Q.jsxs)(`article`,{className:`flex min-w-0 flex-wrap items-center gap-3 rounded border p-3`,children:[(0,Q.jsx)(j,{className:`h-4 w-4 shrink-0 text-muted-foreground`,"aria-label":`Verified`}),(0,Q.jsxs)(`div`,{className:`min-w-0 flex-1 basis-40`,children:[(0,Q.jsx)(`p`,{className:`text-sm font-medium`,children:new Date(e.createdAt).toLocaleString()}),(0,Q.jsxs)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:[Gn[e.kind],` · `,q(e.bytes),` · `,(e.datasets.documents?.count??0).toLocaleString(),` documents`]})]}),(0,Q.jsxs)(H,{variant:`outline`,size:`sm`,disabled:_,onClick:()=>l(e),children:[(0,Q.jsx)(ne,{className:`mr-2 h-3.5 w-3.5`}),`Restore`]})]},e.id))}),(0,Q.jsx)(ft,{open:!!c,onOpenChange:e=>{e||l(null)},children:(0,Q.jsxs)(st,{className:`max-w-[calc(100vw-2rem)] sm:max-w-lg`,children:[(0,Q.jsxs)(dt,{children:[(0,Q.jsx)(ot,{children:`Restore this workspace checkpoint?`}),(0,Q.jsxs)(at,{children:[`The workspace will stop and its current database will be backed up first. Documents, relations and virtual tree placements will return to `,c?new Date(c.createdAt).toLocaleString():`the selected checkpoint`,`. Files in storage backends and workspace settings will stay as they are. The workspace stays stopped after restoration.`]})]}),(0,Q.jsxs)(lt,{children:[(0,Q.jsx)(ut,{children:`Cancel`}),(0,Q.jsx)(ct,{disabled:_,onClick:()=>{c&&g(c)},children:`Back up current & restore`})]})]})})]})}var qn={collect:`Collect unused blobs`,verify:`Verify integrity`,compact:`Compact index`},Jn=e=>e.status===`queued`||e.status===`running`,Yn=e=>`${xe.workspaces}/${encodeURIComponent(e)}/cache/maintenance`,Xn=e=>G.get(Yn(e)),Zn=(e,t,n)=>G.post(Yn(e),{store:t,action:n,...n===`verify`?{confirm:!0}:{}});function Qn(e){if(e.status===`failed`)return e.error||`Maintenance failed`;if(e.status===`queued`)return`Waiting for active storage operations…`;if(e.status===`running`)return e.action===`verify`?`Reading and checking stored content…`:`Processing the cache index…`;let t=e.result||{};return e.action===`compact`?`${(t.compactedCount||0).toLocaleString()} keys compacted`:e.action===`verify`?`${(t.verifiedContent||0).toLocaleString()} blobs verified · ${(t.badContentCount||0).toLocaleString()} corrupted blobs removed · ${q(t.reclaimedSize||0)} reclaimed`:`${(t.reclaimedCount||0).toLocaleString()} unused blobs removed · ${q(t.reclaimedSize||0)} reclaimed`}var $n=new Map,er=`workspace:cache-maintenance`;function tr(e,t,n){let r=JSON.stringify([t,n.id]),i=$n.get(r);if(i)return i;let a=(async()=>{let r=e({title:qn[n.action],description:`${n.store} · ${Qn(n)}`});try{let e=n;for(;Jn(e);){let i=await Xn(t),a=i.jobs.find(e=>e.id===n.id);if(!a)throw Error(`Maintenance receipt is no longer available. The server may have restarted; refresh the cache settings.`);if(e=a,window.dispatchEvent(new CustomEvent(er,{detail:{workspace:t,status:i}})),!Jn(e))break;r.update({title:qn[e.action],description:`${e.store} · ${Qn(e)}`}),await new Promise(e=>setTimeout(e,2e3))}if(e.status===`failed`)throw Error(Qn(e));r.done({title:`${qn[e.action]} complete`,description:`${e.store} · ${Qn(e)}`})}catch(e){throw r.fail({title:`Cache maintenance needs attention`,description:`${n.store} · ${e instanceof Error?e.message:String(e)}`,variant:`destructive`}),e}})();return $n.set(r,a),a.finally(()=>{$n.get(r)===a&&$n.delete(r)}).catch(()=>{}),a}function nr({workspaceId:e,children:t}){let{showToast:n,showProgress:r}=K(),[i,a]=(0,Z.useState)(null),[o,s]=(0,Z.useState)(`workspace:cache`),[c,l]=(0,Z.useState)(!1),[u,d]=(0,Z.useState)(!1),[f,p]=(0,Z.useState)(null),m=(0,Z.useRef)(!1),h=(0,Z.useRef)(!1),g=(0,Z.useCallback)(()=>Xn(e).then(t=>{if(h.current){a(t),p(null);for(let n of t.jobs.filter(Jn))tr(r,e,n).catch(()=>{})}}).catch(e=>{h.current&&p(e instanceof Error?e.message:`Cannot load maintenance status`)}),[e,r]);(0,Z.useEffect)(()=>{h.current=!0,g();let t=t=>{let{workspace:n,status:r}=t.detail;n===e&&(a(r),p(null))};return window.addEventListener(er,t),()=>{h.current=!1,window.removeEventListener(er,t)}},[e,g]);let _=async t=>{if(!(m.current||i?.jobs.some(Jn))){m.current=!0,l(!0);try{let n=await Zn(e,o,t);h.current&&a(e=>e&&{...e,jobs:[n,...e.jobs.filter(e=>e.id!==n.id)]}),tr(r,e,n).catch(()=>{})}catch(e){n({title:`Could not start maintenance`,description:e instanceof Error?e.message:String(e),variant:`destructive`}),g()}finally{m.current=!1,h.current&&l(!1)}}},v=c||!!i?.jobs.some(Jn),y=i?.stores.find(e=>e.id===o),b=i?.jobs[0];return(0,Q.jsxs)(`section`,{className:`space-y-4 rounded-(--panel-radius) border p-4`,"aria-label":`Workspace cache maintenance`,children:[(0,Q.jsxs)(`div`,{className:`flex flex-wrap items-start justify-between gap-3`,children:[(0,Q.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Q.jsxs)(`h2`,{className:`flex items-center gap-2 text-sm font-semibold`,children:[(0,Q.jsx)(I,{className:`h-4 w-4 shrink-0`}),`Workspace cache`]}),(0,Q.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:`Thumbnails, cached resources and pending transfers. Maintenance runs only when requested.`})]}),t&&(0,Q.jsx)(`fieldset`,{disabled:v,children:t})]}),(0,Q.jsxs)(`div`,{className:`space-y-3 border-t pt-3`,children:[(0,Q.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,Q.jsx)(`label`,{htmlFor:`cache-maintenance-store`,className:`text-xs font-medium`,children:`Store`}),(0,Q.jsxs)(`select`,{id:`cache-maintenance-store`,value:o,onChange:e=>s(e.target.value),disabled:v,className:`min-w-0 max-w-full rounded-md border bg-background px-2 py-1.5 text-xs`,children:[(0,Q.jsx)(`option`,{value:`workspace:cache`,children:`workspace:cache`}),(0,Q.jsx)(`option`,{value:`workspace:data`,children:`workspace:data`})]}),(0,Q.jsx)(H,{type:`button`,variant:`ghost`,size:`icon`,onClick:()=>void g(),"aria-label":`Refresh cache maintenance status`,className:`ml-auto h-8 w-8`,children:(0,Q.jsx)(R,{className:`h-3.5 w-3.5`})})]}),(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:o===`workspace:data`?`Managed document blobs. Referenced content is kept during collection.`:`Working cache, including content awaiting transfer. Referenced content is kept during collection.`}),(0,Q.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,Q.jsxs)(H,{type:`button`,variant:`outline`,size:`sm`,disabled:v||!y?.canCollect||!!f,onClick:()=>void _(`collect`),children:[(0,Q.jsx)(M,{className:`mr-2 h-3.5 w-3.5`}),`Collect unused blobs`]}),(0,Q.jsxs)(H,{type:`button`,variant:`outline`,size:`sm`,disabled:v||!y?.canCompact||!!f,onClick:()=>void _(`compact`),children:[(0,Q.jsx)(oe,{className:`mr-2 h-3.5 w-3.5`}),`Compact index`]}),(0,Q.jsxs)(H,{type:`button`,variant:`outline`,size:`sm`,disabled:v||!y?.canVerify||!!f,onClick:()=>d(!0),children:[(0,Q.jsx)(L,{className:`mr-2 h-3.5 w-3.5`}),`Verify integrity`]})]}),(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Collection removes unreferenced blobs. Compaction trims index history. Verification reads every blob and may remove corrupted content. Storage writes may wait during maintenance.`}),!i&&!f&&(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,role:`status`,children:`Loading maintenance status…`}),y&&!y.canCollect&&!y.canVerify&&!y.canCompact&&(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Update canvas-stored to enable maintenance for this store.`}),f&&(0,Q.jsx)(`p`,{className:`text-xs text-destructive`,role:`alert`,children:f}),b&&(0,Q.jsxs)(`div`,{className:`rounded-md bg-muted/50 p-3 text-xs`,role:`status`,"aria-live":`polite`,children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2 font-medium`,children:[Jn(b)&&(0,Q.jsx)(z,{className:`h-3.5 w-3.5 animate-spin`}),qn[b.action],` · `,b.store]}),(0,Q.jsx)(`p`,{className:`mt-1 ${b.status===`failed`?`text-destructive`:`text-muted-foreground`}`,children:Qn(b)}),(0,Q.jsx)(`p`,{className:`mt-1 text-muted-foreground`,children:b.finishedAt?`Finished ${new Date(b.finishedAt).toLocaleString()}`:`Requested ${new Date(b.createdAt).toLocaleString()}`})]})]}),(0,Q.jsx)(ft,{open:u,onOpenChange:d,children:(0,Q.jsxs)(st,{className:`max-w-[calc(100vw-2rem)] sm:max-w-lg`,children:[(0,Q.jsxs)(dt,{children:[(0,Q.jsxs)(ot,{children:[`Verify `,o,`?`]}),(0,Q.jsx)(at,{children:`This reads all stored content and can take a long time. Corrupted blobs and their index entries may be removed. Keep a recovery backup before running it. Storage writes may wait until it finishes.`})]}),(0,Q.jsxs)(lt,{children:[(0,Q.jsx)(ut,{children:`Cancel`}),(0,Q.jsx)(ct,{disabled:v,onClick:()=>void _(`verify`),children:`Verify and repair`})]})]})})]})}var rr=e=>e.status===`queued`||e.status===`running`,ir=e=>`${xe.workspaces}/${encodeURIComponent(e)}/db`,ar=e=>G.get(`${ir(e)}/maintenance`),or={"reindex:timelines":`reindex/timelines`,"reindex:mime":`reindex/mime`,"reindex:search":`reindex/search`,optimize:`optimize`};function sr(e,t,n={}){let r=or[t];return t===`reindex:search`?G.post(`${ir(e)}/${r}${n.rebuild?`?rebuild=true`:``}`,{}):G.post(`${ir(e)}/${r}`,t===`optimize`&&n.space?{space:n.space}:{})}function cr(e){switch(e.action){case`reindex:timelines`:return`Rebuild timelines`;case`reindex:mime`:return`Rebuild file types`;case`reindex:search`:return e.options.rebuild?`Rebuild word search`:`Index missing documents`;default:return e.options.space?`Optimize ${e.options.space}`:`Optimize indexes`}}var lr=e=>typeof e==`number`?e.toLocaleString():`0`;function ur(e){if(e.status===`failed`)return e.error||`Maintenance failed`;if(e.status===`queued`)return`Waiting for the database…`;if(e.status===`running`){let t=e.progress;return t?e.action===`reindex:search`?`${lr(t.indexed)} indexed`:`${lr(t.scanned)}${typeof t.total==`number`?` / ${lr(t.total)}`:``} documents scanned`:`Working…`}let t=e.result||{};return e.action===`reindex:timelines`?`${lr(t.created)} created, ${lr(t.updated)} updated (${lr(t.scanned)} scanned)`:e.action===`reindex:mime`?`${lr(t.ticked)} of ${lr(t.scanned)} documents across ${lr(t.keys)} file types`:e.action===`reindex:search`?`${lr(t.indexed)} newly indexed (${lr(t.alreadyIndexed)} of ${lr(t.totalDocs)} already were)`:`Indexes compacted`}var dr=new Map;function fr(e,t,n){let r=JSON.stringify([t,n.id]),i=dr.get(r);if(i)return i;let a=(async()=>{let r=e({title:cr(n),description:ur(n)});try{let e=n;for(;rr(e);){let i=(await ar(t)).jobs.find(e=>e.id===n.id);if(!i)throw Error(`Maintenance receipt is no longer available. The workspace may have restarted; run it again.`);if(e=i,!rr(e))break;r.update({title:cr(e),description:ur(e)}),await new Promise(e=>setTimeout(e,2e3))}if(e.status===`failed`)throw Error(ur(e));return r.done({title:`${cr(e)} complete`,description:ur(e)}),e}catch(e){throw r.fail({title:`${cr(n)} needs attention`,description:e instanceof Error?e.message:String(e),variant:`destructive`}),e}})();return dr.set(r,a),a.finally(()=>{dr.get(r)===a&&dr.delete(r)}).catch(()=>{}),a}function pr({workspaceId:e,backend:t,onSaved:n}){let r=t?.config||{},i=()=>({name:String(r.label||``),bucket:String(r.bucket||``),prefix:String(r.prefix||``),endpoint:String(r.endpoint||``),region:String(r.region||`us-east-1`),accessKeyId:``,secretAccessKey:``,sessionToken:``}),[a,o]=(0,Z.useState)(!1),[s,c]=(0,Z.useState)(i),[l,u]=(0,Z.useState)(r.forcePathStyle!==!1),[d,f]=(0,Z.useState)(r.readOnly===!0),[p,h]=(0,Z.useState)(r.watch===!0),[g,_]=(0,Z.useState)(!1),[v,y]=(0,Z.useState)(!1),{showToast:b}=K(),x=e=>({value:s[e],onChange:t=>c(n=>({...n,[e]:t.target.value}))});return a?(0,Q.jsxs)(`form`,{onSubmit:async r=>{r.preventDefault(),y(!0);try{let r={label:s.name.trim(),bucket:s.bucket.trim(),prefix:s.prefix.trim(),endpoint:s.endpoint.trim(),region:s.region.trim()||`us-east-1`,forcePathStyle:l,readOnly:d,watch:p,...Object.fromEntries([`accessKeyId`,`secretAccessKey`,`sessionToken`].flatMap(e=>{let t=s[e].trim();return t?[[e,t]]:[]})),...g?{sessionToken:``}:{}};t?await Ke(e,`s3`,t.address,r):await Xe(e,`s3`,r),o(!1),c(i()),b({title:t?`S3 backend updated`:`S3 backend added`,description:`Use Re-sync to check indexing progress, and filing policies to automate copies.`}),await n()}catch(e){b({title:`Could not connect S3`,description:e instanceof Error?e.message:String(e),variant:`destructive`})}finally{y(!1)}},className:`w-full space-y-3 rounded-lg border p-4`,children:[(0,Q.jsxs)(`h2`,{className:`flex items-center gap-2 text-sm font-semibold`,children:[(0,Q.jsx)(I,{className:`h-4 w-4`}),t?`Edit S3 connection`:`Add S3-compatible bucket`]}),(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Amazon S3, MinIO, Garage, RustFS or Ceph RGW. Connect an existing bucket, optionally scoped to a prefix. Supports browsing, reads and filing copies; mirror policies and overwrites are unavailable.`}),(0,Q.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs`,children:[`Name`,(0,Q.jsx)(U,{...x(`name`),required:!0,placeholder:`Accounting archive`})]}),(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs`,children:[`Bucket`,(0,Q.jsx)(U,{...x(`bucket`),disabled:!!t,required:!0,placeholder:`accounting`})]}),(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs`,children:[`Endpoint (blank for Amazon S3)`,(0,Q.jsx)(U,{...x(`endpoint`),disabled:!!t,type:`url`,placeholder:`https://s3.example.com`})]}),(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs`,children:[`Region`,(0,Q.jsx)(U,{...x(`region`),required:!0,placeholder:`us-east-1`})]}),(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs sm:col-span-2`,children:[`Prefix (optional)`,(0,Q.jsx)(U,{...x(`prefix`),disabled:!!t,placeholder:`Augmentd/Accounting`})]}),(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs`,children:[`Access key ID`,(0,Q.jsx)(U,{...x(`accessKeyId`),required:!t,autoComplete:`off`,placeholder:t?`Leave blank to keep stored value`:``})]}),(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs`,children:[`Secret access key`,(0,Q.jsx)(U,{...x(`secretAccessKey`),type:`password`,required:!t,autoComplete:`off`,placeholder:t?`Leave blank to keep stored value`:``})]}),(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs sm:col-span-2`,children:[`Session token (optional)`,(0,Q.jsx)(U,{...x(`sessionToken`),disabled:g,type:`password`,autoComplete:`off`,placeholder:t?`Leave blank to keep stored value`:``})]}),t&&(0,Q.jsxs)(`label`,{className:`flex items-center gap-2 text-xs`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,checked:g,onChange:e=>_(e.target.checked)}),`Clear stored session token`]})]}),(0,Q.jsxs)(`div`,{className:`flex flex-wrap gap-4 text-xs`,children:[(0,Q.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,checked:l,onChange:e=>u(e.target.checked)}),`Path-style addressing`]}),(0,Q.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,checked:d,onChange:e=>f(e.target.checked)}),`Read-only`]}),(0,Q.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,checked:p,onChange:e=>h(e.target.checked)}),`Poll for changes`]})]}),(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Writable connections test conflict protection using a temporary object, then delete it. The key needs list/read/write access and delete access under .canvas-probe/. Initial indexing reads file bytes; polling can incur request and download charges. Upload limit: 5 GiB per file.`}),(0,Q.jsxs)(`div`,{className:`flex justify-end gap-2`,children:[(0,Q.jsx)(H,{type:`button`,variant:`ghost`,disabled:v,onClick:()=>{o(!1),c(i())},children:`Cancel`}),(0,Q.jsx)(H,{disabled:v,children:v?`Checking connection…`:`Save connection`})]})]}):(0,Q.jsxs)(H,{variant:`outline`,size:`sm`,onClick:()=>{c(i()),u(r.forcePathStyle!==!1),f(r.readOnly===!0),h(r.watch===!0),_(!1),o(!0)},children:[t?(0,Q.jsx)(m,{className:`mr-2 h-3.5 w-3.5`}):(0,Q.jsx)(D,{className:`mr-2 h-3.5 w-3.5`}),t?`Edit S3 connection`:`Add S3 bucket`]})}function mr({workspaceId:e,isActive:t,currentMode:n,onChanged:r}){let[i,a]=(0,Z.useState)(n===`workspace`?`workspace`:`secrets`),[o,s]=(0,Z.useState)(``),[c,l]=(0,Z.useState)(``),[u,d]=(0,Z.useState)(``),[f,p]=(0,Z.useState)(``),[m,h]=(0,Z.useState)(``),[g,_]=(0,Z.useState)(!1);return(0,Q.jsxs)(`section`,{className:`space-y-3 rounded-lg border p-4`,children:[(0,Q.jsx)(`h2`,{className:`font-semibold text-sm`,children:`Workspace protection`}),(0,Q.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Protect service credentials with a PIN or password. Optionally require it to start the whole workspace. Files and document contents are not encrypted.`}),t&&(0,Q.jsx)(`p`,{className:`text-sm`,children:`Stop the workspace before changing protection.`}),(0,Q.jsxs)(`form`,{className:`space-y-3`,onSubmit:async t=>{if(t.preventDefault(),h(``),o!==c){h(`PIN/password confirmation does not match`);return}_(!0);try{let t=await G.put(`${xe.workspaces}/${e}/protection`,{mode:i,passphrase:o,currentPassphrase:u||void 0});p(t.recoveryKey),s(``),l(``),d(``)}catch(e){h(e instanceof Error?e.message:`Could not save protection`)}finally{_(!1)}},children:[(0,Q.jsxs)(`label`,{className:`block text-sm space-y-1`,children:[`Protection mode`,(0,Q.jsxs)(`select`,{className:`block rounded border bg-background p-2 w-full`,value:i,onChange:e=>a(e.target.value),disabled:t||g,children:[(0,Q.jsx)(`option`,{value:`secrets`,children:`Secrets only — allow start without integrations`}),(0,Q.jsx)(`option`,{value:`workspace`,children:`Whole workspace — require PIN/password to start`})]})]}),(0,Q.jsxs)(`label`,{className:`block text-sm space-y-1`,children:[`Current PIN/password or recovery key (if already protected)`,(0,Q.jsx)(U,{type:`password`,autoComplete:`current-password`,value:u,onChange:e=>d(e.target.value),disabled:t||g})]}),(0,Q.jsxs)(`label`,{className:`block text-sm space-y-1`,children:[`New PIN/password`,(0,Q.jsx)(U,{type:`password`,autoComplete:`new-password`,minLength:4,maxLength:1024,required:!0,value:o,onChange:e=>s(e.target.value),disabled:t||g})]}),(0,Q.jsxs)(`label`,{className:`block text-sm space-y-1`,children:[`Confirm new PIN/password`,(0,Q.jsx)(U,{type:`password`,autoComplete:`new-password`,required:!0,value:c,onChange:e=>l(e.target.value),disabled:t||g})]}),(0,Q.jsx)(H,{disabled:t||g||!!f,children:g?`Saving…`:`Save protection`})]}),m&&(0,Q.jsx)(`p`,{role:`alert`,className:`text-sm text-destructive`,children:m}),f&&(0,Q.jsxs)(`div`,{className:`space-y-2 rounded border p-3`,children:[(0,Q.jsx)(`p`,{className:`text-sm`,children:`Save this recovery key now. It is shown only once and replaces any previous recovery key.`}),(0,Q.jsx)(`code`,{className:`block break-all select-all`,children:f}),(0,Q.jsx)(H,{variant:`outline`,onClick:()=>{p(``),r()},children:`I saved the recovery key`})]})]})}var hr=`h-8 rounded-md border bg-background px-2 text-sm outline-none focus:ring-2 focus:ring-ring`;function gr({title:e,hint:t,children:n}){let[r,i]=(0,Z.useState)(!1);return(0,Q.jsxs)(`section`,{className:`overflow-hidden rounded-lg border`,children:[(0,Q.jsxs)(`button`,{type:`button`,onClick:()=>i(e=>!e),"aria-expanded":r,className:`flex w-full items-center justify-between gap-4 px-4 py-3 text-left transition-colors hover:bg-muted/40`,children:[(0,Q.jsxs)(`span`,{className:`min-w-0`,children:[(0,Q.jsx)(`span`,{className:`block text-sm font-medium`,children:e}),(0,Q.jsx)(`span`,{className:`mt-0.5 block text-xs text-muted-foreground`,children:t})]}),(0,Q.jsx)(re,{className:be(`h-4 w-4 shrink-0 text-muted-foreground transition-transform motion-reduce:transition-none`,r&&`rotate-180`)})]}),r&&(0,Q.jsx)(`div`,{className:`border-t p-4`,children:n})]})}function _r({workspaceName:e,value:t,onChange:n,disabled:r}){let[i,a]=(0,Z.useState)(!1);return(0,Q.jsxs)(`div`,{className:`space-y-1`,children:[(0,Q.jsxs)(`label`,{className:`text-xs font-medium`,children:[`Only this folder `,(0,Q.jsx)(`span`,{className:`font-normal text-muted-foreground`,children:`(optional)`})]}),(0,Q.jsxs)(`div`,{className:`flex gap-2`,children:[(0,Q.jsx)(U,{value:t,disabled:r,onChange:e=>n(e.target.value),placeholder:`Whole workspace`,className:`h-8 font-mono text-sm`}),(0,Q.jsx)(H,{type:`button`,size:`sm`,variant:`outline`,disabled:r,onClick:()=>a(!0),title:`Pick a folder or context from the tree`,children:(0,Q.jsx)(ae,{className:`h-3.5 w-3.5`})})]}),(0,Q.jsxs)(`p`,{className:`text-[11px] text-muted-foreground`,children:[`Includes everything below it. Pick from the tree, or type `,(0,Q.jsx)(`span`,{className:`font-mono`,children:`ctx://work/project`}),` or`,` `,(0,Q.jsx)(`span`,{className:`font-mono`,children:`dir://photos`}),`.`]}),i&&(0,Q.jsx)(St,{onClose:()=>a(!1),children:(0,Q.jsx)(we,{sizeClassName:`h-full w-[380px] max-w-[90vw] max-md:w-full`,fixedWorkspaceName:e,multiple:!1,onClose:()=>a(!1),onConfirm:(e,t)=>{let r=e[0];r&&n(`${t.treeType===`directory`?`dir`:`ctx`}://${r.replace(/^\/+/,``)}`),a(!1)}})})]})}function vr({workspaceId:e,workspaceName:t,refreshKey:n,onRefresh:r}){let{showToast:i}=K(),[a,o]=(0,Z.useState)(null),[s,c]=(0,Z.useState)(!1),l=(0,Z.useCallback)(()=>bn(e).then(e=>o(e.queue??null)).catch(()=>{}),[e]);(0,Z.useEffect)(()=>{l();let e=window.setInterval(()=>{o(e=>(e&&(e.pending>0||e.draining)&&l(),e))},3e3);return()=>window.clearInterval(e)},[l,n]);let u=async()=>{if(a){c(!0);try{let e=await Je(!a.paused,t);i({title:e.paused?`Indexing paused`:`Indexing resumed`,description:e.paused?`${e.pending.toLocaleString()} document(s) on hold. Resume any time; a server restart also resumes.`:`${e.pending.toLocaleString()} document(s) being indexed.`}),await l()}catch(e){i({title:`Error`,description:e instanceof Error?e.message:`Failed to pause or resume indexing (admin only)`,variant:`destructive`})}finally{c(!1)}}},d=!!a?.draining,f=a?a.paused?`bg-warning`:d?`bg-success`:`bg-muted-foreground/40`:`bg-muted-foreground/40`;return(0,Q.jsxs)(`section`,{className:`flex flex-wrap items-center justify-between gap-x-4 gap-y-2 rounded-lg border bg-muted/30 px-4 py-2.5`,children:[(0,Q.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2 text-sm`,children:[(0,Q.jsxs)(`span`,{className:`relative flex h-2 w-2 shrink-0`,"aria-hidden":!0,children:[d&&(0,Q.jsx)(`span`,{className:`absolute inline-flex h-full w-full animate-ping rounded-full bg-success opacity-60 motion-reduce:hidden`}),(0,Q.jsx)(`span`,{className:be(`relative inline-flex h-2 w-2 rounded-full`,f)})]}),(0,Q.jsx)(`span`,{className:`font-medium`,children:a?a.pending>0?(0,Q.jsxs)(Q.Fragment,{children:[a.pending.toLocaleString(),` `,(0,Q.jsx)(`span`,{className:`font-normal text-muted-foreground`,children:`document(s) waiting to be indexed`})]}):a.paused?`Paused`:`Up to date`:`Inference service not reachable`}),a?.paused&&a.pending>0&&(0,Q.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`(paused)`}),a?.ingestDisabled&&(0,Q.jsx)(`span`,{className:`rounded bg-warning-subtle px-1.5 py-0.5 text-[10px] font-medium text-warning`,title:`CANVAS_INFERD_INGEST_DISABLED=true: new documents are not indexed for meaning search; what is already indexed still works`,children:`indexing turned off on the server`})]}),(0,Q.jsxs)(`div`,{className:`flex items-center gap-1`,children:[a&&(0,Q.jsx)(H,{type:`button`,size:`sm`,variant:`ghost`,disabled:s,onClick:u,title:a.paused?`Resume; the waiting documents get indexed`:`Pause after the current batch. Stops the CPU-heavy model work; new documents are still found by word search.`,children:s?`…`:a.paused?`Resume`:`Pause`}),(0,Q.jsx)(H,{type:`button`,size:`sm`,variant:`ghost`,onClick:r,title:`Reload`,children:(0,Q.jsx)(R,{className:`h-3.5 w-3.5`})})]})]})}function yr({workspaceId:e,tables:t,error:n,onChanged:r}){let{showToast:i}=K(),[a,o]=(0,Z.useState)(null),s=t.filter(e=>!e.active),c=async t=>{if(window.confirm(`Reclaim "${t.name}"?\n\nThis permanently deletes the index built with ${t.model||`that model`}. Switching back to it afterwards means indexing every document again instead of being instant.\n\nThis is the only step here that cannot be undone.`)){o(t.name);try{let n=await yn(e,t.name);if(!n.dropped)throw Error(n.error||`Failed to drop the vector table`);i({title:`Deleted`,description:`Removed '${n.name||t.name}'.`}),r()}catch(e){i({title:`Error`,description:e instanceof Error?e.message:`Failed to delete`,variant:`destructive`})}finally{o(null)}}};return n?(0,Q.jsxs)(`section`,{className:`rounded-lg border border-destructive/40 bg-destructive-subtle p-4`,children:[(0,Q.jsx)(`p`,{className:`text-sm font-medium text-destructive`,children:`Stored indexes unavailable`}),(0,Q.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:n})]}):s.length===0?null:(0,Q.jsx)(gr,{title:`Previous models (${s.length})`,hint:`Indexes built with models you switched away from. They stay on disk so switching back is instant. Deleting one frees the space for good.`,children:(0,Q.jsx)(`div`,{className:`divide-y`,children:s.map(e=>(0,Q.jsxs)(`div`,{className:`flex items-center justify-between gap-4 py-2 first:pt-0 last:pb-0`,children:[(0,Q.jsxs)(`div`,{className:`min-w-0`,children:[(0,Q.jsxs)(`p`,{className:`truncate font-mono text-xs`,children:[e.model||`unknown model`,e.dim?` · ${e.dim}-d`:``]}),(0,Q.jsxs)(`p`,{className:`truncate font-mono text-[11px] text-muted-foreground`,children:[`└─ `,e.name]})]}),(0,Q.jsxs)(H,{type:`button`,size:`sm`,variant:`ghost`,className:`text-destructive hover:text-destructive`,disabled:a===e.name,onClick:()=>c(e),title:`Permanently delete the index built with this model`,children:[(0,Q.jsx)(M,{className:`mr-1.5 h-3.5 w-3.5`}),a===e.name?`Deleting…`:`Delete`]})]},e.name))})})}function br({workspaceId:e,workspaceName:t,spaces:n,onDone:r}){let{showToast:i}=K(),[a,o]=(0,Z.useState)(``),[s,c]=(0,Z.useState)(``),[l,u]=(0,Z.useState)(!1),[d,f]=(0,Z.useState)(!1);return(0,Q.jsxs)(gr,{title:`Index existing documents`,hint:`Add documents that are not in meaning search yet, for example after switching models. Limit it to one folder to try a model on a small set first.`,children:[(0,Q.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,Q.jsxs)(`div`,{className:`space-y-1`,children:[(0,Q.jsx)(`label`,{className:`text-xs font-medium`,children:`Content type`}),(0,Q.jsxs)(`select`,{className:`${hr} w-full`,value:a,onChange:e=>o(e.target.value),children:[(0,Q.jsx)(`option`,{value:``,children:`All content types`}),n.map(e=>(0,Q.jsx)(`option`,{value:e,children:gn(e)},e))]})]}),(0,Q.jsx)(_r,{workspaceName:t,value:s,onChange:c,disabled:d})]}),(0,Q.jsxs)(`label`,{className:`mt-3 flex items-start gap-2 text-xs`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,className:`mt-0.5`,checked:l,onChange:e=>u(e.target.checked)}),(0,Q.jsxs)(`span`,{children:[`Also redo documents that are already indexed`,l&&s.trim()&&(0,Q.jsx)(`span`,{className:`mt-1 block text-[11px] text-warning`,children:`Even with a folder limit, this clears the whole index for the chosen content type, not just that folder. Leave it off unless you want to redo everything.`})]})]}),(0,Q.jsx)(H,{type:`button`,size:`sm`,className:`mt-3`,onClick:async()=>{f(!0);try{let t=await mn(e,{space:a||void 0,reindex:l,scope:s.trim()||void 0});t.ingestDisabled?i({title:`Indexing is turned off on the server`,description:`CANVAS_INFERD_INGEST_DISABLED=true: nothing was queued. What is already indexed still works.`,variant:`destructive`}):i({title:`Indexing queued`,description:`${t.enqueued.toLocaleString()} document(s) queued${t.scope?` under ${t.scope}`:``}. The status line above shows progress.`}),r()}catch(e){i({title:`Indexing failed to start`,description:e instanceof Error?e.message:`Failed to queue`,variant:`destructive`})}finally{f(!1)}},disabled:d,children:d?`Queueing…`:`Start indexing`})]})}var xr=[{provider:`blip`,model:`HuggingFaceTB/SmolVLM-500M-Instruct`,task:`instruct`,label:`SmolVLM 500M: follows your instructions (recommended)`,note:`About 500 MB. Follows the instructions below, so you can ask for what matters to you, such as style, materials or setting.`},{provider:`blip`,model:`HuggingFaceTB/SmolVLM-256M-Instruct`,task:`instruct`,label:`SmolVLM 256M: smaller, follows your instructions`,note:`About 250 MB. Same instructions, less detail; for servers short on memory.`},{provider:`blip`,model:`onnx-community/Florence-2-base-ft`,task:`florence2`,label:`Florence-2 base: detailed, fixed style`,note:`Writes several detailed sentences, but ignores instructions.`},{provider:`blip`,model:`Xenova/vit-gpt2-image-captioning`,task:`caption`,label:`vit-gpt2: one short sentence (smallest)`,note:`One terse sentence per image, sometimes repetitive. Uses the least memory.`}],Sr=`custom`,Cr=[{value:`instruct`,label:`Follows instructions (instruct VLM)`},{value:`florence2`,label:`Florence-2 family`},{value:`caption`,label:`Plain captioner, image only`}],wr=`Describe this photograph in two or three sentences. If it shows a building or interior, name the architectural style, the main materials and the setting. Describe only what is visible.`;function Tr({workspaceId:e,workspaceName:t,config:n,saving:r,onSave:i}){let{showToast:a}=K(),o=n.workspace||{},s=n.effective||{},c=xr[0],l=o.summarize?.image||s.summarize?.image||{},[u,d]=(0,Z.useState)(()=>s.summarize?.image?.enabled===!0||o.summarize?.image?.enabled===!0),[f,p]=(0,Z.useState)(()=>{let e=xr.find(e=>e.provider===(l.provider||c.provider)&&e.model===l.model);return e?`${e.provider}::${e.model}`:l.model?Sr:`${c.provider}::${c.model}`}),[m,h]=(0,Z.useState)(()=>xr.some(e=>e.model===l.model)?``:l.model||``),[g,_]=(0,Z.useState)(()=>l.task||`instruct`),[v,y]=(0,Z.useState)(()=>l.prompt||``),[b,x]=(0,Z.useState)(!1),[S,C]=(0,Z.useState)(null),[w,T]=(0,Z.useState)(!1),[E,ee]=(0,Z.useState)(!1),[D,te]=(0,Z.useState)(!1),[O,ne]=(0,Z.useState)(``),k=xr.find(e=>`${e.provider}::${e.model}`===f),re=f===Sr,A=re?{provider:c.provider,model:m.trim(),task:g,label:`Custom`,note:``}:k||c,ie=A.task===`instruct`,j=(0,Z.useCallback)(()=>bn(e).then(e=>C(e.summarize||null)).catch(()=>{}),[e]);(0,Z.useEffect)(()=>{j();let e=window.setInterval(()=>{C(e=>(e?.running&&j(),e))},2e3);return()=>window.clearInterval(e)},[j]);let M=async()=>{await i({...o,summarize:{...o.summarize||{},image:{enabled:u,provider:A.provider,model:A.model,task:A.task,...ie&&v.trim()?{prompt:v.trim()}:{}}}}),x(!1)},ae=async()=>{ee(!0);try{C(await hn(e)),a({title:`Stopping image descriptions`,description:`The current image finishes first; the rest are left for a later run.`})}catch(e){a({title:`Could not stop`,description:e instanceof Error?e.message:`Failed to stop`,variant:`destructive`})}finally{ee(!1)}},N=async(t=!1)=>{T(!0);try{let n=await vn(e,{force:t,scope:O.trim()||void 0});C(n),a({title:t?`Describing all images again`:`Describing images`,description:`${n.total.toLocaleString()} image(s)${n.scope?` under ${n.scope}`:``}. The first run downloads the model, which can take a few minutes.`})}catch(e){a({title:`Image descriptions failed to start`,description:e instanceof Error?e.message:`Failed to start`,variant:`destructive`})}finally{T(!1)}},P=s.summarize?.image?.enabled===!0,F=S?.running===!0,oe=S?.errors?.[0]?.error;return(0,Q.jsx)(gr,{title:`Image descriptions`,hint:`A vision model writes a few sentences about each image, so you can find photos by what is in them.`,children:(0,Q.jsxs)(`div`,{className:`space-y-3`,children:[(0,Q.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,Q.jsxs)(`label`,{className:`flex items-center gap-2 text-sm`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,checked:u,disabled:r,onChange:e=>{d(e.target.checked),x(!0)}}),`Describe images`]}),(0,Q.jsxs)(`select`,{className:hr,value:f,disabled:r||!u,onChange:e=>{p(e.target.value),x(!0)},children:[xr.map(e=>(0,Q.jsx)(`option`,{value:`${e.provider}::${e.model}`,children:e.label},`${e.provider}::${e.model}`)),(0,Q.jsx)(`option`,{value:Sr,children:`Custom model…`})]}),!re&&(0,Q.jsx)(`span`,{className:`font-mono text-xs text-muted-foreground`,children:A.model})]}),re&&(0,Q.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,Q.jsx)(U,{className:`h-8 w-72 font-mono text-xs`,placeholder:`org/model-id (Hugging Face, ONNX)`,value:m,disabled:r||!u,onChange:e=>{h(e.target.value),x(!0)}}),(0,Q.jsx)(`select`,{className:hr,value:g,disabled:r||!u,onChange:e=>{_(e.target.value),x(!0)},children:Cr.map(e=>(0,Q.jsx)(`option`,{value:e.value,children:e.label},e.value))})]}),u&&A.note&&(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:A.note}),u&&ie&&(0,Q.jsxs)(`div`,{className:`space-y-1`,children:[(0,Q.jsx)(`textarea`,{className:`w-full rounded-md border border-input bg-transparent p-2 text-xs outline-none focus-visible:ring-1 focus-visible:ring-ring`,rows:3,placeholder:wr,value:v,disabled:r,onChange:e=>{y(e.target.value),x(!0)}}),(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`What to ask about every image. Leave empty to use the default shown above. Descriptions become searchable, so ask for the details you would search by.`})]}),S&&(S.running||S.total>0||S.finishedAt)&&(0,Q.jsxs)(`p`,{className:be(`text-xs`,S.aborted?`text-destructive`:`text-muted-foreground`),children:[F?`Running`:S.aborted?`Stopped`:S.cancelled?`Cancelled`:`Last run`,S.scope?(0,Q.jsxs)(Q.Fragment,{children:[` under `,(0,Q.jsx)(`span`,{className:`font-mono`,children:S.scope})]}):null,`: `,S.described,`/`,S.total,` described`,S.skipped?`, ${S.skipped} skipped`:``,S.failed?`, ${S.failed} failed`:``,S.aborted?`. ${S.abortedReason||`The model stopped working`}. The remaining images were not tried; run again to retry.`:S.cancelled?`. Stopped by you. The remaining images were left untouched; run again to continue.`:oe?`. ${oe}`:``]}),(0,Q.jsx)(_r,{workspaceName:t,value:O,onChange:ne,disabled:r||F}),(0,Q.jsxs)(`label`,{className:`flex items-start gap-2 text-xs`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,className:`mt-0.5`,checked:D,disabled:r||F,onChange:e=>te(e.target.checked)}),(0,Q.jsxs)(`span`,{children:[`Also redo images that already have a description`,D&&(0,Q.jsxs)(`span`,{className:`mt-1 block text-[11px] text-warning`,children:[`Replaces existing descriptions`,O.trim()?` in that folder`:``,`, including ones written by another model. Leave this off to describe only images that have none yet.`]})]})]}),(0,Q.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Turn on and save, then run. Descriptions are generated on this server; the first run downloads the model.`}),(0,Q.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,Q.jsx)(H,{size:`sm`,variant:`outline`,onClick:()=>void M(),disabled:r||!b,children:`Save`}),(0,Q.jsx)(H,{size:`sm`,onClick:()=>void N(D),disabled:r||b||w||F||!P,title:P?b?`Save your changes first`:D?`Describe every image again, replacing existing descriptions`:`Describe images that have no description yet`:`Turn on image descriptions and save first`,children:F||w?`Running…`:D?`Describe all again`:`Describe missing`}),F&&(0,Q.jsx)(H,{size:`sm`,variant:`destructive`,onClick:()=>void ae(),disabled:E,title:`Finish the current image, then stop. The rest are left for later.`,children:E?`Stopping…`:`Stop`})]})]})]})})}function Er({workspaceId:e,workspaceName:t}){let{showToast:n}=K(),[r,i]=(0,Z.useState)(null),[a,o]=(0,Z.useState)([]),[s,c]=(0,Z.useState)(),[l,u]=(0,Z.useState)(!0),[d,f]=(0,Z.useState)(!1),[p,m]=(0,Z.useState)(null),[h,g]=(0,Z.useState)([]),[_,v]=(0,Z.useState)(0),y=(0,Z.useCallback)(()=>_n(e).then(e=>{i(e),m(null)}).catch(e=>m(e instanceof Error?e.message:`Failed to load the search settings`)).finally(()=>u(!1)),[e]),b=(0,Z.useCallback)(()=>fn(e).then(e=>{o(e.tables||[]),c(e.error)}).catch(e=>c(e instanceof Error?e.message:`Failed to list stored indexes`)),[e]);(0,Z.useEffect)(()=>{y(),b()},[y,b]);let x=()=>{u(!0),y(),b(),v(e=>e+1)},S=async t=>{f(!0);try{let r=await pn(e,t);g(r.movedSpaces||[]),r.movedSpaces?.length?n({title:`Saved: now index your existing documents`,description:`${r.movedSpaces.map(gn).join(`, `)}: new model in use. New documents use it right away; existing ones need indexing (button on the row).`}):r.applied===!1?n({title:`Saved: applies on next start`,description:`The workspace is not running, so the changes take effect when it starts.`}):n({title:`Saved`,description:`Search settings updated.`}),await y(),await b()}catch(e){n({title:`Save failed`,description:e instanceof Error?e.message:`Failed to save`,variant:`destructive`})}finally{f(!1)}},C=async t=>{try{let r=await mn(e,{space:t});if(r.ingestDisabled){n({title:`Indexing is turned off on the server`,description:`CANVAS_INFERD_INGEST_DISABLED=true: nothing was queued. What is already indexed still works.`,variant:`destructive`});return}n({title:`Indexing ${gn(t).toLowerCase()}`,description:`${r.enqueued.toLocaleString()} document(s) queued. The status line above shows progress.`}),g(e=>e.filter(e=>e!==t)),v(e=>e+1),b()}catch(e){n({title:`Indexing failed to start`,description:e instanceof Error?e.message:`Failed to queue`,variant:`destructive`})}};if(l)return(0,Q.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-muted-foreground`,children:[(0,Q.jsx)(R,{className:`h-4 w-4 animate-spin`}),`Loading search settings…`]});if(p||!r)return(0,Q.jsxs)(`div`,{className:`space-y-3`,children:[(0,Q.jsxs)(`div`,{className:`rounded-lg border border-destructive/40 bg-destructive-subtle p-4 text-sm`,children:[(0,Q.jsx)(`p`,{className:`font-medium text-destructive`,children:`Search settings unavailable`}),(0,Q.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:p||`No config returned.`})]}),(0,Q.jsx)(H,{type:`button`,size:`sm`,variant:`outline`,onClick:x,children:`Try again`})]});let w=Object.keys(r.effective.spaces||{}).sort();return(0,Q.jsxs)(`div`,{className:`space-y-5`,children:[(0,Q.jsx)(vr,{workspaceId:e,workspaceName:t,refreshKey:_,onRefresh:x}),(0,Q.jsx)(xn,{value:r.workspace||{},effective:r.effective||{},inherited:r.inherited||{},resolvedSpaces:r.spaces,invalid:r.invalid,attention:h,onFill:C,saving:d,saveLabel:`Save models`,onSave:S},JSON.stringify(r.workspace)),(0,Q.jsxs)(`div`,{className:`space-y-3`,children:[(0,Q.jsx)(Tr,{workspaceId:e,workspaceName:t,config:r,saving:d,onSave:S},`summarize:${JSON.stringify(r.workspace?.summarize||{})}`),(0,Q.jsx)(br,{workspaceId:e,workspaceName:t,spaces:w,onDone:()=>{b(),v(e=>e+1)}}),(0,Q.jsx)(yr,{workspaceId:e,tables:a,error:s,onChanged:()=>{b()}})]}),(0,Q.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`These settings are saved with the workspace (in its `,(0,Q.jsx)(`span`,{className:`font-mono`,children:`workspace.json`}),`), so they move with it. Anything not set here comes from your personal defaults, then the server's. Changes apply immediately, with no restart.`]})]})}function Dr(e){let n=(e||``).split(`.`).pop()?.toLowerCase();switch(n){case`js`:case`mjs`:case`ts`:return[a({typescript:n===`ts`})];case`json`:return[i()];case`sh`:case`bash`:return[t.define(o)];default:return[]}}function Or({value:e,onChange:t,path:r,className:i=``}){let a=(0,Z.useMemo)(()=>Dr(r),[r]),{resolvedScheme:o}=$t();return(0,Q.jsx)(n,{value:e,onChange:t,extensions:a,theme:o===`dark`?`dark`:`light`,className:i,basicSetup:{lineNumbers:!0,foldGutter:!0,highlightActiveLine:!0,bracketMatching:!0,autocompletion:!1}})}function kr(e,t){if(![`download`,`store`].includes(e.action)||e.recursive===!0&&!t)return null;let n=String(e.folder||``);return n.includes(`{{`)?null:[n,(e.recursive===!0?e.pathMode===`full`?t?.path:t?.rel:``)||``].join(`/`).split(`/`).filter(e=>e&&e!==`.`&&e!==`..`).join(`/`)}function Ar(e,t){if(![`download`,`store`].includes(e.action)||typeof e.to!=`string`)return null;if(e.recursive===!0&&!t)return`Missing filing path — decline and trigger the rule again`;let n=kr(e,t);return n===null?null:`${e.to}/${n}`}function jr(e,t){let n=kr(e,t);if(n===null||e.recursive!==!0||e.autoLink===!0)return{...e};let r={...e,folder:n};return delete r.recursive,delete r.pathMode,r}function Mr(e,t){let n=structuredClone({actions:e.actions});for(let[r,i]of Object.entries(t)){if(!e.editable.includes(r))continue;let t=r.split(`.`);if(t[0]!==`actions`||t.some(e=>[`__proto__`,`prototype`,`constructor`].includes(e)))continue;let a=n;for(let e of t.slice(0,-1)){if(!a[e]||typeof a[e]!=`object`){a={};break}a=a[e]}a[t[t.length-1]]=i}return n.actions}var Nr=[`pending`,`approved`,`declined`,`failed`,`expired`,`all`],Pr={pending:`text-warning dark:text-warning`,approved:`text-success dark:text-success`,declined:`text-muted-foreground`,failed:`text-destructive`,expired:`text-muted-foreground line-through`};function Fr(e){let t=Date.now()-new Date(e).getTime(),n=Math.floor(t/6e4);if(n<1)return`now`;if(n<60)return`${n}m`;let r=Math.floor(n/60);return r<24?`${r}h`:`${Math.floor(r/24)}d`}function Ir(e,t){return t.split(`.`).reduce((e,t)=>typeof e==`object`&&e?e[t]:void 0,e)}function Lr(e){let t=e.split(`.`);return t.slice(Math.max(t.length-2,2)).join(`.`)}var Rr=/(body|content|message|text|prompt)$/i;function zr({workspaceId:e,id:t,children:n}){let{open:r}=Ct(),{showToast:i}=K(),[a,o]=(0,Z.useState)(!1),s=async n=>{n.stopPropagation(),o(!0);try{r(await et(e,t),e)}catch(e){i({title:`Document ${t} not available`,description:e instanceof Error?e.message:void 0,variant:`destructive`})}finally{o(!1)}};return(0,Q.jsx)(`button`,{type:`button`,disabled:a,onClick:e=>void s(e),className:`text-primary underline-offset-2 hover:underline disabled:opacity-60`,title:`Open document ${t}`,children:n??`doc ${t}`})}function Br({workspaceId:e,text:t}){let n=t.split(/(\bdoc \d+\b)/);return(0,Q.jsx)(Q.Fragment,{children:n.map((t,n)=>{let r=/^doc (\d+)$/.exec(t);return r?(0,Q.jsx)(zr,{workspaceId:e,id:Number(r[1])},n):(0,Q.jsx)(Z.Fragment,{children:t},n)})})}function Vr({action:e,amend:t,onAmend:n}){return e.editable?.length?(0,Q.jsx)(`div`,{className:`space-y-2`,children:e.editable.map(r=>{let i=Ir(e,r),a=typeof i==`string`,o=r in t?t[r]:i,s=a?String(o??``):JSON.stringify(o,null,2),c=a&&(Rr.test(r)||s.length>80);return(0,Q.jsxs)(`label`,{className:`block text-xs`,children:[(0,Q.jsxs)(`span`,{className:`font-medium text-muted-foreground`,children:[Lr(r),(0,Q.jsx)(`span`,{className:`ml-1.5 font-mono text-[10px] opacity-60`,children:r}),r in t&&(0,Q.jsx)(`span`,{className:`ml-1.5 text-warning dark:text-warning`,children:`edited`})]}),c?(0,Q.jsx)(`textarea`,{className:`mt-1 w-full rounded-md border bg-background px-2 py-1.5 font-mono text-xs outline-none focus:ring-2 focus:ring-ring min-h-[100px]`,value:s,onChange:e=>n(r,e.target.value)}):(0,Q.jsx)(`input`,{className:`mt-1 w-full h-8 rounded-md border bg-background px-2 font-mono text-xs outline-none focus:ring-2 focus:ring-ring`,value:s,onChange:e=>{if(a){n(r,e.target.value);return}try{n(r,JSON.parse(e.target.value))}catch{n(r,e.target.value)}}})]},r)})}):null}function Hr({workspaceId:e,onPendingCount:t}){let{showToast:n}=K(),r=Sn(),[i,a]=(0,Z.useState)(`pending`),[o,s]=(0,Z.useState)([]),[c,l]=(0,Z.useState)(!0),[u,d]=(0,Z.useState)(new Set),[f,p]=(0,Z.useState)(null),[m,h]=(0,Z.useState)({}),[g,_]=(0,Z.useState)(!1),v=(0,Z.useCallback)(()=>At(e,{status:i===`all`?void 0:i,limit:200}).then(e=>{s(e),d(t=>new Set(e.filter(e=>e.status===`pending`&&t.has(e.actionId)).map(e=>e.actionId))),t?.(i===`pending`?e.length:e.filter(e=>e.status===`pending`).length)}).catch(()=>{n({title:`Error`,description:`Failed to load pending actions`,variant:`destructive`})}).finally(()=>l(!1)),[e,i]),y=(0,Z.useCallback)(async()=>{l(!0),await v()},[v]),[b,x]=(0,Z.useState)(`${e}|${i}`),S=`${e}|${i}`;S!==b&&(x(S),l(!0)),(0,Z.useEffect)(()=>{v()},[v]),Cn(r,`workspace:${e}`,(0,Z.useMemo)(()=>{let e=()=>{y()};return{"action.proposed":e,"action.approved":e,"action.declined":e,"action.failed":e}},[y]));let C=o.filter(e=>e.status===`pending`),T=C.length>0&&C.every(e=>u.has(e.actionId)),E=()=>{d(T?new Set:new Set(C.map(e=>e.actionId)))},ee=e=>{d(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},D=(e,t,n)=>{h(r=>({...r,[e]:{...r[e],[t]:n}}))},te=async(t,r)=>{if(!(!t.length&&!r.length)){_(!0);try{let i=await Lt(e,{approve:t.map(e=>{let t=m[e];return t&&Object.keys(t).length?{actionId:e,amend:t}:e}),decline:r}),a=i.results.filter(e=>e.status===`error`||e.status===`failed`);a.length?n({title:`${a.length} of ${i.decided} failed`,description:a.map(e=>`${e.actionId}: ${e.error??`execution failed`}`).join(`; `),variant:`destructive`}):n({title:t.length&&r.length?`Decisions applied`:t.length?`Approved ${t.length}`:`Declined ${r.length}`,description:t.length?`Approved actions executed with their original provenance.`:void 0}),h(e=>{let n={...e};for(let e of[...t,...r])delete n[e];return n}),d(new Set),f&&[...t,...r].includes(f)&&p(null),await y()}catch(e){n({title:`Decision failed`,description:e instanceof Error?e.message:`Unknown error`,variant:`destructive`})}finally{_(!1)}}};return(0,Q.jsxs)(`div`,{className:`space-y-3`,children:[(0,Q.jsxs)(`div`,{className:`flex items-center justify-between gap-2 flex-wrap`,children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`select`,{className:`h-8 rounded-md border bg-background px-2 text-xs outline-none focus:ring-2 focus:ring-ring`,value:i,onChange:e=>a(e.target.value),children:Nr.map(e=>(0,Q.jsx)(`option`,{value:e,children:e},e))}),(0,Q.jsx)(H,{size:`sm`,variant:`ghost`,onClick:()=>void y(),title:`Reload`,children:(0,Q.jsx)(R,{className:`h-4 w-4`})})]}),u.size>0&&(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[u.size,` selected`]}),(0,Q.jsxs)(H,{size:`sm`,disabled:g,onClick:()=>void te([...u],[]),children:[(0,Q.jsx)(j,{className:`mr-1 h-3.5 w-3.5`}),` Approve`]}),(0,Q.jsxs)(H,{size:`sm`,variant:`outline`,disabled:g,onClick:()=>void te([],[...u]),children:[(0,Q.jsx)(w,{className:`mr-1 h-3.5 w-3.5`}),` Decline`]})]})]}),(0,Q.jsx)(`div`,{className:`border rounded-lg overflow-auto max-h-[560px]`,children:c?(0,Q.jsx)(`p`,{className:`text-sm text-muted-foreground p-3`,children:`Loading...`}):o.length===0?(0,Q.jsx)(`p`,{className:`text-sm text-muted-foreground p-3`,children:i===`pending`?`Nothing waiting for review. Rules or hooks with approval enabled queue their actions here.`:`No ${i===`all`?``:i+` `}actions recorded.`}):(0,Q.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,Q.jsx)(`thead`,{className:`text-xs text-muted-foreground border-b sticky top-0 bg-background`,children:(0,Q.jsxs)(`tr`,{children:[(0,Q.jsx)(`th`,{className:`px-3 py-2 w-8`,children:C.length>0&&(0,Q.jsx)(`input`,{type:`checkbox`,checked:T,onChange:E,title:`Select all pending`})}),(0,Q.jsx)(`th`,{className:`text-left font-medium px-3 py-2`,children:`Proposed action`}),(0,Q.jsx)(`th`,{className:`text-left font-medium px-3 py-2`,children:`Handler`}),(0,Q.jsx)(`th`,{className:`text-left font-medium px-3 py-2`,children:`Age`}),(0,Q.jsx)(`th`,{className:`text-left font-medium px-3 py-2`,children:`Status`}),(0,Q.jsx)(`th`,{className:`px-2 py-2 w-40`})]})}),(0,Q.jsx)(`tbody`,{children:o.map(t=>{let n=t.status===`pending`||t.status===`failed`,r=f===t.actionId,i=r?Mr(t,n?m[t.actionId]??{}:{}):t.actions,a=t.envelope?.payload?.document;return(0,Q.jsxs)(Z.Fragment,{children:[(0,Q.jsxs)(`tr`,{className:`border-b last:border-0 align-top hover:bg-muted/40 cursor-pointer`,onClick:()=>p(r?null:t.actionId),children:[(0,Q.jsx)(`td`,{className:`px-3 py-2`,onClick:e=>e.stopPropagation(),children:t.status===`pending`&&(0,Q.jsx)(`input`,{type:`checkbox`,checked:u.has(t.actionId),onChange:()=>ee(t.actionId)})}),(0,Q.jsxs)(`td`,{className:`px-3 py-2`,children:[(0,Q.jsxs)(`span`,{className:`flex items-center gap-1 font-medium`,children:[r?(0,Q.jsx)(re,{className:`h-3 w-3 shrink-0`}):(0,Q.jsx)(A,{className:`h-3 w-3 shrink-0`}),t.title,t.editable?.length>0&&(0,Q.jsx)(`span`,{className:`text-[10px] uppercase tracking-wide rounded bg-muted-foreground/15 px-1 py-0.5 text-muted-foreground shrink-0`,children:`editable`})]}),t.summary&&(0,Q.jsx)(`span`,{className:`block text-xs text-muted-foreground pl-4`,children:(0,Q.jsx)(Br,{workspaceId:e,text:t.summary})})]}),(0,Q.jsxs)(`td`,{className:`px-3 py-2 font-mono text-xs whitespace-nowrap`,children:[(0,Q.jsxs)(`span`,{className:`text-muted-foreground`,children:[t.handlerType,`:`]}),t.handler,t.event&&(0,Q.jsxs)(`span`,{className:`block text-muted-foreground`,children:[t.event,a?.id!=null&&(0,Q.jsxs)(Q.Fragment,{children:[` · `,(0,Q.jsx)(zr,{workspaceId:e,id:a.id})]})]})]}),(0,Q.jsx)(`td`,{className:`px-3 py-2 text-xs whitespace-nowrap`,title:t.ts,children:Fr(t.ts)}),(0,Q.jsxs)(`td`,{className:`px-3 py-2 text-xs`,children:[(0,Q.jsx)(`span`,{className:Pr[t.status],children:t.status}),t.amended&&(0,Q.jsx)(`span`,{className:`block text-muted-foreground`,children:`amended`}),t.decidedBy&&(0,Q.jsx)(`span`,{className:`block text-muted-foreground truncate max-w-[120px]`,title:t.decidedBy,children:t.decidedBy})]}),(0,Q.jsx)(`td`,{className:`px-2 py-2 whitespace-nowrap text-right`,onClick:e=>e.stopPropagation(),children:n&&(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(H,{size:`sm`,className:`h-7 px-2`,disabled:g,title:t.status===`failed`?`Retry (re-approve)`:`Approve and execute`,onClick:()=>void te([t.actionId],[]),children:(0,Q.jsx)(j,{className:`h-3.5 w-3.5`})}),t.status===`pending`&&(0,Q.jsx)(H,{size:`sm`,variant:`ghost`,className:`h-7 px-2 text-muted-foreground`,disabled:g,title:`Decline`,onClick:()=>void te([],[t.actionId]),children:(0,Q.jsx)(w,{className:`h-3.5 w-3.5`})})]})})]}),r&&(0,Q.jsxs)(`tr`,{className:`border-b last:border-0 bg-muted/20`,children:[(0,Q.jsx)(`td`,{className:`px-3 py-3`}),(0,Q.jsxs)(`td`,{className:`px-3 py-3 space-y-3`,colSpan:5,children:[n&&t.editable?.length>0&&(0,Q.jsx)(Vr,{action:t,amend:m[t.actionId]??{},onAmend:(e,n)=>D(t.actionId,e,n)}),i.map((e,n)=>{let r=Ar(e,t.pathMatch);return r&&(0,Q.jsxs)(`p`,{className:`text-xs`,children:[(0,Q.jsx)(`span`,{className:`font-medium`,children:`Destination folder: `}),(0,Q.jsx)(`span`,{className:`font-mono break-all`,children:r})]},n)}),(0,Q.jsxs)(`div`,{children:[(0,Q.jsx)(`span`,{className:`text-xs font-medium text-muted-foreground`,children:`Actions on approve`}),(0,Q.jsx)(`pre`,{className:`mt-1 rounded border bg-background p-2 font-mono text-xs overflow-auto max-h-56`,children:JSON.stringify(i.map(e=>jr(e,t.pathMatch)),null,2)})]}),(0,Q.jsxs)(`details`,{className:`text-xs text-muted-foreground`,children:[(0,Q.jsx)(`summary`,{className:`cursor-pointer`,children:`Rule action settings`}),(0,Q.jsx)(`pre`,{className:`mt-1 rounded border bg-background p-2 font-mono overflow-auto max-h-56`,children:JSON.stringify(i,null,2)})]}),t.result&&t.result.length>0&&(0,Q.jsx)(`div`,{className:`text-xs font-mono`,children:t.result.map((e,t)=>(0,Q.jsxs)(`span`,{className:`mr-2 ${e.status===`error`?`text-destructive`:`text-muted-foreground`}`,children:[e.action,`:`,e.status,e.error?` (${e.error})`:``]},t))}),(0,Q.jsxs)(`p`,{className:`text-[11px] text-muted-foreground font-mono`,children:[t.actionId,` · origin `,t.provenance?.origin,t.provenance?.causedBy?` · causedBy ${t.provenance.causedBy}`:``,t.expiresAt?` · expires ${new Date(t.expiresAt).toLocaleString()}`:``]})]})]})]},t.actionId)})})]})})]})}var Ur=`#!/usr/bin/env bash
|
|
1
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{a as t,i as n,l as r,n as i,r as a,t as o,u as s}from"./code-editor-BOIngd5F.js";import{_t as c}from"./react-BHzhHVTZ.js";import{_ as l,g as u,v as d}from"./chunk-62JRHF6Z-vspAGgtK.js";import{An as f,Bn as p,Bt as m,Cn as h,Ct as g,Fn as _,G as v,H as y,It as b,J as x,Jn as S,Kt as C,L as w,Lr as T,Mt as E,Nt as ee,Pt as D,Qt as te,Tr as O,Tt as ne,U as k,Ur as re,Vr as A,Wn as ie,Wr as j,X as M,Xn as ae,Xt as N,Z as P,Zn as F,_i as oe,_t as se,an as ce,bi as le,br as I,bt as ue,cn as de,ct as fe,fr as pe,ft as L,kt as R,mr as me,ni as he,pn as z,pr as ge,pt as _e,rt as ve,st as ye,vn as B,vr as V}from"./ui-CDoK3F3U.js";import{t as be}from"./utils-2pl1SbIp.js";import{t as H}from"./button-SeUZ_Pvi.js";import{t as U}from"./input-BOtCd4HP.js";import{t as W}from"./label-BSTdjCWU.js";import{c as xe,l as Se,t as G}from"./api-CA6WiiYM.js";import{t as Ce}from"./socket-CtH3EU9m.js";import{n as K}from"./use-toast-BlLDqSUO.js";import{t as we}from"./LinkToCard-DGpvNE_V.js";import{$ as Te,A as Ee,Ct as De,Et as Oe,H as q,Ht as ke,I as Ae,Kt as je,L as Me,Nt as Ne,Ot as Pe,P as J,T as Fe,Ut as Ie,W as Y,_n as Le,an as Re,at as ze,ct as Be,d as Ve,dn as He,en as Ue,et as X,f as We,fn as Ge,gn as Ke,ht as qe,in as Je,k as Ye,n as Xe,on as Ze,r as Qe,tn as $e,tt as et,un as tt,vt as nt,yn as rt,yt as it}from"./workspace-cv6Hrfhh.js";import{a as at,c as ot,i as st,n as ct,o as lt,r as ut,s as dt,t as ft}from"./alert-dialog-CFeuDt0T.js";import{t as pt}from"./use-mobile-Db-vWu9Y.js";import{t as mt}from"./useEscapeClose-DR_xKT_k.js";import{o as ht}from"./layer-style-Byl5LNFR.js";import{i as gt,t as _t}from"./color-DFEH4BfK.js";import{a as vt,o as yt,s as bt,t as xt}from"./MessageComposerDialog-CdPp-3GR.js";import{n as St}from"./LinkToSidePanel-eCy3nW4R.js";import{n as Ct}from"./use-document-modal-PG8bQyIB.js";import{A as wt,B as Tt,D as Et,E as Dt,F as Ot,H as kt,I as At,L as jt,M as Mt,N as Nt,O as Pt,P as Ft,R as It,S as Lt,T as Rt,U as zt,V as Bt,b as Vt,d as Ht,f as Ut,h as Wt,j as Gt,m as Kt,p as qt,t as Jt,w as Yt,x as Xt}from"./backend-sync-progress-m7wUKTJn.js";import{t as Zt}from"./workspace-access-C9nZlBBZ.js";import{i as Qt}from"./use-menu-DIP1zh7I.js";import{t as $t}from"./use-theme-DaxpiICf.js";import{_t as en,at as tn,bt as nn,ct as rn,it as an,lt as on,ot as sn,st as cn,ut as ln,wt as un}from"./index-CXPA9Fj8.js";import{n as dn}from"./page-header-DrDt1sQ2.js";import{c as fn,f as pn,l as mn,m as hn,n as gn,o as _n,p as vn,r as yn,s as bn,t as xn}from"./inferd-config-editor-B8x_XPOt.js";import{n as Sn,t as Cn}from"./useSocketSubscription-ifW-vnlb.js";import{a as wn,n as Tn,o as En,r as Dn,t as On}from"./devices-CAa1bRxk.js";import{a as kn,i as An,n as jn,s as Mn,t as Nn}from"./query-debug-DhboV3qX.js";import{a as Pn,i as Fn,r as In,t as Ln}from"./workspace-import-form-D5qPcNFq.js";var Z=e(s(),1),Rn=`workspace:backups`,zn=e=>`${xe.workspaces}/${encodeURIComponent(e)}/db/backups`,Bn=e=>G.get(zn(e)),Vn=e=>G.post(zn(e),{action:`backup`}),Hn=(e,t)=>G.post(zn(e),{action:`restore`,backupId:t,confirm:!0}),Un=new Map;function Wn(e,t,n){let r=JSON.stringify([t,n.id]),i=Un.get(r);if(i)return i;let a=(async()=>{let r=n.action===`restore`,i=e({title:r?`Restoring workspace database`:`Backing up workspace database`,description:r?`Stopping the workspace and preserving its current database…`:`Copying and verifying all datasets…`});try{let e=n;for(;e.status===`running`;){let n=await Bn(t),r=n.jobs.find(t=>t.id===e.id);if(!r)throw Error(`The server restarted. Refresh the backup list to check the result.`);e=r,window.dispatchEvent(new CustomEvent(Rn,{detail:{workspace:t,status:n}})),e.status===`running`&&await new Promise(e=>setTimeout(e,1500))}if(e.status===`failed`)throw Error(e.error||`Database operation failed`);i.done({title:r?`Workspace database restored`:`Workspace backup verified`,description:r?`The workspace is stopped. Start it when you are ready; search indexes will rebuild.`:`Documents, relations and virtual tree placements are saved.`})}catch(e){throw i.fail({title:`Workspace backup needs attention`,description:e instanceof Error?e.message:String(e),variant:`destructive`}),e}})();return Un.set(r,a),a.finally(()=>Un.delete(r)).catch(()=>{}),a}var Q=r(),Gn={startup:`Startup`,hourly:`Hourly`,manual:`Manual`,"pre-restore":`Before restore`};function Kn({workspaceId:e,onRestored:t}){let{showToast:n,showProgress:r}=K(),[i,a]=(0,Z.useState)(null),[o,s]=(0,Z.useState)(null),[c,l]=(0,Z.useState)(null),[u,d]=(0,Z.useState)(!1),f=(0,Z.useRef)(!1),p=(0,Z.useRef)(!1),m=(0,Z.useRef)(0),h=(0,Z.useCallback)(()=>{let t=++m.current;return Bn(e).then(n=>{if(!(!f.current||t!==m.current)){a(n),s(null);for(let t of n.jobs.filter(e=>e.status===`running`))Wn(r,e,t).catch(()=>{})}}).catch(e=>{f.current&&t===m.current&&s(e instanceof Error?e.message:String(e))})},[e,r]);(0,Z.useEffect)(()=>{f.current=!0,h();let t=t=>{let n=t.detail;n.workspace===e&&a(n.status)};return window.addEventListener(Rn,t),()=>{f.current=!1,window.removeEventListener(Rn,t)}},[e,h]);let g=async i=>{if(!p.current){p.current=!0,d(!0);try{let n=i?await Hn(e,i.id):await Vn(e);f.current&&a(e=>e&&{...e,jobs:[n,...e.jobs]}),await Wn(r,e,n),i&&t()}catch(e){n({title:`Database operation did not complete`,description:e instanceof Error?e.message:String(e),variant:`destructive`})}finally{p.current=!1,f.current&&(d(!1),h())}}},_=u||!!i?.jobs.some(e=>e.status===`running`),v=i?.jobs[0];return(0,Q.jsxs)(`div`,{className:`min-w-0 space-y-5`,children:[(0,Q.jsxs)(`section`,{className:`space-y-4 rounded border p-4`,children:[(0,Q.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,Q.jsx)(oe,{className:`h-5 w-5 text-muted-foreground`}),(0,Q.jsx)(`h2`,{className:`font-semibold`,children:`Workspace checkpoints`}),(0,Q.jsxs)(H,{variant:`outline`,size:`sm`,className:`ml-auto`,disabled:_||!i||!!o,onClick:()=>void g(),children:[_?(0,Q.jsx)(z,{className:`mr-2 h-4 w-4 animate-spin`}):(0,Q.jsx)(oe,{className:`mr-2 h-4 w-4`}),`Back up now`]})]}),(0,Q.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Save a checkpoint before a bulk action. Each backup includes every document, relation and virtual tree placement in this workspace’s database.`}),(0,Q.jsxs)(`div`,{className:`flex flex-wrap gap-x-5 gap-y-2 text-sm`,children:[(0,Q.jsxs)(`span`,{children:[(0,Q.jsx)(`strong`,{children:i?.retention.hourly??24}),` hourly backups`]}),(0,Q.jsxs)(`span`,{children:[(0,Q.jsx)(`strong`,{children:i?.retention.startup??14}),` startup backups`]}),(0,Q.jsx)(`span`,{children:`Manual checkpoints kept`})]}),(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Hourly backups run while the workspace is active. These checkpoints cover the database only; files in storage backends and workspace settings need their own backups.`})]}),(0,Q.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,Q.jsxs)(`h2`,{className:`text-sm font-semibold`,children:[`Verified checkpoints`,i?` · ${i.backups.length}`:``]}),(0,Q.jsx)(H,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:()=>void h(),"aria-label":`Refresh backups`,children:(0,Q.jsx)(R,{className:`h-4 w-4`})})]}),o&&(0,Q.jsx)(`p`,{role:`alert`,className:`text-sm text-destructive`,children:o}),v&&(0,Q.jsx)(`p`,{role:`status`,className:`text-sm ${v.status===`failed`?`text-destructive`:`text-muted-foreground`}`,children:v.status===`running`?`Database operation in progress…`:v.status===`failed`?v.error:v.action===`restore`?`Database restored. The workspace is stopped and ready to start.`:`Backup complete and verified.`}),!i&&!o&&(0,Q.jsx)(`p`,{role:`status`,className:`text-sm text-muted-foreground`,children:`Loading backups…`}),i?.backups.length===0&&(0,Q.jsx)(`p`,{className:`rounded border border-dashed p-6 text-sm text-muted-foreground`,children:`No verified checkpoints yet. Create one before your next bulk action.`}),(0,Q.jsx)(`div`,{className:`space-y-2`,children:i?.backups.map(e=>(0,Q.jsxs)(`article`,{className:`flex min-w-0 flex-wrap items-center gap-3 rounded border p-3`,children:[(0,Q.jsx)(j,{className:`h-4 w-4 shrink-0 text-muted-foreground`,"aria-label":`Verified`}),(0,Q.jsxs)(`div`,{className:`min-w-0 flex-1 basis-40`,children:[(0,Q.jsx)(`p`,{className:`text-sm font-medium`,children:new Date(e.createdAt).toLocaleString()}),(0,Q.jsxs)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:[Gn[e.kind],` · `,q(e.bytes),` · `,(e.datasets.documents?.count??0).toLocaleString(),` documents`]})]}),(0,Q.jsxs)(H,{variant:`outline`,size:`sm`,disabled:_,onClick:()=>l(e),children:[(0,Q.jsx)(ne,{className:`mr-2 h-3.5 w-3.5`}),`Restore`]})]},e.id))}),(0,Q.jsx)(ft,{open:!!c,onOpenChange:e=>{e||l(null)},children:(0,Q.jsxs)(st,{className:`max-w-[calc(100vw-2rem)] sm:max-w-lg`,children:[(0,Q.jsxs)(dt,{children:[(0,Q.jsx)(ot,{children:`Restore this workspace checkpoint?`}),(0,Q.jsxs)(at,{children:[`The workspace will stop and its current database will be backed up first. Documents, relations and virtual tree placements will return to `,c?new Date(c.createdAt).toLocaleString():`the selected checkpoint`,`. Files in storage backends and workspace settings will stay as they are. The workspace stays stopped after restoration.`]})]}),(0,Q.jsxs)(lt,{children:[(0,Q.jsx)(ut,{children:`Cancel`}),(0,Q.jsx)(ct,{disabled:_,onClick:()=>{c&&g(c)},children:`Back up current & restore`})]})]})})]})}var qn={collect:`Collect unused blobs`,verify:`Verify integrity`,compact:`Compact index`},Jn=e=>e.status===`queued`||e.status===`running`,Yn=e=>`${xe.workspaces}/${encodeURIComponent(e)}/cache/maintenance`,Xn=e=>G.get(Yn(e)),Zn=(e,t,n)=>G.post(Yn(e),{store:t,action:n,...n===`verify`?{confirm:!0}:{}});function Qn(e){if(e.status===`failed`)return e.error||`Maintenance failed`;if(e.status===`queued`)return`Waiting for active storage operations…`;if(e.status===`running`)return e.action===`verify`?`Reading and checking stored content…`:`Processing the cache index…`;let t=e.result||{};return e.action===`compact`?`${(t.compactedCount||0).toLocaleString()} keys compacted`:e.action===`verify`?`${(t.verifiedContent||0).toLocaleString()} blobs verified · ${(t.badContentCount||0).toLocaleString()} corrupted blobs removed · ${q(t.reclaimedSize||0)} reclaimed`:`${(t.reclaimedCount||0).toLocaleString()} unused blobs removed · ${q(t.reclaimedSize||0)} reclaimed`}var $n=new Map,er=`workspace:cache-maintenance`;function tr(e,t,n){let r=JSON.stringify([t,n.id]),i=$n.get(r);if(i)return i;let a=(async()=>{let r=e({title:qn[n.action],description:`${n.store} · ${Qn(n)}`});try{let e=n;for(;Jn(e);){let i=await Xn(t),a=i.jobs.find(e=>e.id===n.id);if(!a)throw Error(`Maintenance receipt is no longer available. The server may have restarted; refresh the cache settings.`);if(e=a,window.dispatchEvent(new CustomEvent(er,{detail:{workspace:t,status:i}})),!Jn(e))break;r.update({title:qn[e.action],description:`${e.store} · ${Qn(e)}`}),await new Promise(e=>setTimeout(e,2e3))}if(e.status===`failed`)throw Error(Qn(e));r.done({title:`${qn[e.action]} complete`,description:`${e.store} · ${Qn(e)}`})}catch(e){throw r.fail({title:`Cache maintenance needs attention`,description:`${n.store} · ${e instanceof Error?e.message:String(e)}`,variant:`destructive`}),e}})();return $n.set(r,a),a.finally(()=>{$n.get(r)===a&&$n.delete(r)}).catch(()=>{}),a}function nr({workspaceId:e,children:t}){let{showToast:n,showProgress:r}=K(),[i,a]=(0,Z.useState)(null),[o,s]=(0,Z.useState)(`workspace:cache`),[c,l]=(0,Z.useState)(!1),[u,d]=(0,Z.useState)(!1),[f,p]=(0,Z.useState)(null),m=(0,Z.useRef)(!1),h=(0,Z.useRef)(!1),g=(0,Z.useCallback)(()=>Xn(e).then(t=>{if(h.current){a(t),p(null);for(let n of t.jobs.filter(Jn))tr(r,e,n).catch(()=>{})}}).catch(e=>{h.current&&p(e instanceof Error?e.message:`Cannot load maintenance status`)}),[e,r]);(0,Z.useEffect)(()=>{h.current=!0,g();let t=t=>{let{workspace:n,status:r}=t.detail;n===e&&(a(r),p(null))};return window.addEventListener(er,t),()=>{h.current=!1,window.removeEventListener(er,t)}},[e,g]);let _=async t=>{if(!(m.current||i?.jobs.some(Jn))){m.current=!0,l(!0);try{let n=await Zn(e,o,t);h.current&&a(e=>e&&{...e,jobs:[n,...e.jobs.filter(e=>e.id!==n.id)]}),tr(r,e,n).catch(()=>{})}catch(e){n({title:`Could not start maintenance`,description:e instanceof Error?e.message:String(e),variant:`destructive`}),g()}finally{m.current=!1,h.current&&l(!1)}}},v=c||!!i?.jobs.some(Jn),y=i?.stores.find(e=>e.id===o),b=i?.jobs[0];return(0,Q.jsxs)(`section`,{className:`space-y-4 rounded-(--panel-radius) border p-4`,"aria-label":`Workspace cache maintenance`,children:[(0,Q.jsxs)(`div`,{className:`flex flex-wrap items-start justify-between gap-3`,children:[(0,Q.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Q.jsxs)(`h2`,{className:`flex items-center gap-2 text-sm font-semibold`,children:[(0,Q.jsx)(I,{className:`h-4 w-4 shrink-0`}),`Workspace cache`]}),(0,Q.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:`Thumbnails, cached resources and pending transfers. Maintenance runs only when requested.`})]}),t&&(0,Q.jsx)(`fieldset`,{disabled:v,children:t})]}),(0,Q.jsxs)(`div`,{className:`space-y-3 border-t pt-3`,children:[(0,Q.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,Q.jsx)(`label`,{htmlFor:`cache-maintenance-store`,className:`text-xs font-medium`,children:`Store`}),(0,Q.jsxs)(`select`,{id:`cache-maintenance-store`,value:o,onChange:e=>s(e.target.value),disabled:v,className:`min-w-0 max-w-full rounded-md border bg-background px-2 py-1.5 text-xs`,children:[(0,Q.jsx)(`option`,{value:`workspace:cache`,children:`workspace:cache`}),(0,Q.jsx)(`option`,{value:`workspace:data`,children:`workspace:data`})]}),(0,Q.jsx)(H,{type:`button`,variant:`ghost`,size:`icon`,onClick:()=>void g(),"aria-label":`Refresh cache maintenance status`,className:`ml-auto h-8 w-8`,children:(0,Q.jsx)(R,{className:`h-3.5 w-3.5`})})]}),(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:o===`workspace:data`?`Managed document blobs. Referenced content is kept during collection.`:`Working cache, including content awaiting transfer. Referenced content is kept during collection.`}),(0,Q.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,Q.jsxs)(H,{type:`button`,variant:`outline`,size:`sm`,disabled:v||!y?.canCollect||!!f,onClick:()=>void _(`collect`),children:[(0,Q.jsx)(M,{className:`mr-2 h-3.5 w-3.5`}),`Collect unused blobs`]}),(0,Q.jsxs)(H,{type:`button`,variant:`outline`,size:`sm`,disabled:v||!y?.canCompact||!!f,onClick:()=>void _(`compact`),children:[(0,Q.jsx)(oe,{className:`mr-2 h-3.5 w-3.5`}),`Compact index`]}),(0,Q.jsxs)(H,{type:`button`,variant:`outline`,size:`sm`,disabled:v||!y?.canVerify||!!f,onClick:()=>d(!0),children:[(0,Q.jsx)(L,{className:`mr-2 h-3.5 w-3.5`}),`Verify integrity`]})]}),(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Collection removes unreferenced blobs. Compaction trims index history. Verification reads every blob and may remove corrupted content. Storage writes may wait during maintenance.`}),!i&&!f&&(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,role:`status`,children:`Loading maintenance status…`}),y&&!y.canCollect&&!y.canVerify&&!y.canCompact&&(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Update canvas-stored to enable maintenance for this store.`}),f&&(0,Q.jsx)(`p`,{className:`text-xs text-destructive`,role:`alert`,children:f}),b&&(0,Q.jsxs)(`div`,{className:`rounded-md bg-muted/50 p-3 text-xs`,role:`status`,"aria-live":`polite`,children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2 font-medium`,children:[Jn(b)&&(0,Q.jsx)(z,{className:`h-3.5 w-3.5 animate-spin`}),qn[b.action],` · `,b.store]}),(0,Q.jsx)(`p`,{className:`mt-1 ${b.status===`failed`?`text-destructive`:`text-muted-foreground`}`,children:Qn(b)}),(0,Q.jsx)(`p`,{className:`mt-1 text-muted-foreground`,children:b.finishedAt?`Finished ${new Date(b.finishedAt).toLocaleString()}`:`Requested ${new Date(b.createdAt).toLocaleString()}`})]})]}),(0,Q.jsx)(ft,{open:u,onOpenChange:d,children:(0,Q.jsxs)(st,{className:`max-w-[calc(100vw-2rem)] sm:max-w-lg`,children:[(0,Q.jsxs)(dt,{children:[(0,Q.jsxs)(ot,{children:[`Verify `,o,`?`]}),(0,Q.jsx)(at,{children:`This reads all stored content and can take a long time. Corrupted blobs and their index entries may be removed. Keep a recovery backup before running it. Storage writes may wait until it finishes.`})]}),(0,Q.jsxs)(lt,{children:[(0,Q.jsx)(ut,{children:`Cancel`}),(0,Q.jsx)(ct,{disabled:v,onClick:()=>void _(`verify`),children:`Verify and repair`})]})]})})]})}var rr=e=>e.status===`queued`||e.status===`running`,ir=e=>`${xe.workspaces}/${encodeURIComponent(e)}/db`,ar=e=>G.get(`${ir(e)}/maintenance`),or={"reindex:timelines":`reindex/timelines`,"reindex:mime":`reindex/mime`,"reindex:search":`reindex/search`,optimize:`optimize`};function sr(e,t,n={}){let r=or[t];return t===`reindex:search`?G.post(`${ir(e)}/${r}${n.rebuild?`?rebuild=true`:``}`,{}):G.post(`${ir(e)}/${r}`,t===`optimize`&&n.space?{space:n.space}:{})}function cr(e){switch(e.action){case`reindex:timelines`:return`Rebuild timelines`;case`reindex:mime`:return`Rebuild file types`;case`reindex:search`:return e.options.rebuild?`Rebuild word search`:`Index missing documents`;default:return e.options.space?`Optimize ${e.options.space}`:`Optimize indexes`}}var lr=e=>typeof e==`number`?e.toLocaleString():`0`;function ur(e){if(e.status===`failed`)return e.error||`Maintenance failed`;if(e.status===`queued`)return`Waiting for the database…`;if(e.status===`running`){let t=e.progress;return t?e.action===`reindex:search`?`${lr(t.indexed)} indexed`:`${lr(t.scanned)}${typeof t.total==`number`?` / ${lr(t.total)}`:``} documents scanned`:`Working…`}let t=e.result||{};return e.action===`reindex:timelines`?`${lr(t.created)} created, ${lr(t.updated)} updated (${lr(t.scanned)} scanned)`:e.action===`reindex:mime`?`${lr(t.ticked)} of ${lr(t.scanned)} documents across ${lr(t.keys)} file types`:e.action===`reindex:search`?`${lr(t.indexed)} newly indexed (${lr(t.alreadyIndexed)} of ${lr(t.totalDocs)} already were)`:`Indexes compacted`}var dr=new Map;function fr(e,t,n){let r=JSON.stringify([t,n.id]),i=dr.get(r);if(i)return i;let a=(async()=>{let r=e({title:cr(n),description:ur(n)});try{let e=n;for(;rr(e);){let i=(await ar(t)).jobs.find(e=>e.id===n.id);if(!i)throw Error(`Maintenance receipt is no longer available. The workspace may have restarted; run it again.`);if(e=i,!rr(e))break;r.update({title:cr(e),description:ur(e)}),await new Promise(e=>setTimeout(e,2e3))}if(e.status===`failed`)throw Error(ur(e));return r.done({title:`${cr(e)} complete`,description:ur(e)}),e}catch(e){throw r.fail({title:`${cr(n)} needs attention`,description:e instanceof Error?e.message:String(e),variant:`destructive`}),e}})();return dr.set(r,a),a.finally(()=>{dr.get(r)===a&&dr.delete(r)}).catch(()=>{}),a}function pr({workspaceId:e,backend:t,onSaved:n}){let r=t?.config||{},i=()=>({name:String(r.label||``),bucket:String(r.bucket||``),prefix:String(r.prefix||``),endpoint:String(r.endpoint||``),region:String(r.region||`us-east-1`),accessKeyId:``,secretAccessKey:``,sessionToken:``}),[a,o]=(0,Z.useState)(!1),[s,c]=(0,Z.useState)(i),[l,u]=(0,Z.useState)(r.forcePathStyle!==!1),[d,f]=(0,Z.useState)(r.readOnly===!0),[p,h]=(0,Z.useState)(r.watch===!0),[g,_]=(0,Z.useState)(!1),[v,y]=(0,Z.useState)(!1),{showToast:b}=K(),x=e=>({value:s[e],onChange:t=>c(n=>({...n,[e]:t.target.value}))});return a?(0,Q.jsxs)(`form`,{onSubmit:async r=>{r.preventDefault(),y(!0);try{let r={label:s.name.trim(),bucket:s.bucket.trim(),prefix:s.prefix.trim(),endpoint:s.endpoint.trim(),region:s.region.trim()||`us-east-1`,forcePathStyle:l,readOnly:d,watch:p,...Object.fromEntries([`accessKeyId`,`secretAccessKey`,`sessionToken`].flatMap(e=>{let t=s[e].trim();return t?[[e,t]]:[]})),...g?{sessionToken:``}:{}};t?await Ke(e,`s3`,t.address,r):await Xe(e,`s3`,r),o(!1),c(i()),b({title:t?`S3 backend updated`:`S3 backend added`,description:`Use Re-sync to check indexing progress, and filing policies to automate copies.`}),await n()}catch(e){b({title:`Could not connect S3`,description:e instanceof Error?e.message:String(e),variant:`destructive`})}finally{y(!1)}},className:`w-full space-y-3 rounded-lg border p-4`,children:[(0,Q.jsxs)(`h2`,{className:`flex items-center gap-2 text-sm font-semibold`,children:[(0,Q.jsx)(I,{className:`h-4 w-4`}),t?`Edit S3 connection`:`Add S3-compatible bucket`]}),(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Amazon S3, MinIO, Garage, RustFS or Ceph RGW. Connect an existing bucket, optionally scoped to a prefix. Supports browsing, reads and filing copies; mirror policies and overwrites are unavailable.`}),(0,Q.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs`,children:[`Name`,(0,Q.jsx)(U,{...x(`name`),required:!0,placeholder:`Accounting archive`})]}),(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs`,children:[`Bucket`,(0,Q.jsx)(U,{...x(`bucket`),disabled:!!t,required:!0,placeholder:`accounting`})]}),(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs`,children:[`Endpoint (blank for Amazon S3)`,(0,Q.jsx)(U,{...x(`endpoint`),disabled:!!t,type:`url`,placeholder:`https://s3.example.com`})]}),(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs`,children:[`Region`,(0,Q.jsx)(U,{...x(`region`),required:!0,placeholder:`us-east-1`})]}),(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs sm:col-span-2`,children:[`Prefix (optional)`,(0,Q.jsx)(U,{...x(`prefix`),disabled:!!t,placeholder:`Augmentd/Accounting`})]}),(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs`,children:[`Access key ID`,(0,Q.jsx)(U,{...x(`accessKeyId`),required:!t,autoComplete:`off`,placeholder:t?`Leave blank to keep stored value`:``})]}),(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs`,children:[`Secret access key`,(0,Q.jsx)(U,{...x(`secretAccessKey`),type:`password`,required:!t,autoComplete:`off`,placeholder:t?`Leave blank to keep stored value`:``})]}),(0,Q.jsxs)(`label`,{className:`space-y-1 text-xs sm:col-span-2`,children:[`Session token (optional)`,(0,Q.jsx)(U,{...x(`sessionToken`),disabled:g,type:`password`,autoComplete:`off`,placeholder:t?`Leave blank to keep stored value`:``})]}),t&&(0,Q.jsxs)(`label`,{className:`flex items-center gap-2 text-xs`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,checked:g,onChange:e=>_(e.target.checked)}),`Clear stored session token`]})]}),(0,Q.jsxs)(`div`,{className:`flex flex-wrap gap-4 text-xs`,children:[(0,Q.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,checked:l,onChange:e=>u(e.target.checked)}),`Path-style addressing`]}),(0,Q.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,checked:d,onChange:e=>f(e.target.checked)}),`Read-only`]}),(0,Q.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,checked:p,onChange:e=>h(e.target.checked)}),`Poll for changes`]})]}),(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Writable connections test conflict protection using a temporary object, then delete it. The key needs list/read/write access and delete access under .canvas-probe/. Initial indexing reads file bytes; polling can incur request and download charges. Upload limit: 5 GiB per file.`}),(0,Q.jsxs)(`div`,{className:`flex justify-end gap-2`,children:[(0,Q.jsx)(H,{type:`button`,variant:`ghost`,disabled:v,onClick:()=>{o(!1),c(i())},children:`Cancel`}),(0,Q.jsx)(H,{disabled:v,children:v?`Checking connection…`:`Save connection`})]})]}):(0,Q.jsxs)(H,{variant:`outline`,size:`sm`,onClick:()=>{c(i()),u(r.forcePathStyle!==!1),f(r.readOnly===!0),h(r.watch===!0),_(!1),o(!0)},children:[t?(0,Q.jsx)(m,{className:`mr-2 h-3.5 w-3.5`}):(0,Q.jsx)(D,{className:`mr-2 h-3.5 w-3.5`}),t?`Edit S3 connection`:`Add S3 bucket`]})}function mr({workspaceId:e,isActive:t,currentMode:n,onChanged:r}){let[i,a]=(0,Z.useState)(n===`workspace`?`workspace`:`secrets`),[o,s]=(0,Z.useState)(``),[c,l]=(0,Z.useState)(``),[u,d]=(0,Z.useState)(``),[f,p]=(0,Z.useState)(``),[m,h]=(0,Z.useState)(``),[g,_]=(0,Z.useState)(!1);return(0,Q.jsxs)(`section`,{className:`space-y-3 rounded-lg border p-4`,children:[(0,Q.jsx)(`h2`,{className:`font-semibold text-sm`,children:`Workspace protection`}),(0,Q.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Protect service credentials with a PIN or password. Optionally require it to start the whole workspace. Files and document contents are not encrypted.`}),t&&(0,Q.jsx)(`p`,{className:`text-sm`,children:`Stop the workspace before changing protection.`}),(0,Q.jsxs)(`form`,{className:`space-y-3`,onSubmit:async t=>{if(t.preventDefault(),h(``),o!==c){h(`PIN/password confirmation does not match`);return}_(!0);try{let t=await G.put(`${xe.workspaces}/${e}/protection`,{mode:i,passphrase:o,currentPassphrase:u||void 0});p(t.recoveryKey),s(``),l(``),d(``)}catch(e){h(e instanceof Error?e.message:`Could not save protection`)}finally{_(!1)}},children:[(0,Q.jsxs)(`label`,{className:`block text-sm space-y-1`,children:[`Protection mode`,(0,Q.jsxs)(`select`,{className:`block rounded border bg-background p-2 w-full`,value:i,onChange:e=>a(e.target.value),disabled:t||g,children:[(0,Q.jsx)(`option`,{value:`secrets`,children:`Secrets only — allow start without integrations`}),(0,Q.jsx)(`option`,{value:`workspace`,children:`Whole workspace — require PIN/password to start`})]})]}),(0,Q.jsxs)(`label`,{className:`block text-sm space-y-1`,children:[`Current PIN/password or recovery key (if already protected)`,(0,Q.jsx)(U,{type:`password`,autoComplete:`current-password`,value:u,onChange:e=>d(e.target.value),disabled:t||g})]}),(0,Q.jsxs)(`label`,{className:`block text-sm space-y-1`,children:[`New PIN/password`,(0,Q.jsx)(U,{type:`password`,autoComplete:`new-password`,minLength:4,maxLength:1024,required:!0,value:o,onChange:e=>s(e.target.value),disabled:t||g})]}),(0,Q.jsxs)(`label`,{className:`block text-sm space-y-1`,children:[`Confirm new PIN/password`,(0,Q.jsx)(U,{type:`password`,autoComplete:`new-password`,required:!0,value:c,onChange:e=>l(e.target.value),disabled:t||g})]}),(0,Q.jsx)(H,{disabled:t||g||!!f,children:g?`Saving…`:`Save protection`})]}),m&&(0,Q.jsx)(`p`,{role:`alert`,className:`text-sm text-destructive`,children:m}),f&&(0,Q.jsxs)(`div`,{className:`space-y-2 rounded border p-3`,children:[(0,Q.jsx)(`p`,{className:`text-sm`,children:`Save this recovery key now. It is shown only once and replaces any previous recovery key.`}),(0,Q.jsx)(`code`,{className:`block break-all select-all`,children:f}),(0,Q.jsx)(H,{variant:`outline`,onClick:()=>{p(``),r()},children:`I saved the recovery key`})]})]})}var hr=`h-8 rounded-md border bg-background px-2 text-sm outline-none focus:ring-2 focus:ring-ring`;function gr({title:e,hint:t,children:n}){let[r,i]=(0,Z.useState)(!1);return(0,Q.jsxs)(`section`,{className:`overflow-hidden rounded-lg border`,children:[(0,Q.jsxs)(`button`,{type:`button`,onClick:()=>i(e=>!e),"aria-expanded":r,className:`flex w-full items-center justify-between gap-4 px-4 py-3 text-left transition-colors hover:bg-muted/40`,children:[(0,Q.jsxs)(`span`,{className:`min-w-0`,children:[(0,Q.jsx)(`span`,{className:`block text-sm font-medium`,children:e}),(0,Q.jsx)(`span`,{className:`mt-0.5 block text-xs text-muted-foreground`,children:t})]}),(0,Q.jsx)(re,{className:be(`h-4 w-4 shrink-0 text-muted-foreground transition-transform motion-reduce:transition-none`,r&&`rotate-180`)})]}),r&&(0,Q.jsx)(`div`,{className:`border-t p-4`,children:n})]})}function _r({workspaceName:e,value:t,onChange:n,disabled:r}){let[i,a]=(0,Z.useState)(!1);return(0,Q.jsxs)(`div`,{className:`space-y-1`,children:[(0,Q.jsxs)(`label`,{className:`text-xs font-medium`,children:[`Only this folder `,(0,Q.jsx)(`span`,{className:`font-normal text-muted-foreground`,children:`(optional)`})]}),(0,Q.jsxs)(`div`,{className:`flex gap-2`,children:[(0,Q.jsx)(U,{value:t,disabled:r,onChange:e=>n(e.target.value),placeholder:`Whole workspace`,className:`h-8 font-mono text-sm`}),(0,Q.jsx)(H,{type:`button`,size:`sm`,variant:`outline`,disabled:r,onClick:()=>a(!0),title:`Pick a folder or context from the tree`,children:(0,Q.jsx)(ae,{className:`h-3.5 w-3.5`})})]}),(0,Q.jsxs)(`p`,{className:`text-[11px] text-muted-foreground`,children:[`Includes everything below it. Pick from the tree, or type `,(0,Q.jsx)(`span`,{className:`font-mono`,children:`ctx://work/project`}),` or`,` `,(0,Q.jsx)(`span`,{className:`font-mono`,children:`dir://photos`}),`.`]}),i&&(0,Q.jsx)(St,{onClose:()=>a(!1),children:(0,Q.jsx)(we,{sizeClassName:`h-full w-[380px] max-w-[90vw] max-md:w-full`,fixedWorkspaceName:e,multiple:!1,onClose:()=>a(!1),onConfirm:(e,t)=>{let r=e[0];r&&n(`${t.treeType===`directory`?`dir`:`ctx`}://${r.replace(/^\/+/,``)}`),a(!1)}})})]})}function vr({workspaceId:e,workspaceName:t,refreshKey:n,onRefresh:r}){let{showToast:i}=K(),[a,o]=(0,Z.useState)(null),[s,c]=(0,Z.useState)(!1),l=(0,Z.useCallback)(()=>bn(e).then(e=>o(e.queue??null)).catch(()=>{}),[e]);(0,Z.useEffect)(()=>{l();let e=window.setInterval(()=>{o(e=>(e&&(e.pending>0||e.draining)&&l(),e))},3e3);return()=>window.clearInterval(e)},[l,n]);let u=async()=>{if(a){c(!0);try{let e=await Je(!a.paused,t);i({title:e.paused?`Indexing paused`:`Indexing resumed`,description:e.paused?`${e.pending.toLocaleString()} document(s) on hold. Resume any time; a server restart also resumes.`:`${e.pending.toLocaleString()} document(s) being indexed.`}),await l()}catch(e){i({title:`Error`,description:e instanceof Error?e.message:`Failed to pause or resume indexing (admin only)`,variant:`destructive`})}finally{c(!1)}}},d=!!a?.draining,f=a?a.paused?`bg-warning`:d?`bg-success`:`bg-muted-foreground/40`:`bg-muted-foreground/40`;return(0,Q.jsxs)(`section`,{className:`flex flex-wrap items-center justify-between gap-x-4 gap-y-2 rounded-lg border bg-muted/30 px-4 py-2.5`,children:[(0,Q.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2 text-sm`,children:[(0,Q.jsxs)(`span`,{className:`relative flex h-2 w-2 shrink-0`,"aria-hidden":!0,children:[d&&(0,Q.jsx)(`span`,{className:`absolute inline-flex h-full w-full animate-ping rounded-full bg-success opacity-60 motion-reduce:hidden`}),(0,Q.jsx)(`span`,{className:be(`relative inline-flex h-2 w-2 rounded-full`,f)})]}),(0,Q.jsx)(`span`,{className:`font-medium`,children:a?a.pending>0?(0,Q.jsxs)(Q.Fragment,{children:[a.pending.toLocaleString(),` `,(0,Q.jsx)(`span`,{className:`font-normal text-muted-foreground`,children:`document(s) waiting to be indexed`})]}):a.paused?`Paused`:`Up to date`:`Inference service not reachable`}),a?.paused&&a.pending>0&&(0,Q.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`(paused)`}),a?.ingestDisabled&&(0,Q.jsx)(`span`,{className:`rounded bg-warning-subtle px-1.5 py-0.5 text-[10px] font-medium text-warning`,title:`CANVAS_INFERD_INGEST_DISABLED=true: new documents are not indexed for meaning search; what is already indexed still works`,children:`indexing turned off on the server`})]}),(0,Q.jsxs)(`div`,{className:`flex items-center gap-1`,children:[a&&(0,Q.jsx)(H,{type:`button`,size:`sm`,variant:`ghost`,disabled:s,onClick:u,title:a.paused?`Resume; the waiting documents get indexed`:`Pause after the current batch. Stops the CPU-heavy model work; new documents are still found by word search.`,children:s?`…`:a.paused?`Resume`:`Pause`}),(0,Q.jsx)(H,{type:`button`,size:`sm`,variant:`ghost`,onClick:r,title:`Reload`,children:(0,Q.jsx)(R,{className:`h-3.5 w-3.5`})})]})]})}function yr({workspaceId:e,tables:t,error:n,onChanged:r}){let{showToast:i}=K(),[a,o]=(0,Z.useState)(null),s=t.filter(e=>!e.active),c=async t=>{if(window.confirm(`Reclaim "${t.name}"?\n\nThis permanently deletes the index built with ${t.model||`that model`}. Switching back to it afterwards means indexing every document again instead of being instant.\n\nThis is the only step here that cannot be undone.`)){o(t.name);try{let n=await yn(e,t.name);if(!n.dropped)throw Error(n.error||`Failed to drop the vector table`);i({title:`Deleted`,description:`Removed '${n.name||t.name}'.`}),r()}catch(e){i({title:`Error`,description:e instanceof Error?e.message:`Failed to delete`,variant:`destructive`})}finally{o(null)}}};return n?(0,Q.jsxs)(`section`,{className:`rounded-lg border border-destructive/40 bg-destructive-subtle p-4`,children:[(0,Q.jsx)(`p`,{className:`text-sm font-medium text-destructive`,children:`Stored indexes unavailable`}),(0,Q.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:n})]}):s.length===0?null:(0,Q.jsx)(gr,{title:`Previous models (${s.length})`,hint:`Indexes built with models you switched away from. They stay on disk so switching back is instant. Deleting one frees the space for good.`,children:(0,Q.jsx)(`div`,{className:`divide-y`,children:s.map(e=>(0,Q.jsxs)(`div`,{className:`flex items-center justify-between gap-4 py-2 first:pt-0 last:pb-0`,children:[(0,Q.jsxs)(`div`,{className:`min-w-0`,children:[(0,Q.jsxs)(`p`,{className:`truncate font-mono text-xs`,children:[e.model||`unknown model`,e.dim?` · ${e.dim}-d`:``]}),(0,Q.jsxs)(`p`,{className:`truncate font-mono text-[11px] text-muted-foreground`,children:[`└─ `,e.name]})]}),(0,Q.jsxs)(H,{type:`button`,size:`sm`,variant:`ghost`,className:`text-destructive hover:text-destructive`,disabled:a===e.name,onClick:()=>c(e),title:`Permanently delete the index built with this model`,children:[(0,Q.jsx)(M,{className:`mr-1.5 h-3.5 w-3.5`}),a===e.name?`Deleting…`:`Delete`]})]},e.name))})})}function br({workspaceId:e,workspaceName:t,spaces:n,onDone:r}){let{showToast:i}=K(),[a,o]=(0,Z.useState)(``),[s,c]=(0,Z.useState)(``),[l,u]=(0,Z.useState)(!1),[d,f]=(0,Z.useState)(!1);return(0,Q.jsxs)(gr,{title:`Index existing documents`,hint:`Add documents that are not in meaning search yet, for example after switching models. Limit it to one folder to try a model on a small set first.`,children:[(0,Q.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,Q.jsxs)(`div`,{className:`space-y-1`,children:[(0,Q.jsx)(`label`,{className:`text-xs font-medium`,children:`Content type`}),(0,Q.jsxs)(`select`,{className:`${hr} w-full`,value:a,onChange:e=>o(e.target.value),children:[(0,Q.jsx)(`option`,{value:``,children:`All content types`}),n.map(e=>(0,Q.jsx)(`option`,{value:e,children:gn(e)},e))]})]}),(0,Q.jsx)(_r,{workspaceName:t,value:s,onChange:c,disabled:d})]}),(0,Q.jsxs)(`label`,{className:`mt-3 flex items-start gap-2 text-xs`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,className:`mt-0.5`,checked:l,onChange:e=>u(e.target.checked)}),(0,Q.jsxs)(`span`,{children:[`Also redo documents that are already indexed`,l&&s.trim()&&(0,Q.jsx)(`span`,{className:`mt-1 block text-[11px] text-warning`,children:`Even with a folder limit, this clears the whole index for the chosen content type, not just that folder. Leave it off unless you want to redo everything.`})]})]}),(0,Q.jsx)(H,{type:`button`,size:`sm`,className:`mt-3`,onClick:async()=>{f(!0);try{let t=await mn(e,{space:a||void 0,reindex:l,scope:s.trim()||void 0});t.ingestDisabled?i({title:`Indexing is turned off on the server`,description:`CANVAS_INFERD_INGEST_DISABLED=true: nothing was queued. What is already indexed still works.`,variant:`destructive`}):i({title:`Indexing queued`,description:`${t.enqueued.toLocaleString()} document(s) queued${t.scope?` under ${t.scope}`:``}. The status line above shows progress.`}),r()}catch(e){i({title:`Indexing failed to start`,description:e instanceof Error?e.message:`Failed to queue`,variant:`destructive`})}finally{f(!1)}},disabled:d,children:d?`Queueing…`:`Start indexing`})]})}var xr=[{provider:`blip`,model:`HuggingFaceTB/SmolVLM-500M-Instruct`,task:`instruct`,label:`SmolVLM 500M: follows your instructions (recommended)`,note:`About 500 MB. Follows the instructions below, so you can ask for what matters to you, such as style, materials or setting.`},{provider:`blip`,model:`HuggingFaceTB/SmolVLM-256M-Instruct`,task:`instruct`,label:`SmolVLM 256M: smaller, follows your instructions`,note:`About 250 MB. Same instructions, less detail; for servers short on memory.`},{provider:`blip`,model:`onnx-community/Florence-2-base-ft`,task:`florence2`,label:`Florence-2 base: detailed, fixed style`,note:`Writes several detailed sentences, but ignores instructions.`},{provider:`blip`,model:`Xenova/vit-gpt2-image-captioning`,task:`caption`,label:`vit-gpt2: one short sentence (smallest)`,note:`One terse sentence per image, sometimes repetitive. Uses the least memory.`}],Sr=`custom`,Cr=[{value:`instruct`,label:`Follows instructions (instruct VLM)`},{value:`florence2`,label:`Florence-2 family`},{value:`caption`,label:`Plain captioner, image only`}],wr=`Describe this photograph in two or three sentences. If it shows a building or interior, name the architectural style, the main materials and the setting. Describe only what is visible.`;function Tr({workspaceId:e,workspaceName:t,config:n,saving:r,onSave:i}){let{showToast:a}=K(),o=n.workspace||{},s=n.effective||{},c=xr[0],l=o.summarize?.image||s.summarize?.image||{},[u,d]=(0,Z.useState)(()=>s.summarize?.image?.enabled===!0||o.summarize?.image?.enabled===!0),[f,p]=(0,Z.useState)(()=>{let e=xr.find(e=>e.provider===(l.provider||c.provider)&&e.model===l.model);return e?`${e.provider}::${e.model}`:l.model?Sr:`${c.provider}::${c.model}`}),[m,h]=(0,Z.useState)(()=>xr.some(e=>e.model===l.model)?``:l.model||``),[g,_]=(0,Z.useState)(()=>l.task||`instruct`),[v,y]=(0,Z.useState)(()=>l.prompt||``),[b,x]=(0,Z.useState)(!1),[S,C]=(0,Z.useState)(null),[w,T]=(0,Z.useState)(!1),[E,ee]=(0,Z.useState)(!1),[D,te]=(0,Z.useState)(!1),[O,ne]=(0,Z.useState)(``),k=xr.find(e=>`${e.provider}::${e.model}`===f),re=f===Sr,A=re?{provider:c.provider,model:m.trim(),task:g,label:`Custom`,note:``}:k||c,ie=A.task===`instruct`,j=(0,Z.useCallback)(()=>bn(e).then(e=>C(e.summarize||null)).catch(()=>{}),[e]);(0,Z.useEffect)(()=>{j();let e=window.setInterval(()=>{C(e=>(e?.running&&j(),e))},2e3);return()=>window.clearInterval(e)},[j]);let M=async()=>{await i({...o,summarize:{...o.summarize||{},image:{enabled:u,provider:A.provider,model:A.model,task:A.task,...ie&&v.trim()?{prompt:v.trim()}:{}}}}),x(!1)},ae=async()=>{ee(!0);try{C(await hn(e)),a({title:`Stopping image descriptions`,description:`The current image finishes first; the rest are left for a later run.`})}catch(e){a({title:`Could not stop`,description:e instanceof Error?e.message:`Failed to stop`,variant:`destructive`})}finally{ee(!1)}},N=async(t=!1)=>{T(!0);try{let n=await vn(e,{force:t,scope:O.trim()||void 0});C(n),a({title:t?`Describing all images again`:`Describing images`,description:`${n.total.toLocaleString()} image(s)${n.scope?` under ${n.scope}`:``}. The first run downloads the model, which can take a few minutes.`})}catch(e){a({title:`Image descriptions failed to start`,description:e instanceof Error?e.message:`Failed to start`,variant:`destructive`})}finally{T(!1)}},P=s.summarize?.image?.enabled===!0,F=S?.running===!0,oe=S?.errors?.[0]?.error;return(0,Q.jsx)(gr,{title:`Image descriptions`,hint:`A vision model writes a few sentences about each image, so you can find photos by what is in them.`,children:(0,Q.jsxs)(`div`,{className:`space-y-3`,children:[(0,Q.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,Q.jsxs)(`label`,{className:`flex items-center gap-2 text-sm`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,checked:u,disabled:r,onChange:e=>{d(e.target.checked),x(!0)}}),`Describe images`]}),(0,Q.jsxs)(`select`,{className:hr,value:f,disabled:r||!u,onChange:e=>{p(e.target.value),x(!0)},children:[xr.map(e=>(0,Q.jsx)(`option`,{value:`${e.provider}::${e.model}`,children:e.label},`${e.provider}::${e.model}`)),(0,Q.jsx)(`option`,{value:Sr,children:`Custom model…`})]}),!re&&(0,Q.jsx)(`span`,{className:`font-mono text-xs text-muted-foreground`,children:A.model})]}),re&&(0,Q.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,Q.jsx)(U,{className:`h-8 w-72 font-mono text-xs`,placeholder:`org/model-id (Hugging Face, ONNX)`,value:m,disabled:r||!u,onChange:e=>{h(e.target.value),x(!0)}}),(0,Q.jsx)(`select`,{className:hr,value:g,disabled:r||!u,onChange:e=>{_(e.target.value),x(!0)},children:Cr.map(e=>(0,Q.jsx)(`option`,{value:e.value,children:e.label},e.value))})]}),u&&A.note&&(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:A.note}),u&&ie&&(0,Q.jsxs)(`div`,{className:`space-y-1`,children:[(0,Q.jsx)(`textarea`,{className:`w-full rounded-md border border-input bg-transparent p-2 text-xs outline-none focus-visible:ring-1 focus-visible:ring-ring`,rows:3,placeholder:wr,value:v,disabled:r,onChange:e=>{y(e.target.value),x(!0)}}),(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`What to ask about every image. Leave empty to use the default shown above. Descriptions become searchable, so ask for the details you would search by.`})]}),S&&(S.running||S.total>0||S.finishedAt)&&(0,Q.jsxs)(`p`,{className:be(`text-xs`,S.aborted?`text-destructive`:`text-muted-foreground`),children:[F?`Running`:S.aborted?`Stopped`:S.cancelled?`Cancelled`:`Last run`,S.scope?(0,Q.jsxs)(Q.Fragment,{children:[` under `,(0,Q.jsx)(`span`,{className:`font-mono`,children:S.scope})]}):null,`: `,S.described,`/`,S.total,` described`,S.skipped?`, ${S.skipped} skipped`:``,S.failed?`, ${S.failed} failed`:``,S.aborted?`. ${S.abortedReason||`The model stopped working`}. The remaining images were not tried; run again to retry.`:S.cancelled?`. Stopped by you. The remaining images were left untouched; run again to continue.`:oe?`. ${oe}`:``]}),(0,Q.jsx)(_r,{workspaceName:t,value:O,onChange:ne,disabled:r||F}),(0,Q.jsxs)(`label`,{className:`flex items-start gap-2 text-xs`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,className:`mt-0.5`,checked:D,disabled:r||F,onChange:e=>te(e.target.checked)}),(0,Q.jsxs)(`span`,{children:[`Also redo images that already have a description`,D&&(0,Q.jsxs)(`span`,{className:`mt-1 block text-[11px] text-warning`,children:[`Replaces existing descriptions`,O.trim()?` in that folder`:``,`, including ones written by another model. Leave this off to describe only images that have none yet.`]})]})]}),(0,Q.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Turn on and save, then run. Descriptions are generated on this server; the first run downloads the model.`}),(0,Q.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,Q.jsx)(H,{size:`sm`,variant:`outline`,onClick:()=>void M(),disabled:r||!b,children:`Save`}),(0,Q.jsx)(H,{size:`sm`,onClick:()=>void N(D),disabled:r||b||w||F||!P,title:P?b?`Save your changes first`:D?`Describe every image again, replacing existing descriptions`:`Describe images that have no description yet`:`Turn on image descriptions and save first`,children:F||w?`Running…`:D?`Describe all again`:`Describe missing`}),F&&(0,Q.jsx)(H,{size:`sm`,variant:`destructive`,onClick:()=>void ae(),disabled:E,title:`Finish the current image, then stop. The rest are left for later.`,children:E?`Stopping…`:`Stop`})]})]})]})})}function Er({workspaceId:e,workspaceName:t}){let{showToast:n}=K(),[r,i]=(0,Z.useState)(null),[a,o]=(0,Z.useState)([]),[s,c]=(0,Z.useState)(),[l,u]=(0,Z.useState)(!0),[d,f]=(0,Z.useState)(!1),[p,m]=(0,Z.useState)(null),[h,g]=(0,Z.useState)([]),[_,v]=(0,Z.useState)(0),y=(0,Z.useCallback)(()=>_n(e).then(e=>{i(e),m(null)}).catch(e=>m(e instanceof Error?e.message:`Failed to load the search settings`)).finally(()=>u(!1)),[e]),b=(0,Z.useCallback)(()=>fn(e).then(e=>{o(e.tables||[]),c(e.error)}).catch(e=>c(e instanceof Error?e.message:`Failed to list stored indexes`)),[e]);(0,Z.useEffect)(()=>{y(),b()},[y,b]);let x=()=>{u(!0),y(),b(),v(e=>e+1)},S=async t=>{f(!0);try{let r=await pn(e,t);g(r.movedSpaces||[]),r.movedSpaces?.length?n({title:`Saved: now index your existing documents`,description:`${r.movedSpaces.map(gn).join(`, `)}: new model in use. New documents use it right away; existing ones need indexing (button on the row).`}):r.applied===!1?n({title:`Saved: applies on next start`,description:`The workspace is not running, so the changes take effect when it starts.`}):n({title:`Saved`,description:`Search settings updated.`}),await y(),await b()}catch(e){n({title:`Save failed`,description:e instanceof Error?e.message:`Failed to save`,variant:`destructive`})}finally{f(!1)}},C=async t=>{try{let r=await mn(e,{space:t});if(r.ingestDisabled){n({title:`Indexing is turned off on the server`,description:`CANVAS_INFERD_INGEST_DISABLED=true: nothing was queued. What is already indexed still works.`,variant:`destructive`});return}n({title:`Indexing ${gn(t).toLowerCase()}`,description:`${r.enqueued.toLocaleString()} document(s) queued. The status line above shows progress.`}),g(e=>e.filter(e=>e!==t)),v(e=>e+1),b()}catch(e){n({title:`Indexing failed to start`,description:e instanceof Error?e.message:`Failed to queue`,variant:`destructive`})}};if(l)return(0,Q.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-muted-foreground`,children:[(0,Q.jsx)(R,{className:`h-4 w-4 animate-spin`}),`Loading search settings…`]});if(p||!r)return(0,Q.jsxs)(`div`,{className:`space-y-3`,children:[(0,Q.jsxs)(`div`,{className:`rounded-lg border border-destructive/40 bg-destructive-subtle p-4 text-sm`,children:[(0,Q.jsx)(`p`,{className:`font-medium text-destructive`,children:`Search settings unavailable`}),(0,Q.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:p||`No config returned.`})]}),(0,Q.jsx)(H,{type:`button`,size:`sm`,variant:`outline`,onClick:x,children:`Try again`})]});let w=Object.keys(r.effective.spaces||{}).sort();return(0,Q.jsxs)(`div`,{className:`space-y-5`,children:[(0,Q.jsx)(vr,{workspaceId:e,workspaceName:t,refreshKey:_,onRefresh:x}),(0,Q.jsx)(xn,{value:r.workspace||{},effective:r.effective||{},inherited:r.inherited||{},resolvedSpaces:r.spaces,invalid:r.invalid,attention:h,onFill:C,saving:d,saveLabel:`Save models`,onSave:S},JSON.stringify(r.workspace)),(0,Q.jsxs)(`div`,{className:`space-y-3`,children:[(0,Q.jsx)(Tr,{workspaceId:e,workspaceName:t,config:r,saving:d,onSave:S},`summarize:${JSON.stringify(r.workspace?.summarize||{})}`),(0,Q.jsx)(br,{workspaceId:e,workspaceName:t,spaces:w,onDone:()=>{b(),v(e=>e+1)}}),(0,Q.jsx)(yr,{workspaceId:e,tables:a,error:s,onChanged:()=>{b()}})]}),(0,Q.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`These settings are saved with the workspace (in its `,(0,Q.jsx)(`span`,{className:`font-mono`,children:`workspace.json`}),`), so they move with it. Anything not set here comes from your personal defaults, then the server's. Changes apply immediately, with no restart.`]})]})}function Dr(e){let n=(e||``).split(`.`).pop()?.toLowerCase();switch(n){case`js`:case`mjs`:case`ts`:return[a({typescript:n===`ts`})];case`json`:return[i()];case`sh`:case`bash`:return[t.define(o)];default:return[]}}function Or({value:e,onChange:t,path:r,className:i=``}){let a=(0,Z.useMemo)(()=>Dr(r),[r]),{resolvedScheme:o}=$t();return(0,Q.jsx)(n,{value:e,onChange:t,extensions:a,theme:o===`dark`?`dark`:`light`,className:i,basicSetup:{lineNumbers:!0,foldGutter:!0,highlightActiveLine:!0,bracketMatching:!0,autocompletion:!1}})}function kr(e,t){if(![`download`,`store`].includes(e.action)||e.recursive===!0&&!t)return null;let n=String(e.folder||``);return n.includes(`{{`)?null:[n,(e.recursive===!0?e.pathMode===`full`?t?.path:t?.rel:``)||``].join(`/`).split(`/`).filter(e=>e&&e!==`.`&&e!==`..`).join(`/`)}function Ar(e,t){if(![`download`,`store`].includes(e.action)||typeof e.to!=`string`)return null;if(e.recursive===!0&&!t)return`Missing filing path — decline and trigger the rule again`;let n=kr(e,t);return n===null?null:`${e.to}/${n}`}function jr(e,t){let n=kr(e,t);if(n===null||e.recursive!==!0||e.autoLink===!0)return{...e};let r={...e,folder:n};return delete r.recursive,delete r.pathMode,r}function Mr(e,t){let n=structuredClone({actions:e.actions});for(let[r,i]of Object.entries(t)){if(!e.editable.includes(r))continue;let t=r.split(`.`);if(t[0]!==`actions`||t.some(e=>[`__proto__`,`prototype`,`constructor`].includes(e)))continue;let a=n;for(let e of t.slice(0,-1)){if(!a[e]||typeof a[e]!=`object`){a={};break}a=a[e]}a[t[t.length-1]]=i}return n.actions}var Nr=[`pending`,`approved`,`declined`,`failed`,`expired`,`all`],Pr={pending:`text-warning dark:text-warning`,approved:`text-success dark:text-success`,declined:`text-muted-foreground`,failed:`text-destructive`,expired:`text-muted-foreground line-through`};function Fr(e){let t=Date.now()-new Date(e).getTime(),n=Math.floor(t/6e4);if(n<1)return`now`;if(n<60)return`${n}m`;let r=Math.floor(n/60);return r<24?`${r}h`:`${Math.floor(r/24)}d`}function Ir(e,t){return t.split(`.`).reduce((e,t)=>typeof e==`object`&&e?e[t]:void 0,e)}function Lr(e){let t=e.split(`.`);return t.slice(Math.max(t.length-2,2)).join(`.`)}var Rr=/(body|content|message|text|prompt)$/i;function zr({workspaceId:e,id:t,children:n}){let{open:r}=Ct(),{showToast:i}=K(),[a,o]=(0,Z.useState)(!1),s=async n=>{n.stopPropagation(),o(!0);try{r(await et(e,t),e)}catch(e){i({title:`Document ${t} not available`,description:e instanceof Error?e.message:void 0,variant:`destructive`})}finally{o(!1)}};return(0,Q.jsx)(`button`,{type:`button`,disabled:a,onClick:e=>void s(e),className:`text-primary underline-offset-2 hover:underline disabled:opacity-60`,title:`Open document ${t}`,children:n??`doc ${t}`})}function Br({workspaceId:e,text:t}){let n=t.split(/(\bdoc \d+\b)/);return(0,Q.jsx)(Q.Fragment,{children:n.map((t,n)=>{let r=/^doc (\d+)$/.exec(t);return r?(0,Q.jsx)(zr,{workspaceId:e,id:Number(r[1])},n):(0,Q.jsx)(Z.Fragment,{children:t},n)})})}function Vr({action:e,amend:t,onAmend:n}){return e.editable?.length?(0,Q.jsx)(`div`,{className:`space-y-2`,children:e.editable.map(r=>{let i=Ir(e,r),a=typeof i==`string`,o=r in t?t[r]:i,s=a?String(o??``):JSON.stringify(o,null,2),c=a&&(Rr.test(r)||s.length>80);return(0,Q.jsxs)(`label`,{className:`block text-xs`,children:[(0,Q.jsxs)(`span`,{className:`font-medium text-muted-foreground`,children:[Lr(r),(0,Q.jsx)(`span`,{className:`ml-1.5 font-mono text-[10px] opacity-60`,children:r}),r in t&&(0,Q.jsx)(`span`,{className:`ml-1.5 text-warning dark:text-warning`,children:`edited`})]}),c?(0,Q.jsx)(`textarea`,{className:`mt-1 w-full rounded-md border bg-background px-2 py-1.5 font-mono text-xs outline-none focus:ring-2 focus:ring-ring min-h-[100px]`,value:s,onChange:e=>n(r,e.target.value)}):(0,Q.jsx)(`input`,{className:`mt-1 w-full h-8 rounded-md border bg-background px-2 font-mono text-xs outline-none focus:ring-2 focus:ring-ring`,value:s,onChange:e=>{if(a){n(r,e.target.value);return}try{n(r,JSON.parse(e.target.value))}catch{n(r,e.target.value)}}})]},r)})}):null}function Hr({workspaceId:e,onPendingCount:t}){let{showToast:n}=K(),r=Sn(),[i,a]=(0,Z.useState)(`pending`),[o,s]=(0,Z.useState)([]),[c,l]=(0,Z.useState)(!0),[u,d]=(0,Z.useState)(new Set),[f,p]=(0,Z.useState)(null),[m,h]=(0,Z.useState)({}),[g,_]=(0,Z.useState)(!1),v=(0,Z.useCallback)(()=>At(e,{status:i===`all`?void 0:i,limit:200}).then(e=>{s(e),d(t=>new Set(e.filter(e=>e.status===`pending`&&t.has(e.actionId)).map(e=>e.actionId))),t?.(i===`pending`?e.length:e.filter(e=>e.status===`pending`).length)}).catch(()=>{n({title:`Error`,description:`Failed to load pending actions`,variant:`destructive`})}).finally(()=>l(!1)),[e,i]),y=(0,Z.useCallback)(async()=>{l(!0),await v()},[v]),[b,x]=(0,Z.useState)(`${e}|${i}`),S=`${e}|${i}`;S!==b&&(x(S),l(!0)),(0,Z.useEffect)(()=>{v()},[v]),Cn(r,`workspace:${e}`,(0,Z.useMemo)(()=>{let e=()=>{y()};return{"action.proposed":e,"action.approved":e,"action.declined":e,"action.failed":e}},[y]));let C=o.filter(e=>e.status===`pending`),T=C.length>0&&C.every(e=>u.has(e.actionId)),E=()=>{d(T?new Set:new Set(C.map(e=>e.actionId)))},ee=e=>{d(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},D=(e,t,n)=>{h(r=>({...r,[e]:{...r[e],[t]:n}}))},te=async(t,r)=>{if(!(!t.length&&!r.length)){_(!0);try{let i=await Lt(e,{approve:t.map(e=>{let t=m[e];return t&&Object.keys(t).length?{actionId:e,amend:t}:e}),decline:r}),a=i.results.filter(e=>e.status===`error`||e.status===`failed`);a.length?n({title:`${a.length} of ${i.decided} failed`,description:a.map(e=>`${e.actionId}: ${e.error??`execution failed`}`).join(`; `),variant:`destructive`}):n({title:t.length&&r.length?`Decisions applied`:t.length?`Approved ${t.length}`:`Declined ${r.length}`,description:t.length?`Approved actions executed with their original provenance.`:void 0}),h(e=>{let n={...e};for(let e of[...t,...r])delete n[e];return n}),d(new Set),f&&[...t,...r].includes(f)&&p(null),await y()}catch(e){n({title:`Decision failed`,description:e instanceof Error?e.message:`Unknown error`,variant:`destructive`})}finally{_(!1)}}};return(0,Q.jsxs)(`div`,{className:`space-y-3`,children:[(0,Q.jsxs)(`div`,{className:`flex items-center justify-between gap-2 flex-wrap`,children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`select`,{className:`h-8 rounded-md border bg-background px-2 text-xs outline-none focus:ring-2 focus:ring-ring`,value:i,onChange:e=>a(e.target.value),children:Nr.map(e=>(0,Q.jsx)(`option`,{value:e,children:e},e))}),(0,Q.jsx)(H,{size:`sm`,variant:`ghost`,onClick:()=>void y(),title:`Reload`,children:(0,Q.jsx)(R,{className:`h-4 w-4`})})]}),u.size>0&&(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[u.size,` selected`]}),(0,Q.jsxs)(H,{size:`sm`,disabled:g,onClick:()=>void te([...u],[]),children:[(0,Q.jsx)(j,{className:`mr-1 h-3.5 w-3.5`}),` Approve`]}),(0,Q.jsxs)(H,{size:`sm`,variant:`outline`,disabled:g,onClick:()=>void te([],[...u]),children:[(0,Q.jsx)(w,{className:`mr-1 h-3.5 w-3.5`}),` Decline`]})]})]}),(0,Q.jsx)(`div`,{className:`border rounded-lg overflow-auto max-h-[560px]`,children:c?(0,Q.jsx)(`p`,{className:`text-sm text-muted-foreground p-3`,children:`Loading...`}):o.length===0?(0,Q.jsx)(`p`,{className:`text-sm text-muted-foreground p-3`,children:i===`pending`?`Nothing waiting for review. Rules or hooks with approval enabled queue their actions here.`:`No ${i===`all`?``:i+` `}actions recorded.`}):(0,Q.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,Q.jsx)(`thead`,{className:`text-xs text-muted-foreground border-b sticky top-0 bg-background`,children:(0,Q.jsxs)(`tr`,{children:[(0,Q.jsx)(`th`,{className:`px-3 py-2 w-8`,children:C.length>0&&(0,Q.jsx)(`input`,{type:`checkbox`,checked:T,onChange:E,title:`Select all pending`})}),(0,Q.jsx)(`th`,{className:`text-left font-medium px-3 py-2`,children:`Proposed action`}),(0,Q.jsx)(`th`,{className:`text-left font-medium px-3 py-2`,children:`Handler`}),(0,Q.jsx)(`th`,{className:`text-left font-medium px-3 py-2`,children:`Age`}),(0,Q.jsx)(`th`,{className:`text-left font-medium px-3 py-2`,children:`Status`}),(0,Q.jsx)(`th`,{className:`px-2 py-2 w-40`})]})}),(0,Q.jsx)(`tbody`,{children:o.map(t=>{let n=t.status===`pending`||t.status===`failed`,r=f===t.actionId,i=r?Mr(t,n?m[t.actionId]??{}:{}):t.actions,a=t.envelope?.payload?.document;return(0,Q.jsxs)(Z.Fragment,{children:[(0,Q.jsxs)(`tr`,{className:`border-b last:border-0 align-top hover:bg-muted/40 cursor-pointer`,onClick:()=>p(r?null:t.actionId),children:[(0,Q.jsx)(`td`,{className:`px-3 py-2`,onClick:e=>e.stopPropagation(),children:t.status===`pending`&&(0,Q.jsx)(`input`,{type:`checkbox`,checked:u.has(t.actionId),onChange:()=>ee(t.actionId)})}),(0,Q.jsxs)(`td`,{className:`px-3 py-2`,children:[(0,Q.jsxs)(`span`,{className:`flex items-center gap-1 font-medium`,children:[r?(0,Q.jsx)(re,{className:`h-3 w-3 shrink-0`}):(0,Q.jsx)(A,{className:`h-3 w-3 shrink-0`}),t.title,t.editable?.length>0&&(0,Q.jsx)(`span`,{className:`text-[10px] uppercase tracking-wide rounded bg-muted-foreground/15 px-1 py-0.5 text-muted-foreground shrink-0`,children:`editable`})]}),t.summary&&(0,Q.jsx)(`span`,{className:`block text-xs text-muted-foreground pl-4`,children:(0,Q.jsx)(Br,{workspaceId:e,text:t.summary})})]}),(0,Q.jsxs)(`td`,{className:`px-3 py-2 font-mono text-xs whitespace-nowrap`,children:[(0,Q.jsxs)(`span`,{className:`text-muted-foreground`,children:[t.handlerType,`:`]}),t.handler,t.event&&(0,Q.jsxs)(`span`,{className:`block text-muted-foreground`,children:[t.event,a?.id!=null&&(0,Q.jsxs)(Q.Fragment,{children:[` · `,(0,Q.jsx)(zr,{workspaceId:e,id:a.id})]})]})]}),(0,Q.jsx)(`td`,{className:`px-3 py-2 text-xs whitespace-nowrap`,title:t.ts,children:Fr(t.ts)}),(0,Q.jsxs)(`td`,{className:`px-3 py-2 text-xs`,children:[(0,Q.jsx)(`span`,{className:Pr[t.status],children:t.status}),t.amended&&(0,Q.jsx)(`span`,{className:`block text-muted-foreground`,children:`amended`}),t.decidedBy&&(0,Q.jsx)(`span`,{className:`block text-muted-foreground truncate max-w-[120px]`,title:t.decidedBy,children:t.decidedBy})]}),(0,Q.jsx)(`td`,{className:`px-2 py-2 whitespace-nowrap text-right`,onClick:e=>e.stopPropagation(),children:n&&(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(H,{size:`sm`,className:`h-7 px-2`,disabled:g,title:t.status===`failed`?`Retry (re-approve)`:`Approve and execute`,onClick:()=>void te([t.actionId],[]),children:(0,Q.jsx)(j,{className:`h-3.5 w-3.5`})}),t.status===`pending`&&(0,Q.jsx)(H,{size:`sm`,variant:`ghost`,className:`h-7 px-2 text-muted-foreground`,disabled:g,title:`Decline`,onClick:()=>void te([],[t.actionId]),children:(0,Q.jsx)(w,{className:`h-3.5 w-3.5`})})]})})]}),r&&(0,Q.jsxs)(`tr`,{className:`border-b last:border-0 bg-muted/20`,children:[(0,Q.jsx)(`td`,{className:`px-3 py-3`}),(0,Q.jsxs)(`td`,{className:`px-3 py-3 space-y-3`,colSpan:5,children:[n&&t.editable?.length>0&&(0,Q.jsx)(Vr,{action:t,amend:m[t.actionId]??{},onAmend:(e,n)=>D(t.actionId,e,n)}),i.map((e,n)=>{let r=Ar(e,t.pathMatch);return r&&(0,Q.jsxs)(`p`,{className:`text-xs`,children:[(0,Q.jsx)(`span`,{className:`font-medium`,children:`Destination folder: `}),(0,Q.jsx)(`span`,{className:`font-mono break-all`,children:r})]},n)}),(0,Q.jsxs)(`div`,{children:[(0,Q.jsx)(`span`,{className:`text-xs font-medium text-muted-foreground`,children:`Actions on approve`}),(0,Q.jsx)(`pre`,{className:`mt-1 rounded border bg-background p-2 font-mono text-xs overflow-auto max-h-56`,children:JSON.stringify(i.map(e=>jr(e,t.pathMatch)),null,2)})]}),(0,Q.jsxs)(`details`,{className:`text-xs text-muted-foreground`,children:[(0,Q.jsx)(`summary`,{className:`cursor-pointer`,children:`Rule action settings`}),(0,Q.jsx)(`pre`,{className:`mt-1 rounded border bg-background p-2 font-mono overflow-auto max-h-56`,children:JSON.stringify(i,null,2)})]}),t.result&&t.result.length>0&&(0,Q.jsx)(`div`,{className:`text-xs font-mono`,children:t.result.map((e,t)=>(0,Q.jsxs)(`span`,{className:`mr-2 ${e.status===`error`?`text-destructive`:`text-muted-foreground`}`,children:[e.action,`:`,e.status,e.error?` (${e.error})`:``]},t))}),(0,Q.jsxs)(`p`,{className:`text-[11px] text-muted-foreground font-mono`,children:[t.actionId,` · origin `,t.provenance?.origin,t.provenance?.causedBy?` · causedBy ${t.provenance.causedBy}`:``,t.expiresAt?` · expires ${new Date(t.expiresAt).toLocaleString()}`:``]})]})]})]},t.actionId)})})]})})]})}var Ur=`#!/usr/bin/env bash
|
|
2
2
|
# Called from a hook via: spawn('bash', [script, ...args])
|
|
3
3
|
set -euo pipefail
|
|
4
4
|
`;function Wr({workspaceId:e,prefillRule:t,onPrefillConsumed:n,initialSection:r,initialRunsHandler:i,initialRunId:a}){let{showToast:o}=K(),[s,c]=(0,Z.useState)(r??`rules`),[l,u]=(0,Z.useState)(t);t!==l&&(u(t),t&&c(`rules`));let[d,p]=(0,Z.useState)(!1),[m,h]=(0,Z.useState)([]),[v,y]=(0,Z.useState)(!0),[x,S]=(0,Z.useState)(null),[C,T]=(0,Z.useState)(``),[O,k]=(0,Z.useState)(!1),[A,j]=(0,Z.useState)(!1),[ae,N]=(0,Z.useState)(!1),[F,oe]=(0,Z.useState)(null),[se,le]=(0,Z.useState)(`document.inserted`),[I,de]=(0,Z.useState)(``),[pe,L]=(0,Z.useState)([]),[me,z]=(0,Z.useState)(!1),[ge,_e]=(0,Z.useState)([]),[ve,B]=(0,Z.useState)(!1),[V,be]=(0,Z.useState)(i||null),[W,xe]=(0,Z.useState)(a?{runId:a,run:null}:null),G=e=>{xe(t=>t?.runId===e?null:{runId:e,run:null})};(0,Z.useEffect)(()=>{if(!W||W.run||W.error)return;let t=!1;return wt(e,W.runId).then(e=>{t||xe(t=>t?.runId===e.runId?{runId:e.runId,run:e}:t)}).catch(e=>{t||xe(t=>t?.runId===W.runId?{...t,error:e instanceof Error?e.message:`Failed to load run`}:t)}),()=>{t=!0}},[e,W]);let[Ce,we]=(0,Z.useState)(null),[Te,Ee]=(0,Z.useState)(!1),[De,Oe]=(0,Z.useState)(0),[q,ke]=(0,Z.useState)(null),[Ae,je]=(0,Z.useState)(()=>Dt()),[Me,Ne]=(0,Z.useState)(()=>String(Dt())),Pe=()=>{let e=kt(Xt(Me));je(e),Ne(String(e))};(0,Z.useEffect)(()=>{let t=!1;return At(e,{status:`pending`,limit:500}).then(e=>{t||Oe(e.length)}).catch(()=>{}),()=>{t=!0}},[e]),mt(()=>Ee(!1),Te);let J=async t=>{if(confirm(`Replay ${t.handlerType} "${t.handler}" for ${t.event} (docs ${(t.docIds||[]).join(`, `)})?`)){we(t.runId);try{let n=await It(e,t.runId);o({title:`Replayed`,description:`${t.handler} → ${n.status}`}),await Y()}catch(e){o({title:`Replay failed`,description:e instanceof Error?e.message:`Unknown error`,variant:`destructive`})}finally{we(null)}}},Fe=s===`scripts`?{list:Kt,get:qt,save:Wt,del:Ut}:{list:Ot,get:Et,save:Bt,del:Yt},Ie=s===`hooks`||s===`scripts`,Y=async()=>{if(s!==`rules`&&s!==`pending`){if(s===`runs`){try{y(!0),_e(await jt(e,{limit:100,failed:ve||void 0,handler:V||void 0}))}catch{o({title:`Error`,description:`Failed to load hook runs`,variant:`destructive`})}finally{y(!1)}return}try{y(!0),h(await Fe.list(e))}catch{o({title:`Error`,description:`Failed to load ${s}`,variant:`destructive`})}finally{y(!1)}}};(0,Z.useEffect)(()=>{Y()},[e,s,ve,V]);let Le=e=>{e!==s&&(O&&!confirm(`Discard unsaved changes?`)||(c(e),S(null),T(``),k(!1),N(!1)))},Re=async t=>{if(!(O&&!confirm(`Discard unsaved changes?`)))try{S(t),T(await Fe.get(e,t)),k(!1)}catch{o({title:`Error`,description:`Failed to open ${t}`,variant:`destructive`})}},ze=async()=>{if(x)try{j(!0),await Fe.save(e,x,C),k(!1),o({title:`Saved`,description:`${x} saved`}),await Y()}catch{o({title:`Error`,description:`Failed to save ${x}`,variant:`destructive`})}finally{j(!1)}},Be=async t=>{let n=Ft(t);try{let r=await zt(e,t,!n);x===t&&S(r),await Y(),o({title:n?`Disabled`:`Enabled`,description:r})}catch{o({title:`Error`,description:`Failed to toggle ${t}`,variant:`destructive`})}},Ve=async t=>{let n=Mt(t);if(!n||!Ft(t)&&!confirm(`${t} is disabled. Run it anyway?`))return;let r=n.startsWith(`document.`);if(!(r&&!confirm(`Run ${t} against up to ${Ae} existing documents (event ${n})?`))){ke(t);try{if(r){let r=await Vt(e,{hookFile:t,event:n,limit:Ae});o({title:`Run finished`,description:`${r.processed} documents processed, ${r.failed} failed. Details in the Runs tab`,...r.failed?{variant:`destructive`}:{}})}else{let r=await Tt(e,{hookFile:t,event:n});o({title:r.status===`error`?`Run failed`:`Run finished`,description:r.status===`error`?`${t}: ${r.error||`see the Runs tab`}`:`${t} → ${r.status}${r.durationMs==null?``:` in ${r.durationMs}ms`}`,...r.status===`error`?{variant:`destructive`}:{}})}}catch(e){o({title:`Run failed`,description:e instanceof Error?e.message:`Unknown error`,variant:`destructive`})}finally{ke(null)}}},He=async t=>{if(confirm(`Delete ${s===`hooks`?`hook`:`script`} ${t}?`))try{await Fe.del(e,t),x===t&&(S(null),T(``),k(!1)),await Y(),o({title:`Deleted`,description:`${t} deleted`})}catch{o({title:`Error`,description:`Failed to delete ${t}`,variant:`destructive`})}},Ue=async()=>{if(!F)try{oe(await Pt(e))}catch{o({title:`Error`,description:`Failed to load hook metadata`,variant:`destructive`})}},X=async()=>{N(!ae),s===`hooks`&&await Ue()},We=async()=>{p(!d),await Ue()},Ge=async()=>{let t=I.trim().replace(/^\/+/,``);if(!t){o({title:`Error`,description:`Give the script a name (e.g. on-image.sh)`,variant:`destructive`});return}try{z(!0),await Wt(e,t,Ur),N(!1),de(``),await Y(),await Re(t)}catch{o({title:`Error`,description:`Failed to create script`,variant:`destructive`})}finally{z(!1)}},Ke=e=>{L(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e])},qe=async()=>{if(!I.trim()){o({title:`Error`,description:`Give the hook a name`,variant:`destructive`});return}try{z(!0);let{path:t}=await Rt(e,{event:se,name:I.trim(),actions:pe});N(!1),de(``),L([]),await Y(),await Re(t),o({title:`Created`,description:`${t}. Edit the TODOs, then enable it`})}catch{o({title:`Error`,description:`Failed to create hook`,variant:`destructive`})}finally{z(!1)}},Je=s===`hooks`?Gt(m):{scripts:m},Ye=`${Se}/workspaces/${e}/git/internal`;return(0,Q.jsxs)(`div`,{className:`@container space-y-4`,children:[(0,Q.jsxs)(`div`,{className:`flex flex-col gap-3 @3xl:flex-row @3xl:items-start @3xl:justify-between`,children:[(0,Q.jsxs)(`div`,{className:`min-w-0 @3xl:min-w-[18rem] @3xl:flex-1`,children:[(0,Q.jsx)(`h3`,{className:`text-lg font-medium`,children:`Automation`}),(0,Q.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Rules are simple click-to-build automations (Outlook-style). Hooks are their programmable big brother; scripts are the shell helpers hooks spawn. Everything commits to the workspace git repo.`})]}),(0,Q.jsx)(`div`,{className:`flex min-w-0 flex-col gap-2 @3xl:max-w-[60%] @3xl:flex-row @3xl:items-center`,children:(0,Q.jsx)(`div`,{className:`w-full min-w-0 @3xl:w-auto`,children:(0,Q.jsx)(bt,{className:`border-b-0`,active:s,onChange:Le,tabs:[{id:`pending`,label:De>0?`Pending (${De})`:`Pending`,icon:f},{id:`rules`,label:`Rules`,icon:ye},{id:`hooks`,label:`Hooks`,icon:ie},{id:`scripts`,label:`Scripts`,icon:P},{id:`runs`,label:`Runs`,icon:_}]})})})]}),(s===`runs`||Ie)&&(0,Q.jsxs)(`div`,{className:`flex flex-wrap items-center justify-end gap-2`,children:[s===`runs`&&(0,Q.jsxs)(Q.Fragment,{children:[V&&(0,Q.jsxs)(`button`,{type:`button`,className:`inline-flex items-center gap-1 rounded-full border bg-muted/50 px-2.5 py-1 font-mono text-xs hover:bg-muted`,title:`Showing runs of this rule / hook only — click to clear`,onClick:()=>be(null),children:[V,` `,(0,Q.jsx)(w,{className:`h-3 w-3`})]}),(0,Q.jsxs)(`label`,{className:`flex items-center gap-1.5 text-xs text-muted-foreground cursor-pointer`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,checked:ve,onChange:e=>B(e.target.checked)}),`failed only`]}),(0,Q.jsxs)(H,{size:`sm`,variant:`ghost`,onClick:Y,title:`Reload`,children:[(0,Q.jsx)(R,{className:`mr-1.5 h-4 w-4`}),` Reload`]})]}),Ie&&(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsxs)(H,{size:`sm`,variant:`ghost`,onClick:Y,title:`Reload`,children:[(0,Q.jsx)(R,{className:`mr-1.5 h-4 w-4`}),` Reload`]}),(0,Q.jsxs)(H,{size:`sm`,variant:`ghost`,onClick:We,title:`Hook context API & classifier reference`,children:[(0,Q.jsx)(he,{className:`mr-1.5 h-4 w-4`}),` Reference`]}),(0,Q.jsxs)(H,{size:`sm`,variant:`outline`,onClick:X,children:[(0,Q.jsx)(D,{className:`mr-2 h-4 w-4`}),` `,s===`hooks`?`New Hook`:`New Script`]})]})]}),s===`pending`&&(0,Q.jsx)(Hr,{workspaceId:e,onPendingCount:Oe}),s===`rules`&&(0,Q.jsx)(Ht,{workspaceId:e,backfillLimit:Ae,onShowRuns:e=>{be(e),Le(`runs`)},prefill:t,onPrefillConsumed:n,onOpenJson:async()=>{try{await Et(e,`rules.json`)}catch{await Bt(e,`rules.json`,JSON.stringify({$schema:`canvas.hook-rules/v1`,rules:[]},null,2)+`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{r}from"./chunk-62JRHF6Z-vspAGgtK.js";import{di as i}from"./ui-CDoK3F3U.js";import{t as a}from"./input-BOtCd4HP.js";import{Nt as o}from"./workspace-
|
|
1
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{r}from"./chunk-62JRHF6Z-vspAGgtK.js";import{di as i}from"./ui-CDoK3F3U.js";import{t as a}from"./input-BOtCd4HP.js";import{Nt as o}from"./workspace-cv6Hrfhh.js";import{p as s}from"./context-1vR30CeC.js";import{i as c,m as l,p as u}from"./use-menu-DIP1zh7I.js";import{Y as d,_t as f,gt as p,ht as m}from"./index-CXPA9Fj8.js";import{n as h}from"./page-header-DrDt1sQ2.js";var g=e(n(),1),_=t(),v=[{id:`workspace`,label:`Workspace`,path:`workspaces`,description:`Files, search, devices and sharing for one workspace. These settings override account defaults.`,sections:f,load:async()=>(await o()).map(e=>({id:e.name,label:e.label||e.name}))},{id:`context`,label:`Context`,path:`contexts`,description:`Choose the tree and path a context opens, and who can access that view. File storage belongs to its workspace.`,sections:p,load:async()=>(await s()).map(e=>({id:e.id,label:e.name||e.id}))},{id:`agent`,label:`Agent`,path:`agents`,description:`Configure one assistant: its instructions, chat model, tools and access to Canvas.`,sections:m,load:async()=>(await d()).map(e=>({id:e.id,label:e.label||e.name}))}];function y({to:e,label:t,description:n,icon:a}){return(0,_.jsxs)(r,{to:e,className:`group flex items-start gap-3 rounded-lg border bg-card p-4 transition-colors hover:border-primary/50 hover:bg-accent/30 focus-visible:outline focus-visible:outline-2 focus-visible:outline-primary`,children:[(0,_.jsx)(a,{className:`mt-0.5 h-5 w-5 shrink-0 text-muted-foreground`}),(0,_.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,_.jsx)(`span`,{className:`block text-sm font-semibold`,children:t}),(0,_.jsx)(`span`,{className:`mt-1 block text-sm leading-relaxed text-muted-foreground`,children:n})]}),(0,_.jsx)(i,{className:`mt-0.5 h-4 w-4 shrink-0 text-muted-foreground group-hover:text-primary`})]})}function b({group:e,query:t}){let[n,r]=(0,g.useState)([]),[i,a]=(0,g.useState)(``),[o,s]=(0,g.useState)(`loading`),[c,u]=(0,g.useState)(0);(0,g.useEffect)(()=>{let t=!1;return e.load().then(e=>{t||(r(e),s(`ready`))}).catch(()=>{t||s(`error`)}),()=>{t=!0}},[e,c]);let d=e.sections.filter(n=>l(t,e.label,n.label,n.description));return d.length?(0,_.jsxs)(`section`,{id:e.id,className:`scroll-mt-6 space-y-3`,children:[(0,_.jsx)(`h2`,{className:`text-lg font-semibold`,children:e.label}),(0,_.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:e.description}),(0,_.jsxs)(`label`,{className:`block max-w-md text-sm font-medium`,children:[`Choose a `,e.label.toLowerCase(),(0,_.jsxs)(`select`,{className:`mt-2 h-10 w-full rounded-md border bg-background px-3 text-sm`,value:i,disabled:o!==`ready`||!n.length,onChange:e=>a(e.target.value),children:[(0,_.jsx)(`option`,{value:``,children:o===`loading`?`Loading…`:o===`error`?`Unable to load list`:n.length?`Select ${e.label.toLowerCase()}…`:`No ${e.path} available`}),n.map(e=>(0,_.jsx)(`option`,{value:e.id,children:e.label},e.id))]})]}),o===`error`&&(0,_.jsxs)(`p`,{role:`status`,className:`text-sm text-muted-foreground`,children:[`The list could not be loaded. `,(0,_.jsx)(`button`,{type:`button`,className:`underline`,onClick:()=>{s(`loading`),u(e=>e+1)},children:`Retry`})]}),(0,_.jsxs)(`details`,{open:!!(i||t.trim()),children:[(0,_.jsx)(`summary`,{className:`cursor-pointer py-2 text-sm text-muted-foreground`,children:i?`Settings for ${n.find(e=>e.id===i)?.label||i}`:`What you can configure (${d.length})`}),(0,_.jsx)(`div`,{className:`grid grid-cols-[repeat(auto-fit,minmax(min(100%,16rem),1fr))] gap-3`,children:d.map(t=>i?(0,_.jsx)(y,{to:`/${e.path}/${encodeURIComponent(i)}/settings/${t.id}`,...t},t.id):(0,_.jsxs)(`div`,{className:`rounded-lg border border-dashed p-4`,children:[(0,_.jsx)(`p`,{className:`text-sm font-medium`,children:t.label}),(0,_.jsx)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:t.description})]},t.id))})]})]}):null}function x(){let{state:e}=c(),[t,n]=(0,g.useState)(``),r=u.filter(t=>t.id!==`server`||e.user?.userType===`admin`).map(e=>({...e,items:e.items.filter(n=>l(t,e.label,n.label,n.description))})).filter(e=>e.items.length),i=v.some(e=>e.sections.some(n=>l(t,e.label,n.label,n.description)));return(0,_.jsxs)(`div`,{className:`mx-auto max-w-6xl space-y-8 pb-8 max-md:pb-rail-stack`,children:[(0,_.jsx)(h,{title:`Settings`,description:`Start with what you want to change. Each section explains where your changes apply.`}),(0,_.jsx)(a,{type:`search`,className:`max-w-xl`,"aria-label":`Search all settings`,placeholder:`Find a setting: offline, folders, models, sharing…`,value:t,onChange:e=>n(e.target.value)}),r.filter(e=>e.id===`device`||e.id===`account`).map(e=>(0,_.jsxs)(`section`,{className:`space-y-3`,children:[(0,_.jsx)(`h2`,{className:`text-lg font-semibold`,children:e.label}),(0,_.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:e.description}),(0,_.jsx)(`div`,{className:`grid grid-cols-[repeat(auto-fit,minmax(min(100%,16rem),1fr))] gap-3`,children:e.items.map(e=>(0,_.jsx)(y,{to:e.path,...e},e.path))})]},e.id)),v.map(e=>(0,_.jsx)(b,{group:e,query:t},e.id)),r.filter(e=>e.id===`server`||e.id===`information`).map(e=>(0,_.jsxs)(`section`,{className:`space-y-3`,children:[(0,_.jsx)(`h2`,{className:`text-lg font-semibold`,children:e.label}),(0,_.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:e.description}),(0,_.jsx)(`div`,{className:`grid grid-cols-[repeat(auto-fit,minmax(min(100%,16rem),1fr))] gap-3`,children:e.items.map(e=>(0,_.jsx)(y,{to:e.path,...e},e.path))})]},e.id)),!r.length&&!i&&(0,_.jsxs)(`p`,{role:`status`,className:`text-sm text-muted-foreground`,children:[`No settings match “`,t,`”. Try a shorter phrase or clear the search.`]})]})}export{x as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{_ as ee,g as r,v as i}from"./chunk-62JRHF6Z-vspAGgtK.js";import{G as te,X as a,kt as o}from"./ui-CDoK3F3U.js";import{t as s}from"./utils-2pl1SbIp.js";import{t as c}from"./button-SeUZ_Pvi.js";import{t as l}from"./input-BOtCd4HP.js";import{n as ne}from"./use-toast-BlLDqSUO.js";import{t as re}from"./use-mobile-Db-vWu9Y.js";import{E as ie,a as ae,c as oe,f as u,r as d,v as se,w as ce,x as le}from"./context-DZ1Hn7tt.js";import{t as f}from"./PathPickerField-B4yFUjgD.js";import{i as ue}from"./use-menu-DIP1zh7I.js";import{gt as p,yt as de}from"./index-Cp75myNf.js";import{n as fe}from"./page-header-DrDt1sQ2.js";var m=e(n(),1),h=t(),g=[{value:`documentRead`,label:`Read`},{value:`documentWrite`,label:`Write`},{value:`documentReadWrite`,label:`Read & write`}];function _(){let{contextId:e,tab:t}=ee(),[n]=i(),_=n.get(`ownerId`)||void 0,v=r(),{showToast:y}=ne(),{selectEntity:b,goBack:x,closeM2:S}=ue(),C=re(),w=de(t),T=_?`?ownerId=${encodeURIComponent(_)}`:``;(0,m.useEffect)(()=>{t!==w&&e&&v(`/contexts/${e}/settings/${w}${T}`,{replace:!0})},[t,w,e,T,v]);let[E,D]=(0,m.useState)(null),[pe,me]=(0,m.useState)(!0),[O,k]=(0,m.useState)(!1),[A,j]=(0,m.useState)(!1),[M,N]=(0,m.useState)(``),[P,F]=(0,m.useState)(``),[I,L]=(0,m.useState)(null),[R,z]=(0,m.useState)(``),[B,V]=(0,m.useState)(``),[H,he]=(0,m.useState)(),[U,W]=(0,m.useState)([]),[G,K]=(0,m.useState)(!1),[q,J]=(0,m.useState)(``),[Y,ge]=(0,m.useState)(g[0].value),[X,Z]=(0,m.useState)(null);(0,m.useEffect)(()=>{if(!e)return;let t=!1;return ae(e,_).then(e=>{t||(D(e),b(e.id),N(e.name||``),F(e.description||``),L(typeof e.metadata?.ui?.color==`string`?e.metadata.ui.color:null),z(e.url||``),V(e.baseUrl||``))}).catch(()=>{t||y({title:`Error`,description:`Failed to load context`,variant:`destructive`})}).finally(()=>{t||me(!1)}),()=>{t=!0}},[e,_,b,y]);let Q=(t=e)=>{t&&(K(!0),u(t).then(W).catch(()=>W([])).finally(()=>K(!1)))};(0,m.useEffect)(()=>{if(w!==`shares`||!e)return;let t=!1;return u(e).then(e=>{t||W(e)}).catch(()=>{t||W([])}),()=>{t=!0}},[w,e]);let _e=async t=>{if(t.preventDefault(),e){k(!0);try{let t=await se(e,{name:M.trim(),description:P.trim(),metadata:{...E?.metadata,ui:{...E?.metadata?.ui,color:I}}},_);D(t),window.dispatchEvent(new CustomEvent(`contexts:refresh`)),y({title:`Saved`,description:`Context updated`})}catch(e){y({title:`Error`,description:e instanceof Error?e.message:`Save failed`,variant:`destructive`})}finally{k(!1)}}},ve=async t=>{if(t.preventDefault(),e){k(!0);try{await Promise.all([ie(e,R.trim(),_,H),ce(e,{baseUrl:B.trim()||null},_)]),window.dispatchEvent(new CustomEvent(`contexts:refresh`)),y({title:`Saved`,description:`Context URL updated`})}catch(e){y({title:`Error`,description:e instanceof Error?e.message:`Save failed`,variant:`destructive`})}finally{k(!1)}}},ye=async()=>{if(e&&window.confirm(`Delete context "${e}"? This cannot be undone.`)){j(!0);try{await d(e,_),S(),b(null),y({title:`Deleted`,description:`Context "${e}" removed`}),v(`/contexts`,{replace:!0})}catch(e){y({title:`Error`,description:e instanceof Error?e.message:`Delete failed`,variant:`destructive`})}finally{j(!1)}}},be=async t=>{if(t.preventDefault(),!(!e||!q.trim())){Z(`grant`);try{await oe(e,q.trim(),Y),J(``),Q(),y({title:`Shared`,description:`Access granted to ${q.trim()}`})}catch(e){y({title:`Error`,description:e instanceof Error?e.message:`Failed to grant access`,variant:`destructive`})}finally{Z(null)}}},xe=async t=>{if(e&&window.confirm(`Revoke ${t.userEmail}'s access to "${e}"?`)){Z(t.userEmail);try{await le(e,t.userEmail),Q(),y({title:`Revoked`,description:`${t.userEmail} no longer has access`})}catch(e){y({title:`Error`,description:e instanceof Error?e.message:`Failed to revoke access`,variant:`destructive`})}finally{Z(null)}}};if(pe)return(0,h.jsx)(`div`,{className:`p-6 text-sm text-muted-foreground`,children:`Loading...`});if(!E)return(0,h.jsx)(`div`,{className:`p-6 text-sm text-muted-foreground`,children:`Context not found`});let $=p.find(e=>e.id===w),Se=`/contexts/${e}${T}`;return(0,h.jsx)(`div`,{className:`h-full min-h-0 overflow-y-auto`,children:(0,h.jsxs)(`div`,{className:`mx-auto max-w-3xl p-6 pb-12 max-md:px-4 max-md:pb-rail-stack`,children:[(0,h.jsx)(fe,{compact:!0,className:`mb-6 border-b pb-4`,title:`${$.label} - ${E.name||E.id}`,description:$.description,backTo:Se,onBack:C?x:void 0}),w===`general`&&(0,h.jsxs)(`div`,{className:`space-y-6`,children:[(0,h.jsxs)(`form`,{onSubmit:_e,className:`space-y-4 rounded-lg border p-4`,children:[(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{className:`text-sm font-medium`,children:`Context ID`}),(0,h.jsx)(`div`,{className:`mt-1 flex h-10 items-center rounded-md bg-muted px-3 font-mono text-sm text-muted-foreground`,children:E.id})]}),(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{htmlFor:`ctx-name`,className:`text-sm font-medium`,children:`Name`}),(0,h.jsx)(l,{id:`ctx-name`,value:M,onChange:e=>N(e.target.value),placeholder:`My Context`})]}),(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{htmlFor:`ctx-description`,className:`text-sm font-medium`,children:`Description`}),(0,h.jsx)(l,{id:`ctx-description`,value:P,onChange:e=>F(e.target.value),placeholder:`Optional description`})]}),(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{htmlFor:`ctx-color`,className:`text-sm font-medium`,children:`Color`}),(0,h.jsxs)(`div`,{className:`mt-1 flex items-center gap-2`,children:[(0,h.jsx)(l,{id:`ctx-color`,type:`color`,value:/^#[0-9a-f]{6}$/i.test(I||E.color||``)?I||E.color:`#808080`,onChange:e=>L(e.target.value),className:`h-10 w-16 p-1`,disabled:O}),(0,h.jsx)(c,{type:`button`,variant:`outline`,size:`sm`,disabled:O||I===null,onClick:()=>L(null),children:`Use inherited color`})]}),(0,h.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:I===null?`Using the tree folder or workspace color.`:`Applies only to this context.`})]}),(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{className:`text-sm font-medium`,children:`Workspace`}),(0,h.jsx)(`div`,{className:`mt-1 flex h-10 items-center rounded-md bg-muted px-3 text-sm text-muted-foreground`,children:E.workspaceName||E.workspaceId||E.workspace})]}),(0,h.jsx)(c,{type:`submit`,disabled:O,children:O?`Saving...`:`Save Changes`})]}),(0,h.jsxs)(`section`,{className:`rounded-lg border border-destructive/30 p-4`,children:[(0,h.jsx)(`h2`,{className:`mb-3 text-sm font-semibold text-destructive`,children:`Danger Zone`}),(0,h.jsxs)(c,{variant:`destructive`,disabled:A,onClick:ye,children:[(0,h.jsx)(a,{className:`mr-2 h-4 w-4`}),A?`Deleting...`:`Delete Context`]})]})]}),w===`location`&&(0,h.jsxs)(`form`,{onSubmit:ve,className:`space-y-4 rounded-lg border p-4`,children:[(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{htmlFor:`ctx-url`,className:`text-sm font-medium`,children:`URL`}),(0,h.jsx)(f,{id:`ctx-url`,value:R,onChange:z,fixedWorkspaceName:E.workspaceName,pickerTitle:`Switch context to…`,placeholder:`workspace://path`,onPickTarget:(e,t)=>{z(`${t.workspaceName}://${e.replace(/^\/+/,``)}`),he(t.treeName)}}),H&&(0,h.jsxs)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:[`Destination tree: `,H]})]}),(0,h.jsxs)(`div`,{children:[(0,h.jsxs)(`label`,{htmlFor:`ctx-base-url`,className:`text-sm font-medium`,children:[`Base URL `,(0,h.jsx)(`span`,{className:`font-normal text-muted-foreground`,children:`(optional)`})]}),(0,h.jsx)(f,{id:`ctx-base-url`,value:B,onChange:V,fixedWorkspaceName:E.workspaceName,placeholder:`workspace://base/path`,pickerTitle:`Pick a base path…`})]}),(0,h.jsx)(c,{type:`submit`,disabled:O,children:O?`Saving...`:`Save Changes`})]}),w===`shares`&&(0,h.jsxs)(`div`,{className:`space-y-4`,children:[(0,h.jsxs)(`section`,{className:`space-y-3 rounded-lg border p-4`,children:[(0,h.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`h2`,{className:`text-sm font-semibold`,children:`People with access`}),(0,h.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Only the context owner can see and change this list.`})]}),(0,h.jsxs)(c,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>Q(),disabled:G,children:[(0,h.jsx)(o,{className:s(`mr-2 h-3.5 w-3.5`,G&&`animate-spin`)}),`Refresh`]})]}),U.length===0?(0,h.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-sm text-muted-foreground`,children:`Not shared with anyone.`}):U.map(e=>(0,h.jsxs)(`div`,{className:`flex items-start justify-between gap-3 rounded-md border p-3`,children:[(0,h.jsxs)(`div`,{className:`min-w-0`,children:[(0,h.jsx)(`div`,{className:`truncate text-sm font-medium`,children:e.userEmail}),(0,h.jsxs)(`div`,{className:`text-xs text-muted-foreground`,children:[g.find(t=>t.value===e.accessLevel)?.label||e.accessLevel||`unknown access`,e.sharedAt&&` - since ${new Date(e.sharedAt).toLocaleDateString()}`]})]}),(0,h.jsx)(c,{type:`button`,variant:`outline`,size:`sm`,className:`text-destructive hover:text-destructive`,disabled:X===e.userEmail,onClick:()=>xe(e),children:(0,h.jsx)(te,{className:`h-3.5 w-3.5`})})]},e.userEmail))]}),(0,h.jsxs)(`form`,{onSubmit:be,className:`space-y-4 rounded-lg border p-4`,children:[(0,h.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Grant access`}),(0,h.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:[(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{htmlFor:`share-email`,className:`text-sm font-medium`,children:`User email`}),(0,h.jsx)(l,{id:`share-email`,type:`email`,value:q,onChange:e=>J(e.target.value),placeholder:`person@example.com`}),(0,h.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:`The user must already have an account on this server.`})]}),(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{htmlFor:`share-level`,className:`text-sm font-medium`,children:`Access level`}),(0,h.jsx)(`select`,{id:`share-level`,value:Y,onChange:e=>ge(e.target.value),className:`mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring`,children:g.map(e=>(0,h.jsx)(`option`,{value:e.value,children:e.label},e.value))})]})]}),(0,h.jsx)(c,{type:`submit`,disabled:X===`grant`||!q.trim(),children:X===`grant`?`Sharing...`:`Share context`})]})]})]})})}export{_ as default};
|
|
1
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{_ as ee,g as r,v as i}from"./chunk-62JRHF6Z-vspAGgtK.js";import{G as te,X as a,kt as o}from"./ui-CDoK3F3U.js";import{t as s}from"./utils-2pl1SbIp.js";import{t as c}from"./button-SeUZ_Pvi.js";import{t as l}from"./input-BOtCd4HP.js";import{n as ne}from"./use-toast-BlLDqSUO.js";import{t as re}from"./use-mobile-Db-vWu9Y.js";import{E as ie,a as ae,c as oe,f as u,r as d,v as se,w as ce,x as le}from"./context-1vR30CeC.js";import{t as f}from"./PathPickerField-D7SubxSh.js";import{i as ue}from"./use-menu-DIP1zh7I.js";import{gt as p,yt as de}from"./index-CXPA9Fj8.js";import{n as fe}from"./page-header-DrDt1sQ2.js";var m=e(n(),1),h=t(),g=[{value:`documentRead`,label:`Read`},{value:`documentWrite`,label:`Write`},{value:`documentReadWrite`,label:`Read & write`}];function _(){let{contextId:e,tab:t}=ee(),[n]=i(),_=n.get(`ownerId`)||void 0,v=r(),{showToast:y}=ne(),{selectEntity:b,goBack:x,closeM2:S}=ue(),C=re(),w=de(t),T=_?`?ownerId=${encodeURIComponent(_)}`:``;(0,m.useEffect)(()=>{t!==w&&e&&v(`/contexts/${e}/settings/${w}${T}`,{replace:!0})},[t,w,e,T,v]);let[E,D]=(0,m.useState)(null),[pe,me]=(0,m.useState)(!0),[O,k]=(0,m.useState)(!1),[A,j]=(0,m.useState)(!1),[M,N]=(0,m.useState)(``),[P,F]=(0,m.useState)(``),[I,L]=(0,m.useState)(null),[R,z]=(0,m.useState)(``),[B,V]=(0,m.useState)(``),[H,he]=(0,m.useState)(),[U,W]=(0,m.useState)([]),[G,K]=(0,m.useState)(!1),[q,J]=(0,m.useState)(``),[Y,ge]=(0,m.useState)(g[0].value),[X,Z]=(0,m.useState)(null);(0,m.useEffect)(()=>{if(!e)return;let t=!1;return ae(e,_).then(e=>{t||(D(e),b(e.id),N(e.name||``),F(e.description||``),L(typeof e.metadata?.ui?.color==`string`?e.metadata.ui.color:null),z(e.url||``),V(e.baseUrl||``))}).catch(()=>{t||y({title:`Error`,description:`Failed to load context`,variant:`destructive`})}).finally(()=>{t||me(!1)}),()=>{t=!0}},[e,_,b,y]);let Q=(t=e)=>{t&&(K(!0),u(t).then(W).catch(()=>W([])).finally(()=>K(!1)))};(0,m.useEffect)(()=>{if(w!==`shares`||!e)return;let t=!1;return u(e).then(e=>{t||W(e)}).catch(()=>{t||W([])}),()=>{t=!0}},[w,e]);let _e=async t=>{if(t.preventDefault(),e){k(!0);try{let t=await se(e,{name:M.trim(),description:P.trim(),metadata:{...E?.metadata,ui:{...E?.metadata?.ui,color:I}}},_);D(t),window.dispatchEvent(new CustomEvent(`contexts:refresh`)),y({title:`Saved`,description:`Context updated`})}catch(e){y({title:`Error`,description:e instanceof Error?e.message:`Save failed`,variant:`destructive`})}finally{k(!1)}}},ve=async t=>{if(t.preventDefault(),e){k(!0);try{await Promise.all([ie(e,R.trim(),_,H),ce(e,{baseUrl:B.trim()||null},_)]),window.dispatchEvent(new CustomEvent(`contexts:refresh`)),y({title:`Saved`,description:`Context URL updated`})}catch(e){y({title:`Error`,description:e instanceof Error?e.message:`Save failed`,variant:`destructive`})}finally{k(!1)}}},ye=async()=>{if(e&&window.confirm(`Delete context "${e}"? This cannot be undone.`)){j(!0);try{await d(e,_),S(),b(null),y({title:`Deleted`,description:`Context "${e}" removed`}),v(`/contexts`,{replace:!0})}catch(e){y({title:`Error`,description:e instanceof Error?e.message:`Delete failed`,variant:`destructive`})}finally{j(!1)}}},be=async t=>{if(t.preventDefault(),!(!e||!q.trim())){Z(`grant`);try{await oe(e,q.trim(),Y),J(``),Q(),y({title:`Shared`,description:`Access granted to ${q.trim()}`})}catch(e){y({title:`Error`,description:e instanceof Error?e.message:`Failed to grant access`,variant:`destructive`})}finally{Z(null)}}},xe=async t=>{if(e&&window.confirm(`Revoke ${t.userEmail}'s access to "${e}"?`)){Z(t.userEmail);try{await le(e,t.userEmail),Q(),y({title:`Revoked`,description:`${t.userEmail} no longer has access`})}catch(e){y({title:`Error`,description:e instanceof Error?e.message:`Failed to revoke access`,variant:`destructive`})}finally{Z(null)}}};if(pe)return(0,h.jsx)(`div`,{className:`p-6 text-sm text-muted-foreground`,children:`Loading...`});if(!E)return(0,h.jsx)(`div`,{className:`p-6 text-sm text-muted-foreground`,children:`Context not found`});let $=p.find(e=>e.id===w),Se=`/contexts/${e}${T}`;return(0,h.jsx)(`div`,{className:`h-full min-h-0 overflow-y-auto`,children:(0,h.jsxs)(`div`,{className:`mx-auto max-w-3xl p-6 pb-12 max-md:px-4 max-md:pb-rail-stack`,children:[(0,h.jsx)(fe,{compact:!0,className:`mb-6 border-b pb-4`,title:`${$.label} - ${E.name||E.id}`,description:$.description,backTo:Se,onBack:C?x:void 0}),w===`general`&&(0,h.jsxs)(`div`,{className:`space-y-6`,children:[(0,h.jsxs)(`form`,{onSubmit:_e,className:`space-y-4 rounded-lg border p-4`,children:[(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{className:`text-sm font-medium`,children:`Context ID`}),(0,h.jsx)(`div`,{className:`mt-1 flex h-10 items-center rounded-md bg-muted px-3 font-mono text-sm text-muted-foreground`,children:E.id})]}),(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{htmlFor:`ctx-name`,className:`text-sm font-medium`,children:`Name`}),(0,h.jsx)(l,{id:`ctx-name`,value:M,onChange:e=>N(e.target.value),placeholder:`My Context`})]}),(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{htmlFor:`ctx-description`,className:`text-sm font-medium`,children:`Description`}),(0,h.jsx)(l,{id:`ctx-description`,value:P,onChange:e=>F(e.target.value),placeholder:`Optional description`})]}),(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{htmlFor:`ctx-color`,className:`text-sm font-medium`,children:`Color`}),(0,h.jsxs)(`div`,{className:`mt-1 flex items-center gap-2`,children:[(0,h.jsx)(l,{id:`ctx-color`,type:`color`,value:/^#[0-9a-f]{6}$/i.test(I||E.color||``)?I||E.color:`#808080`,onChange:e=>L(e.target.value),className:`h-10 w-16 p-1`,disabled:O}),(0,h.jsx)(c,{type:`button`,variant:`outline`,size:`sm`,disabled:O||I===null,onClick:()=>L(null),children:`Use inherited color`})]}),(0,h.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:I===null?`Using the tree folder or workspace color.`:`Applies only to this context.`})]}),(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{className:`text-sm font-medium`,children:`Workspace`}),(0,h.jsx)(`div`,{className:`mt-1 flex h-10 items-center rounded-md bg-muted px-3 text-sm text-muted-foreground`,children:E.workspaceName||E.workspaceId||E.workspace})]}),(0,h.jsx)(c,{type:`submit`,disabled:O,children:O?`Saving...`:`Save Changes`})]}),(0,h.jsxs)(`section`,{className:`rounded-lg border border-destructive/30 p-4`,children:[(0,h.jsx)(`h2`,{className:`mb-3 text-sm font-semibold text-destructive`,children:`Danger Zone`}),(0,h.jsxs)(c,{variant:`destructive`,disabled:A,onClick:ye,children:[(0,h.jsx)(a,{className:`mr-2 h-4 w-4`}),A?`Deleting...`:`Delete Context`]})]})]}),w===`location`&&(0,h.jsxs)(`form`,{onSubmit:ve,className:`space-y-4 rounded-lg border p-4`,children:[(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{htmlFor:`ctx-url`,className:`text-sm font-medium`,children:`URL`}),(0,h.jsx)(f,{id:`ctx-url`,value:R,onChange:z,fixedWorkspaceName:E.workspaceName,pickerTitle:`Switch context to…`,placeholder:`workspace://path`,onPickTarget:(e,t)=>{z(`${t.workspaceName}://${e.replace(/^\/+/,``)}`),he(t.treeName)}}),H&&(0,h.jsxs)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:[`Destination tree: `,H]})]}),(0,h.jsxs)(`div`,{children:[(0,h.jsxs)(`label`,{htmlFor:`ctx-base-url`,className:`text-sm font-medium`,children:[`Base URL `,(0,h.jsx)(`span`,{className:`font-normal text-muted-foreground`,children:`(optional)`})]}),(0,h.jsx)(f,{id:`ctx-base-url`,value:B,onChange:V,fixedWorkspaceName:E.workspaceName,placeholder:`workspace://base/path`,pickerTitle:`Pick a base path…`})]}),(0,h.jsx)(c,{type:`submit`,disabled:O,children:O?`Saving...`:`Save Changes`})]}),w===`shares`&&(0,h.jsxs)(`div`,{className:`space-y-4`,children:[(0,h.jsxs)(`section`,{className:`space-y-3 rounded-lg border p-4`,children:[(0,h.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`h2`,{className:`text-sm font-semibold`,children:`People with access`}),(0,h.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Only the context owner can see and change this list.`})]}),(0,h.jsxs)(c,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>Q(),disabled:G,children:[(0,h.jsx)(o,{className:s(`mr-2 h-3.5 w-3.5`,G&&`animate-spin`)}),`Refresh`]})]}),U.length===0?(0,h.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-sm text-muted-foreground`,children:`Not shared with anyone.`}):U.map(e=>(0,h.jsxs)(`div`,{className:`flex items-start justify-between gap-3 rounded-md border p-3`,children:[(0,h.jsxs)(`div`,{className:`min-w-0`,children:[(0,h.jsx)(`div`,{className:`truncate text-sm font-medium`,children:e.userEmail}),(0,h.jsxs)(`div`,{className:`text-xs text-muted-foreground`,children:[g.find(t=>t.value===e.accessLevel)?.label||e.accessLevel||`unknown access`,e.sharedAt&&` - since ${new Date(e.sharedAt).toLocaleDateString()}`]})]}),(0,h.jsx)(c,{type:`button`,variant:`outline`,size:`sm`,className:`text-destructive hover:text-destructive`,disabled:X===e.userEmail,onClick:()=>xe(e),children:(0,h.jsx)(te,{className:`h-3.5 w-3.5`})})]},e.userEmail))]}),(0,h.jsxs)(`form`,{onSubmit:be,className:`space-y-4 rounded-lg border p-4`,children:[(0,h.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Grant access`}),(0,h.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:[(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{htmlFor:`share-email`,className:`text-sm font-medium`,children:`User email`}),(0,h.jsx)(l,{id:`share-email`,type:`email`,value:q,onChange:e=>J(e.target.value),placeholder:`person@example.com`}),(0,h.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:`The user must already have an account on this server.`})]}),(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`label`,{htmlFor:`share-level`,className:`text-sm font-medium`,children:`Access level`}),(0,h.jsx)(`select`,{id:`share-level`,value:Y,onChange:e=>ge(e.target.value),className:`mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring`,children:g.map(e=>(0,h.jsx)(`option`,{value:e.value,children:e.label},e.value))})]})]}),(0,h.jsx)(c,{type:`submit`,disabled:X===`grant`||!q.trim(),children:X===`grant`?`Sharing...`:`Share context`})]})]})]})})}export{_ as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{_ as r,g as ee}from"./chunk-62JRHF6Z-vspAGgtK.js";import{X as i}from"./ui-CDoK3F3U.js";import{t as a}from"./button-SeUZ_Pvi.js";import{t as o}from"./input-BOtCd4HP.js";import{n as te}from"./use-toast-BlLDqSUO.js";import{Nt as ne}from"./workspace-BJELPCNs.js";import{t as re}from"./use-mobile-Db-vWu9Y.js";import{p as ie}from"./context-DZ1Hn7tt.js";import{t as s}from"./color-DFEH4BfK.js";import{i as ae}from"./use-menu-DIP1zh7I.js";import{$ as oe,H as se,J as ce,K as le,Q as ue,U as de,X as fe,Z as pe,et as me,ht as he,q as ge,rt as _e,vt as ve,z as ye}from"./index-Cp75myNf.js";import{n as be}from"./page-header-DrDt1sQ2.js";import{n as xe,r as Se,t as Ce}from"./useAgentModels-B10Tbl6D.js";var c=e(n(),1),l=t(),we={anthropic:`claude-3-5-sonnet-20241022`,openai:`gpt-4o`,ollama:`qwen2.5-coder:latest`,"lm-studio":``,vllm:``,custom:``},u={anthropic:`https://api.anthropic.com`,openai:`https://api.openai.com/v1`,ollama:`http://localhost:11434/v1`,"lm-studio":`http://localhost:1234/v1`,vllm:`http://localhost:8000/v1`,custom:``};function d(e){return u[e]||``}function f({label:e,hint:t,children:n}){return(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`label`,{className:`text-sm font-medium`,children:e}),t&&(0,l.jsx)(`p`,{className:`mb-1 mt-0.5 text-xs text-muted-foreground`,children:t}),(0,l.jsx)(`div`,{className:t?void 0:`mt-1`,children:n})]})}var p=`w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring resize-y`,m=`w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring`;function h(){let{agentId:e,tab:t}=r(),n=ee(),{showToast:u}=te(),{selectEntity:h,goBack:Te}=ae(),Ee=re(),g=ve(t);(0,c.useEffect)(()=>{t!==g&&e&&n(`/agents/${encodeURIComponent(e)}/settings/${g}`,{replace:!0})},[t,g,e,n]);let[_,v]=(0,c.useState)(null),[De,Oe]=(0,c.useState)(!0),[ke,Ae]=(0,c.useState)(null),[je,Me]=(0,c.useState)(!1),[Ne,Pe]=(0,c.useState)(!1),[Fe,Ie]=(0,c.useState)(``),[Le,Re]=(0,c.useState)(``),[ze,Be]=(0,c.useState)(``),[Ve,y]=(0,c.useState)(s()),[b,He]=(0,c.useState)(``),[x,Ue]=(0,c.useState)(``),[S,We]=(0,c.useState)(``),[C,Ge]=(0,c.useState)(``),[w,Ke]=(0,c.useState)(`anthropic`),[T,qe]=(0,c.useState)(``),[E,D]=(0,c.useState)(``),[O,k]=(0,c.useState)(``),[Je,Ye]=(0,c.useState)(.7),[Xe,A]=(0,c.useState)(4096),[Ze,Qe]=(0,c.useState)(1),$e=Ce(w,T,E,_?.id),et=$e.models.find(e=>e.id===O),[tt,j]=(0,c.useState)([]),[M,N]=(0,c.useState)(``),[nt,P]=(0,c.useState)(``),[F,I]=(0,c.useState)(``),[L,R]=(0,c.useState)(``),[rt,it]=(0,c.useState)(!1),[at,ot]=(0,c.useState)(null),[z,B]=(0,c.useState)(null),[st,ct]=(0,c.useState)(null),[V,H]=(0,c.useState)(!1),[U,W]=(0,c.useState)(null),[G,K]=(0,c.useState)(``),[q,J]=(0,c.useState)(!1),[Y,lt]=(0,c.useState)(`context`),[X,ut]=(0,c.useState)(``),[dt,ft]=(0,c.useState)(`/`),[Z,pt]=(0,c.useState)(``),[mt,ht]=(0,c.useState)(!0),[Q,gt]=(0,c.useState)(!1),[_t,vt]=(0,c.useState)([]),[yt,bt]=(0,c.useState)([]),[$,xt]=(0,c.useState)(null),[St,Ct]=(0,c.useState)(`{}`),[wt,Tt]=(0,c.useState)(null),[Et,Dt]=(0,c.useState)(e);Et!==e&&(Dt(e),Oe(!0),v(null)),(0,c.useEffect)(()=>{if(!e)return;let t=!1;return se(e).then(async e=>{if(t)return;let n=e.config?.identity||{};v(e),h(e.id),Ie(e.name||``),Re(e.label||``),Be(e.description||``),y(e.color||s()),He(n.role||``),Ue(n.identity||``),We(n.instructions||``),Ge(e.config?.prompts?.system||``),Ke(e.llmProvider||`anthropic`),qe(e.config?.apiKey||``),D(e.config?.baseUrl||d(e.llmProvider)),k(e.model||we[e.llmProvider]||``);let r=e.config?.connectors?.[e.llmProvider];r&&(Ye(r.temperature??.7),A(r.maxTokens??4096),Qe(r.topP??1)),Ct(JSON.stringify(e.config?.tools??{},null,2)),Tt(null),Ae(null);try{j(await ce(e.id))}catch{j([])}}).catch(e=>{t||Ae(e instanceof Error?e.message:`Failed to load agent`)}).finally(()=>{t||Oe(!1)}),()=>{t=!0}},[e,h]),(0,c.useEffect)(()=>{if(g!==`access`&&g!==`tools`||!_?.id)return;let e=_.id,t=!1;return Promise.all([de(_.id).catch(()=>null),ne().catch(()=>[]),ie().catch(()=>[]),le(_.id).catch(()=>null)]).then(([n,r,ee,i])=>{t||(B(n),vt(r),bt(ee),xt(i?i.tools:[]),ct(e))}),()=>{t=!0}},[g,_?.id]);let Ot=()=>{let e=Se(b,x,S),t;try{let e=JSON.parse(St);e&&typeof e==`object`&&!Array.isArray(e)&&(t=e)}catch{}return{...t===void 0?{}:{tools:t},name:Fe.trim(),label:Le.trim(),description:ze.trim()||void 0,color:Ve,llmProvider:w,model:O,apiKey:T.trim()||(w===_?.llmProvider?void 0:``),baseUrl:E||void 0,config:{type:w,model:O,identity:{role:b.trim()||void 0,identity:x.trim()||void 0,instructions:S.trim()||void 0},prompts:C.trim()||e?{system:C.trim()||e}:void 0,connectors:{[w]:{...w===`anthropic`?{}:{temperature:Je},maxTokens:Xe,topP:Ze}}}}},kt=async e=>{if(e.preventDefault(),_){Me(!0);try{let e=await _e(_.id,Ot());v(e),window.dispatchEvent(new CustomEvent(`agents:refresh`)),u({title:`Saved`,description:`Agent updated`}),e.name&&e.name!==_.name&&n(`/agents/${encodeURIComponent(e.name)}/settings/${g}`,{replace:!0})}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Save failed`,variant:`destructive`})}finally{Me(!1)}}},At=async()=>{if(_&&window.confirm(`Delete agent "${_.label||_.name}"? This cannot be undone.`)){Pe(!0);try{await ye(_.id),window.dispatchEvent(new CustomEvent(`agents:refresh`)),u({title:`Deleted`,description:`Agent removed`}),n(`/agents`)}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Delete failed`,variant:`destructive`})}finally{Pe(!1)}}},jt=()=>{N(``),P(``),I(``),R(``)},Mt=async()=>{if(!(!_||!L.trim()&&!F.trim())){it(!0);try{let e=await ge(_.id,L.trim()?{source:L.trim()}:{name:M,description:nt,content:F});j(e),jt(),window.dispatchEvent(new CustomEvent(`agents:refresh`)),u({title:`Installed`,description:`Skill saved`})}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Skill install failed`,variant:`destructive`})}finally{it(!1)}}},Nt=async e=>{if(_){ot(e);try{let t=await fe(_.id,e);j(t),(M===e||L===e)&&jt(),window.dispatchEvent(new CustomEvent(`agents:refresh`)),u({title:`Removed`,description:`Skill "${e}" removed`})}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Skill remove failed`,variant:`destructive`})}finally{ot(null)}}},Pt=()=>Y===`global`?{type:`global`}:Y===`context`?Z?{type:`context`,context:Z}:null:X?Y===`path`?{type:`path`,workspace:X,path:dt.trim()||`/`}:{type:`workspace`,workspace:X}:null,Ft=async()=>{if(!_||V)return;let e=Pt(),t=[];if(mt&&t.push(`read`),Q&&t.push(`write`),!e||!/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/.test(G.trim())||t.length===0||!q&&z?.grants.some(e=>e.id===G.trim())){u({title:`Invalid binding`,description:`Choose a unique connection name (letters, numbers, hyphens or underscores), scope and permissions`,variant:`destructive`});return}if(!(e.type===`global`&&!window.confirm(`Global scope lets this agent ${Q?`read and write`:`read`} ALL your workspaces. Continue?`))){H(!0);try{let n=await me(_.id,G.trim(),{label:z?.grants.find(e=>e.id===G.trim())?.label||G.trim(),binding:e,permissions:t});B(n.access),W(n.tokens[0]?.token??null),K(``),J(!1),u({title:`Connection saved`,description:`Other connections and their tokens are unchanged`})}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Bind failed`,variant:`destructive`})}finally{H(!1)}}},It=async e=>{if(!(!_||V)){H(!0);try{let t=await oe(_.id,e);B(t.access),W(t.tokens[0]?.token??null),u({title:`Rotated`,description:`New token minted — the previous one no longer works`})}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Rotate failed`,variant:`destructive`})}finally{H(!1)}}},Lt=e=>{K(e.id),J(!0),lt(e.binding.type),ut(e.binding.workspace||``),ft(e.binding.path||`/`),pt(e.binding.context||``),ht(e.permissions.includes(`read`)),gt(e.permissions.includes(`write`))},Rt=async e=>{if(!(!_||V)){H(!0);try{let t=await ue(_.id,e);B(t.access),W(null),G===e&&(K(``),J(!1))}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Revoke failed`,variant:`destructive`})}finally{H(!1)}}},zt=async()=>{if(!(!_||V)&&window.confirm(`Revoke this agent's canvas access? All its connection tokens stop working immediately.`)){H(!0);try{await pe(_.id),B(null),W(null),u({title:`Revoked`,description:`Agent access removed`})}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Revoke failed`,variant:`destructive`})}finally{H(!1)}}},Bt=e=>{if(e.type===`global`)return`Global — all workspaces`;if(e.type===`context`){let t=yt.find(t=>t.id===e.context);return`Context ${t?`${t.id} (${t.url})`:e.context} — follows the context live`}let t=e.workspaceName||e.workspace;return e.type===`path`?`Workspace ${t}, path ${e.path||`/`}`:`Workspace ${t} (whole tree)`};if(De)return(0,l.jsx)(`div`,{className:`p-6 text-sm text-muted-foreground`,children:`Loading...`});if(!_||ke)return(0,l.jsx)(`div`,{className:`p-6 text-sm text-destructive`,children:ke||`Agent not found`});let Vt=he.find(e=>e.id===g),Ht=encodeURIComponent(_.name||_.id),Ut=g===`identity`||g===`provider`||g===`models`||g===`tools`;return(0,l.jsx)(`div`,{className:`h-full min-h-0 overflow-y-auto`,children:(0,l.jsxs)(`div`,{className:`mx-auto max-w-5xl p-6 pb-12 max-md:px-4 max-md:pb-rail-stack`,children:[(0,l.jsx)(be,{compact:!0,className:`mb-6 border-b pb-4`,title:`${Vt.label} - ${_.label||_.name}`,description:Vt.description,backTo:`/agents/${Ht}`,onBack:Ee?Te:void 0}),(0,l.jsxs)(`form`,{onSubmit:kt,className:`space-y-6`,children:[g===`identity`&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsxs)(`section`,{className:`space-y-4 rounded-lg border p-4`,children:[(0,l.jsxs)(`div`,{className:`grid gap-4 md:grid-cols-2`,children:[(0,l.jsx)(f,{label:`Name`,hint:`ID: ${_.id}`,children:(0,l.jsx)(o,{value:Fe,onChange:e=>Ie(e.target.value),placeholder:`lucy`})}),(0,l.jsx)(f,{label:`Label`,children:(0,l.jsx)(o,{value:Le,onChange:e=>Re(e.target.value),placeholder:`Display name`})})]}),(0,l.jsx)(f,{label:`Description`,children:(0,l.jsx)(o,{value:ze,onChange:e=>Be(e.target.value),placeholder:`Short description`})}),(0,l.jsx)(f,{label:`Color`,children:(0,l.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,l.jsx)(o,{type:`color`,value:Ve,onChange:e=>y(e.target.value),className:`h-10 w-16 p-1`}),(0,l.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>y(s()),children:`Randomize`})]})})]}),(0,l.jsxs)(`section`,{className:`space-y-4 rounded-lg border p-4`,children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Persona`}),(0,l.jsx)(f,{label:`Role`,children:(0,l.jsx)(o,{value:b,onChange:e=>He(e.target.value),placeholder:`e.g. Software Engineer`})}),(0,l.jsx)(f,{label:`Identity`,children:(0,l.jsx)(`textarea`,{value:x,onChange:e=>Ue(e.target.value),placeholder:`Who this agent is…`,className:`${p} min-h-[80px]`})}),(0,l.jsx)(f,{label:`Instructions`,children:(0,l.jsx)(`textarea`,{value:S,onChange:e=>We(e.target.value),placeholder:`Behavioral instructions…`,className:`${p} min-h-[80px]`})}),(0,l.jsx)(f,{label:`System Prompt`,hint:`Compiled from Role + Identity + Instructions. Override manually.`,children:(0,l.jsx)(`textarea`,{value:C,onChange:e=>Ge(e.target.value),placeholder:`System prompt sent to the LLM…`,className:`${p} min-h-[140px] font-mono text-xs`})})]}),(0,l.jsxs)(`section`,{className:`rounded-lg border border-destructive/30 p-4`,children:[(0,l.jsx)(`h2`,{className:`mb-3 text-sm font-semibold text-destructive`,children:`Danger Zone`}),(0,l.jsxs)(a,{type:`button`,variant:`destructive`,disabled:Ne,onClick:At,children:[(0,l.jsx)(i,{className:`mr-2 h-4 w-4`}),Ne?`Deleting...`:`Delete Agent`]})]})]}),g===`provider`&&(0,l.jsxs)(`section`,{className:`space-y-4 rounded-lg border p-4`,children:[(0,l.jsx)(f,{label:`Provider`,children:(0,l.jsxs)(`select`,{value:w,onChange:e=>{let t=e.target.value;Ke(t),qe(``),k(we[t]||``),D(d(t))},className:`w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring`,children:[(0,l.jsx)(`option`,{value:`anthropic`,children:`Anthropic Claude`}),(0,l.jsx)(`option`,{value:`openai`,children:`OpenAI GPT`}),(0,l.jsx)(`option`,{value:`ollama`,children:`Ollama (Local)`}),(0,l.jsx)(`option`,{value:`lm-studio`,children:`LM Studio (Local)`}),(0,l.jsx)(`option`,{value:`vllm`,children:`vLLM (Local)`}),(0,l.jsx)(`option`,{value:`custom`,children:`Custom`})]})}),(0,l.jsx)(f,{label:`API Key`,hint:[`ollama`,`lm-studio`,`vllm`].includes(w)?`Any value works for local providers.`:void 0,children:(0,l.jsx)(o,{type:`password`,value:T,onChange:e=>qe(e.target.value),placeholder:w===`ollama`?`ollama`:w===`lm-studio`?`lm-studio`:`sk-…`})}),(0,l.jsx)(f,{label:`Host / Base URL`,children:(0,l.jsx)(o,{value:E,onChange:e=>D(e.target.value),placeholder:d(w)||`https://api.example.com`})})]}),g===`models`&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsxs)(`section`,{className:`space-y-4 rounded-lg border p-4`,children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Main Model`}),(0,l.jsx)(f,{label:`Model`,children:(0,l.jsx)(xe,{value:O,onChange:(e,t)=>{k(e),t?.maxTokens&&A(t.maxTokens)},...$e})}),(0,l.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-3`,children:[w!==`anthropic`&&(0,l.jsx)(f,{label:`Temperature`,children:(0,l.jsx)(o,{type:`number`,min:0,max:2,step:.1,value:Je,onChange:e=>Ye(Number.isNaN(e.target.valueAsNumber)?.7:e.target.valueAsNumber)})}),(0,l.jsx)(f,{label:`Max Output Tokens`,children:(0,l.jsx)(o,{type:`number`,min:1,max:et?.maxTokens,value:Xe,onChange:e=>A(parseInt(e.target.value)||4096)})}),(0,l.jsx)(f,{label:`Top P`,children:(0,l.jsx)(o,{type:`number`,min:0,max:1,step:.1,value:Ze,onChange:e=>Qe(Number.isNaN(e.target.valueAsNumber)?1:e.target.valueAsNumber)})})]})]}),[`Governance`,`Memory Management`,`Subagent / Tool Use`].map(e=>(0,l.jsxs)(`section`,{className:`rounded-lg border border-dashed p-4`,children:[(0,l.jsxs)(`h2`,{className:`text-sm font-semibold text-muted-foreground`,children:[e,` Model`]}),(0,l.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:`Coming soon`})]},e))]}),g===`tools`&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsxs)(`section`,{className:`space-y-3 rounded-lg border p-4`,children:[(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Runtime Tools`}),(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Injected at start (pi defineTool): coding tools plus canvas tools scoped by the token binding (Access / ACL). Definitions live in the runtime — read-only here until the agent-runtime workspace lands.`})]}),$===null?(0,l.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-sm text-muted-foreground`,children:`Loading…`}):$.length===0?(0,l.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-sm text-muted-foreground`,children:`No tools resolved.`}):(0,l.jsx)(`div`,{className:`space-y-1.5`,children:$.map(e=>(0,l.jsxs)(`details`,{className:`rounded-md border px-3 py-2`,children:[(0,l.jsxs)(`summary`,{className:`cursor-pointer text-sm`,children:[(0,l.jsx)(`code`,{className:`font-mono text-xs font-medium`,children:e.name}),(0,l.jsx)(`span`,{className:`ml-2 rounded bg-muted px-1.5 py-0.5 text-[10px] uppercase text-muted-foreground`,children:e.source})]}),e.description&&(0,l.jsx)(`p`,{className:`mt-2 whitespace-pre-wrap text-xs text-muted-foreground`,children:e.description}),e.parameters!=null&&(0,l.jsx)(`pre`,{className:`mt-2 overflow-x-auto rounded bg-muted p-2 font-mono text-[11px]`,children:JSON.stringify(e.parameters,null,2)})]},e.name))}),(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:z?z.grants.map(e=>`${e.label}: ${Bt(e.binding)}`).join(`; `):`Unbound — no canvas tools are injected. Bind under Access / ACL.`})]}),(0,l.jsxs)(`section`,{className:`space-y-3 rounded-lg border p-4`,children:[(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Tools Config`}),(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`config.tools JSON, merged server-side — e.g. {"canvas": {"enabled": false}} gates the canvas tools. Saved with Save Changes.`})]}),(0,l.jsx)(`textarea`,{value:St,onChange:e=>{Ct(e.target.value);try{JSON.parse(e.target.value),Tt(null)}catch(e){Tt(e instanceof Error?e.message:`Invalid JSON`)}},className:`${p} min-h-[120px] font-mono text-xs`}),wt&&(0,l.jsxs)(`p`,{className:`text-xs text-destructive`,children:[`Invalid JSON (not saved): `,wt]})]}),(0,l.jsxs)(`section`,{className:`space-y-3 rounded-lg border p-4`,children:[(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Skills`}),(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Installed skills are saved immediately, independent of Save Changes.`})]}),tt.length===0?(0,l.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-sm text-muted-foreground`,children:`No skills installed.`}):tt.map(e=>(0,l.jsxs)(`div`,{className:`flex items-start justify-between gap-3 rounded-md border p-3`,children:[(0,l.jsxs)(`div`,{className:`min-w-0`,children:[(0,l.jsx)(`div`,{className:`truncate text-sm font-medium`,children:e.name}),(0,l.jsx)(`div`,{className:`truncate text-xs text-muted-foreground`,children:e.package?e.source:e.description||`No description`})]}),(0,l.jsxs)(`div`,{className:`flex shrink-0 gap-2`,children:[(0,l.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>{N(e.name),P(e.description||``),I(e.content||``),R(e.source||``)},children:`Edit`}),(0,l.jsx)(a,{type:`button`,variant:`destructive`,size:`sm`,disabled:at===(e.source||e.name),onClick:()=>Nt(e.source||e.name),children:at===(e.source||e.name)?`Removing…`:`Remove`})]})]},e.name)),(0,l.jsxs)(`div`,{className:`space-y-4 rounded-md border p-4`,children:[(0,l.jsx)(f,{label:`Package Source`,hint:`Use this for whole pi packages. Leave empty to save inline SKILL.md content.`,children:(0,l.jsx)(o,{value:L,onChange:e=>R(e.target.value),placeholder:`npm:@foo/pi-tools or git:github.com/badlogic/pi-doom`})}),(0,l.jsxs)(`div`,{className:`grid gap-4 md:grid-cols-2`,children:[(0,l.jsx)(f,{label:`Name`,children:(0,l.jsx)(o,{value:M,onChange:e=>N(e.target.value),placeholder:`skill-name, or read from frontmatter`,disabled:!!L.trim()})}),(0,l.jsx)(f,{label:`Description`,children:(0,l.jsx)(o,{value:nt,onChange:e=>P(e.target.value),placeholder:`What this skill helps with`,disabled:!!L.trim()})})]}),(0,l.jsx)(f,{label:`SKILL.md Content`,children:(0,l.jsx)(`textarea`,{value:F,onChange:e=>I(e.target.value),placeholder:`# Skill instructions…`,disabled:!!L.trim(),className:`${p} min-h-[160px] font-mono text-xs`})}),(0,l.jsxs)(`div`,{className:`flex gap-2`,children:[(0,l.jsx)(a,{type:`button`,disabled:rt||!L.trim()&&!F.trim(),onClick:Mt,children:rt?`Saving…`:`Install / Update Skill`}),(0,l.jsx)(a,{type:`button`,variant:`outline`,onClick:jt,children:`Clear`})]})]})]}),(0,l.jsxs)(`section`,{className:`space-y-3 rounded-lg border p-4`,children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:`MCP Servers`}),(_.config?.mcp?.servers||[]).length===0?(0,l.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-sm text-muted-foreground`,children:`No MCP servers configured.`}):(_.config?.mcp?.servers||[]).map((e,t)=>(0,l.jsxs)(`div`,{className:`rounded-md border p-3`,children:[(0,l.jsx)(`div`,{className:`text-sm font-medium`,children:e.name}),(0,l.jsxs)(`div`,{className:`font-mono text-xs text-muted-foreground`,children:[e.command,` `,(e.args||[]).join(` `)]})]},t))]})]}),g===`access`&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsxs)(`section`,{className:`space-y-3 rounded-lg border p-4`,children:[(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Canvas Access`}),(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Add named connections to workspaces, paths or contexts, with permissions for each. Every connection has its own scoped token. Overlapping grants are additive: a whole-workspace grant is not restricted by a context on that workspace.`})]}),st===_.id?z?(0,l.jsxs)(`div`,{className:`space-y-2`,children:[z.grants.map(e=>(0,l.jsxs)(`div`,{className:`space-y-2 rounded-md border p-3`,children:[(0,l.jsx)(`div`,{className:`text-sm font-medium`,children:e.label||e.id}),(0,l.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:Bt(e.binding)}),(0,l.jsxs)(`div`,{className:`text-xs text-muted-foreground`,children:[`Permissions: `,e.permissions.join(`, `)]}),(0,l.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,l.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,disabled:V,onClick:()=>Lt(e),children:`Edit`}),(0,l.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,disabled:V,onClick:()=>It(e.id),children:`Rotate Token`}),(0,l.jsx)(a,{type:`button`,variant:`destructive`,size:`sm`,disabled:V,onClick:()=>Rt(e.id),children:`Remove`})]})]},e.id)),(0,l.jsx)(a,{type:`button`,variant:`destructive`,size:`sm`,disabled:V,onClick:zt,children:`Revoke All Access`})]}):(0,l.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-sm text-muted-foreground`,children:`Unbound — this agent has no canvas access.`}):(0,l.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-sm text-muted-foreground`,children:`Loading…`}),U&&(0,l.jsxs)(`div`,{className:`space-y-2 rounded-md border border-warning/50 bg-warning/10 p-3`,children:[(0,l.jsx)(`div`,{className:`text-xs font-medium`,children:`Agent token — shown once, store it now`}),(0,l.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,l.jsx)(`code`,{className:`flex-1 truncate rounded bg-background px-2 py-1 font-mono text-xs`,children:U}),(0,l.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>navigator.clipboard?.writeText(U),children:`Copy`}),(0,l.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>W(null),children:`Dismiss`})]}),(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Managed agents receive their connections automatically. External runtimes use the CANVAS_CONNECTIONS JSON array.`})]})]}),(0,l.jsxs)(`section`,{className:`space-y-4 rounded-lg border p-4`,children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:q?`Edit Connection`:`Add Connection`}),(0,l.jsx)(f,{label:`Connection name`,hint:`Agents use this name to select the scope for each tool call.`,children:(0,l.jsx)(o,{value:G,disabled:q,onChange:e=>K(e.target.value),placeholder:`bar, baz, baf`})}),(0,l.jsx)(f,{label:`Scope`,hint:`Context bindings follow the context live; global spans all workspaces.`,children:(0,l.jsxs)(`select`,{value:Y,onChange:e=>lt(e.target.value),className:m,children:[(0,l.jsx)(`option`,{value:`context`,children:`Context (follows live)`}),(0,l.jsx)(`option`,{value:`workspace`,children:`Workspace`}),(0,l.jsx)(`option`,{value:`path`,children:`Workspace path`}),(0,l.jsx)(`option`,{value:`global`,children:`Global (all workspaces)`})]})}),Y===`context`&&(0,l.jsx)(f,{label:`Context`,children:(0,l.jsxs)(`select`,{value:Z,onChange:e=>pt(e.target.value),className:m,children:[(0,l.jsx)(`option`,{value:``,children:`Select a context…`}),yt.map(e=>(0,l.jsxs)(`option`,{value:e.id,children:[e.id,` — `,e.url]},e.id))]})}),(Y===`workspace`||Y===`path`)&&(0,l.jsx)(f,{label:`Workspace`,children:(0,l.jsxs)(`select`,{value:X,onChange:e=>ut(e.target.value),className:m,children:[(0,l.jsx)(`option`,{value:``,children:`Select a workspace…`}),_t.map(e=>(0,l.jsx)(`option`,{value:e.name||e.id,children:e.label||e.name},e.id))]})}),Y===`path`&&(0,l.jsx)(f,{label:`Base path`,hint:`The agent is clamped to this subtree.`,children:(0,l.jsx)(o,{value:dt,onChange:e=>ft(e.target.value),placeholder:`/work/projects/foo`})}),(0,l.jsx)(f,{label:`Permissions`,children:(0,l.jsxs)(`div`,{className:`flex gap-4 text-sm`,children:[(0,l.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,l.jsx)(`input`,{type:`checkbox`,checked:mt,onChange:e=>ht(e.target.checked)}),` read`]}),(0,l.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,l.jsx)(`input`,{type:`checkbox`,checked:Q,onChange:e=>gt(e.target.checked)}),` write`]})]})}),(0,l.jsx)(a,{type:`button`,disabled:V,onClick:Ft,children:V?`Working…`:q?`Save Connection`:`Add Connection`}),q&&(0,l.jsx)(a,{type:`button`,variant:`outline`,onClick:()=>{K(``),J(!1)},children:`Cancel Edit`})]})]}),g===`memory`&&(0,l.jsxs)(`section`,{className:`rounded-lg border border-dashed p-6 text-center`,children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold text-muted-foreground`,children:`Memory Engine`}),(0,l.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:`Loop-based memory management. Settings coming soon.`})]}),g===`integrations`&&(0,l.jsxs)(`section`,{className:`rounded-lg border border-dashed p-6 text-center`,children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold text-muted-foreground`,children:`Integrations`}),(0,l.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:`IMAP, chat, SQL and REST API accounts. Coming soon.`})]}),Ut&&(0,l.jsx)(a,{type:`submit`,disabled:je,children:je?`Saving…`:`Save Changes`})]})]})})}export{h as default};
|
|
1
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{_ as r,g as ee}from"./chunk-62JRHF6Z-vspAGgtK.js";import{X as i}from"./ui-CDoK3F3U.js";import{t as a}from"./button-SeUZ_Pvi.js";import{t as o}from"./input-BOtCd4HP.js";import{n as te}from"./use-toast-BlLDqSUO.js";import{Nt as ne}from"./workspace-cv6Hrfhh.js";import{t as re}from"./use-mobile-Db-vWu9Y.js";import{p as ie}from"./context-1vR30CeC.js";import{t as s}from"./color-DFEH4BfK.js";import{i as ae}from"./use-menu-DIP1zh7I.js";import{$ as oe,H as se,J as ce,K as le,Q as ue,U as de,X as fe,Z as pe,et as me,ht as he,q as ge,rt as _e,vt as ve,z as ye}from"./index-CXPA9Fj8.js";import{n as be}from"./page-header-DrDt1sQ2.js";import{n as xe,r as Se,t as Ce}from"./useAgentModels-CI7iZlUR.js";var c=e(n(),1),l=t(),we={anthropic:`claude-3-5-sonnet-20241022`,openai:`gpt-4o`,ollama:`qwen2.5-coder:latest`,"lm-studio":``,vllm:``,custom:``},u={anthropic:`https://api.anthropic.com`,openai:`https://api.openai.com/v1`,ollama:`http://localhost:11434/v1`,"lm-studio":`http://localhost:1234/v1`,vllm:`http://localhost:8000/v1`,custom:``};function d(e){return u[e]||``}function f({label:e,hint:t,children:n}){return(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`label`,{className:`text-sm font-medium`,children:e}),t&&(0,l.jsx)(`p`,{className:`mb-1 mt-0.5 text-xs text-muted-foreground`,children:t}),(0,l.jsx)(`div`,{className:t?void 0:`mt-1`,children:n})]})}var p=`w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring resize-y`,m=`w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring`;function h(){let{agentId:e,tab:t}=r(),n=ee(),{showToast:u}=te(),{selectEntity:h,goBack:Te}=ae(),Ee=re(),g=ve(t);(0,c.useEffect)(()=>{t!==g&&e&&n(`/agents/${encodeURIComponent(e)}/settings/${g}`,{replace:!0})},[t,g,e,n]);let[_,v]=(0,c.useState)(null),[De,Oe]=(0,c.useState)(!0),[ke,Ae]=(0,c.useState)(null),[je,Me]=(0,c.useState)(!1),[Ne,Pe]=(0,c.useState)(!1),[Fe,Ie]=(0,c.useState)(``),[Le,Re]=(0,c.useState)(``),[ze,Be]=(0,c.useState)(``),[Ve,y]=(0,c.useState)(s()),[b,He]=(0,c.useState)(``),[x,Ue]=(0,c.useState)(``),[S,We]=(0,c.useState)(``),[C,Ge]=(0,c.useState)(``),[w,Ke]=(0,c.useState)(`anthropic`),[T,qe]=(0,c.useState)(``),[E,D]=(0,c.useState)(``),[O,k]=(0,c.useState)(``),[Je,Ye]=(0,c.useState)(.7),[Xe,A]=(0,c.useState)(4096),[Ze,Qe]=(0,c.useState)(1),$e=Ce(w,T,E,_?.id),et=$e.models.find(e=>e.id===O),[tt,j]=(0,c.useState)([]),[M,N]=(0,c.useState)(``),[nt,P]=(0,c.useState)(``),[F,I]=(0,c.useState)(``),[L,R]=(0,c.useState)(``),[rt,it]=(0,c.useState)(!1),[at,ot]=(0,c.useState)(null),[z,B]=(0,c.useState)(null),[st,ct]=(0,c.useState)(null),[V,H]=(0,c.useState)(!1),[U,W]=(0,c.useState)(null),[G,K]=(0,c.useState)(``),[q,J]=(0,c.useState)(!1),[Y,lt]=(0,c.useState)(`context`),[X,ut]=(0,c.useState)(``),[dt,ft]=(0,c.useState)(`/`),[Z,pt]=(0,c.useState)(``),[mt,ht]=(0,c.useState)(!0),[Q,gt]=(0,c.useState)(!1),[_t,vt]=(0,c.useState)([]),[yt,bt]=(0,c.useState)([]),[$,xt]=(0,c.useState)(null),[St,Ct]=(0,c.useState)(`{}`),[wt,Tt]=(0,c.useState)(null),[Et,Dt]=(0,c.useState)(e);Et!==e&&(Dt(e),Oe(!0),v(null)),(0,c.useEffect)(()=>{if(!e)return;let t=!1;return se(e).then(async e=>{if(t)return;let n=e.config?.identity||{};v(e),h(e.id),Ie(e.name||``),Re(e.label||``),Be(e.description||``),y(e.color||s()),He(n.role||``),Ue(n.identity||``),We(n.instructions||``),Ge(e.config?.prompts?.system||``),Ke(e.llmProvider||`anthropic`),qe(e.config?.apiKey||``),D(e.config?.baseUrl||d(e.llmProvider)),k(e.model||we[e.llmProvider]||``);let r=e.config?.connectors?.[e.llmProvider];r&&(Ye(r.temperature??.7),A(r.maxTokens??4096),Qe(r.topP??1)),Ct(JSON.stringify(e.config?.tools??{},null,2)),Tt(null),Ae(null);try{j(await ce(e.id))}catch{j([])}}).catch(e=>{t||Ae(e instanceof Error?e.message:`Failed to load agent`)}).finally(()=>{t||Oe(!1)}),()=>{t=!0}},[e,h]),(0,c.useEffect)(()=>{if(g!==`access`&&g!==`tools`||!_?.id)return;let e=_.id,t=!1;return Promise.all([de(_.id).catch(()=>null),ne().catch(()=>[]),ie().catch(()=>[]),le(_.id).catch(()=>null)]).then(([n,r,ee,i])=>{t||(B(n),vt(r),bt(ee),xt(i?i.tools:[]),ct(e))}),()=>{t=!0}},[g,_?.id]);let Ot=()=>{let e=Se(b,x,S),t;try{let e=JSON.parse(St);e&&typeof e==`object`&&!Array.isArray(e)&&(t=e)}catch{}return{...t===void 0?{}:{tools:t},name:Fe.trim(),label:Le.trim(),description:ze.trim()||void 0,color:Ve,llmProvider:w,model:O,apiKey:T.trim()||(w===_?.llmProvider?void 0:``),baseUrl:E||void 0,config:{type:w,model:O,identity:{role:b.trim()||void 0,identity:x.trim()||void 0,instructions:S.trim()||void 0},prompts:C.trim()||e?{system:C.trim()||e}:void 0,connectors:{[w]:{...w===`anthropic`?{}:{temperature:Je},maxTokens:Xe,topP:Ze}}}}},kt=async e=>{if(e.preventDefault(),_){Me(!0);try{let e=await _e(_.id,Ot());v(e),window.dispatchEvent(new CustomEvent(`agents:refresh`)),u({title:`Saved`,description:`Agent updated`}),e.name&&e.name!==_.name&&n(`/agents/${encodeURIComponent(e.name)}/settings/${g}`,{replace:!0})}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Save failed`,variant:`destructive`})}finally{Me(!1)}}},At=async()=>{if(_&&window.confirm(`Delete agent "${_.label||_.name}"? This cannot be undone.`)){Pe(!0);try{await ye(_.id),window.dispatchEvent(new CustomEvent(`agents:refresh`)),u({title:`Deleted`,description:`Agent removed`}),n(`/agents`)}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Delete failed`,variant:`destructive`})}finally{Pe(!1)}}},jt=()=>{N(``),P(``),I(``),R(``)},Mt=async()=>{if(!(!_||!L.trim()&&!F.trim())){it(!0);try{let e=await ge(_.id,L.trim()?{source:L.trim()}:{name:M,description:nt,content:F});j(e),jt(),window.dispatchEvent(new CustomEvent(`agents:refresh`)),u({title:`Installed`,description:`Skill saved`})}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Skill install failed`,variant:`destructive`})}finally{it(!1)}}},Nt=async e=>{if(_){ot(e);try{let t=await fe(_.id,e);j(t),(M===e||L===e)&&jt(),window.dispatchEvent(new CustomEvent(`agents:refresh`)),u({title:`Removed`,description:`Skill "${e}" removed`})}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Skill remove failed`,variant:`destructive`})}finally{ot(null)}}},Pt=()=>Y===`global`?{type:`global`}:Y===`context`?Z?{type:`context`,context:Z}:null:X?Y===`path`?{type:`path`,workspace:X,path:dt.trim()||`/`}:{type:`workspace`,workspace:X}:null,Ft=async()=>{if(!_||V)return;let e=Pt(),t=[];if(mt&&t.push(`read`),Q&&t.push(`write`),!e||!/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/.test(G.trim())||t.length===0||!q&&z?.grants.some(e=>e.id===G.trim())){u({title:`Invalid binding`,description:`Choose a unique connection name (letters, numbers, hyphens or underscores), scope and permissions`,variant:`destructive`});return}if(!(e.type===`global`&&!window.confirm(`Global scope lets this agent ${Q?`read and write`:`read`} ALL your workspaces. Continue?`))){H(!0);try{let n=await me(_.id,G.trim(),{label:z?.grants.find(e=>e.id===G.trim())?.label||G.trim(),binding:e,permissions:t});B(n.access),W(n.tokens[0]?.token??null),K(``),J(!1),u({title:`Connection saved`,description:`Other connections and their tokens are unchanged`})}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Bind failed`,variant:`destructive`})}finally{H(!1)}}},It=async e=>{if(!(!_||V)){H(!0);try{let t=await oe(_.id,e);B(t.access),W(t.tokens[0]?.token??null),u({title:`Rotated`,description:`New token minted — the previous one no longer works`})}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Rotate failed`,variant:`destructive`})}finally{H(!1)}}},Lt=e=>{K(e.id),J(!0),lt(e.binding.type),ut(e.binding.workspace||``),ft(e.binding.path||`/`),pt(e.binding.context||``),ht(e.permissions.includes(`read`)),gt(e.permissions.includes(`write`))},Rt=async e=>{if(!(!_||V)){H(!0);try{let t=await ue(_.id,e);B(t.access),W(null),G===e&&(K(``),J(!1))}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Revoke failed`,variant:`destructive`})}finally{H(!1)}}},zt=async()=>{if(!(!_||V)&&window.confirm(`Revoke this agent's canvas access? All its connection tokens stop working immediately.`)){H(!0);try{await pe(_.id),B(null),W(null),u({title:`Revoked`,description:`Agent access removed`})}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Revoke failed`,variant:`destructive`})}finally{H(!1)}}},Bt=e=>{if(e.type===`global`)return`Global — all workspaces`;if(e.type===`context`){let t=yt.find(t=>t.id===e.context);return`Context ${t?`${t.id} (${t.url})`:e.context} — follows the context live`}let t=e.workspaceName||e.workspace;return e.type===`path`?`Workspace ${t}, path ${e.path||`/`}`:`Workspace ${t} (whole tree)`};if(De)return(0,l.jsx)(`div`,{className:`p-6 text-sm text-muted-foreground`,children:`Loading...`});if(!_||ke)return(0,l.jsx)(`div`,{className:`p-6 text-sm text-destructive`,children:ke||`Agent not found`});let Vt=he.find(e=>e.id===g),Ht=encodeURIComponent(_.name||_.id),Ut=g===`identity`||g===`provider`||g===`models`||g===`tools`;return(0,l.jsx)(`div`,{className:`h-full min-h-0 overflow-y-auto`,children:(0,l.jsxs)(`div`,{className:`mx-auto max-w-5xl p-6 pb-12 max-md:px-4 max-md:pb-rail-stack`,children:[(0,l.jsx)(be,{compact:!0,className:`mb-6 border-b pb-4`,title:`${Vt.label} - ${_.label||_.name}`,description:Vt.description,backTo:`/agents/${Ht}`,onBack:Ee?Te:void 0}),(0,l.jsxs)(`form`,{onSubmit:kt,className:`space-y-6`,children:[g===`identity`&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsxs)(`section`,{className:`space-y-4 rounded-lg border p-4`,children:[(0,l.jsxs)(`div`,{className:`grid gap-4 md:grid-cols-2`,children:[(0,l.jsx)(f,{label:`Name`,hint:`ID: ${_.id}`,children:(0,l.jsx)(o,{value:Fe,onChange:e=>Ie(e.target.value),placeholder:`lucy`})}),(0,l.jsx)(f,{label:`Label`,children:(0,l.jsx)(o,{value:Le,onChange:e=>Re(e.target.value),placeholder:`Display name`})})]}),(0,l.jsx)(f,{label:`Description`,children:(0,l.jsx)(o,{value:ze,onChange:e=>Be(e.target.value),placeholder:`Short description`})}),(0,l.jsx)(f,{label:`Color`,children:(0,l.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,l.jsx)(o,{type:`color`,value:Ve,onChange:e=>y(e.target.value),className:`h-10 w-16 p-1`}),(0,l.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>y(s()),children:`Randomize`})]})})]}),(0,l.jsxs)(`section`,{className:`space-y-4 rounded-lg border p-4`,children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Persona`}),(0,l.jsx)(f,{label:`Role`,children:(0,l.jsx)(o,{value:b,onChange:e=>He(e.target.value),placeholder:`e.g. Software Engineer`})}),(0,l.jsx)(f,{label:`Identity`,children:(0,l.jsx)(`textarea`,{value:x,onChange:e=>Ue(e.target.value),placeholder:`Who this agent is…`,className:`${p} min-h-[80px]`})}),(0,l.jsx)(f,{label:`Instructions`,children:(0,l.jsx)(`textarea`,{value:S,onChange:e=>We(e.target.value),placeholder:`Behavioral instructions…`,className:`${p} min-h-[80px]`})}),(0,l.jsx)(f,{label:`System Prompt`,hint:`Compiled from Role + Identity + Instructions. Override manually.`,children:(0,l.jsx)(`textarea`,{value:C,onChange:e=>Ge(e.target.value),placeholder:`System prompt sent to the LLM…`,className:`${p} min-h-[140px] font-mono text-xs`})})]}),(0,l.jsxs)(`section`,{className:`rounded-lg border border-destructive/30 p-4`,children:[(0,l.jsx)(`h2`,{className:`mb-3 text-sm font-semibold text-destructive`,children:`Danger Zone`}),(0,l.jsxs)(a,{type:`button`,variant:`destructive`,disabled:Ne,onClick:At,children:[(0,l.jsx)(i,{className:`mr-2 h-4 w-4`}),Ne?`Deleting...`:`Delete Agent`]})]})]}),g===`provider`&&(0,l.jsxs)(`section`,{className:`space-y-4 rounded-lg border p-4`,children:[(0,l.jsx)(f,{label:`Provider`,children:(0,l.jsxs)(`select`,{value:w,onChange:e=>{let t=e.target.value;Ke(t),qe(``),k(we[t]||``),D(d(t))},className:`w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring`,children:[(0,l.jsx)(`option`,{value:`anthropic`,children:`Anthropic Claude`}),(0,l.jsx)(`option`,{value:`openai`,children:`OpenAI GPT`}),(0,l.jsx)(`option`,{value:`ollama`,children:`Ollama (Local)`}),(0,l.jsx)(`option`,{value:`lm-studio`,children:`LM Studio (Local)`}),(0,l.jsx)(`option`,{value:`vllm`,children:`vLLM (Local)`}),(0,l.jsx)(`option`,{value:`custom`,children:`Custom`})]})}),(0,l.jsx)(f,{label:`API Key`,hint:[`ollama`,`lm-studio`,`vllm`].includes(w)?`Any value works for local providers.`:void 0,children:(0,l.jsx)(o,{type:`password`,value:T,onChange:e=>qe(e.target.value),placeholder:w===`ollama`?`ollama`:w===`lm-studio`?`lm-studio`:`sk-…`})}),(0,l.jsx)(f,{label:`Host / Base URL`,children:(0,l.jsx)(o,{value:E,onChange:e=>D(e.target.value),placeholder:d(w)||`https://api.example.com`})})]}),g===`models`&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsxs)(`section`,{className:`space-y-4 rounded-lg border p-4`,children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Main Model`}),(0,l.jsx)(f,{label:`Model`,children:(0,l.jsx)(xe,{value:O,onChange:(e,t)=>{k(e),t?.maxTokens&&A(t.maxTokens)},...$e})}),(0,l.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-3`,children:[w!==`anthropic`&&(0,l.jsx)(f,{label:`Temperature`,children:(0,l.jsx)(o,{type:`number`,min:0,max:2,step:.1,value:Je,onChange:e=>Ye(Number.isNaN(e.target.valueAsNumber)?.7:e.target.valueAsNumber)})}),(0,l.jsx)(f,{label:`Max Output Tokens`,children:(0,l.jsx)(o,{type:`number`,min:1,max:et?.maxTokens,value:Xe,onChange:e=>A(parseInt(e.target.value)||4096)})}),(0,l.jsx)(f,{label:`Top P`,children:(0,l.jsx)(o,{type:`number`,min:0,max:1,step:.1,value:Ze,onChange:e=>Qe(Number.isNaN(e.target.valueAsNumber)?1:e.target.valueAsNumber)})})]})]}),[`Governance`,`Memory Management`,`Subagent / Tool Use`].map(e=>(0,l.jsxs)(`section`,{className:`rounded-lg border border-dashed p-4`,children:[(0,l.jsxs)(`h2`,{className:`text-sm font-semibold text-muted-foreground`,children:[e,` Model`]}),(0,l.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:`Coming soon`})]},e))]}),g===`tools`&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsxs)(`section`,{className:`space-y-3 rounded-lg border p-4`,children:[(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Runtime Tools`}),(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Injected at start (pi defineTool): coding tools plus canvas tools scoped by the token binding (Access / ACL). Definitions live in the runtime — read-only here until the agent-runtime workspace lands.`})]}),$===null?(0,l.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-sm text-muted-foreground`,children:`Loading…`}):$.length===0?(0,l.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-sm text-muted-foreground`,children:`No tools resolved.`}):(0,l.jsx)(`div`,{className:`space-y-1.5`,children:$.map(e=>(0,l.jsxs)(`details`,{className:`rounded-md border px-3 py-2`,children:[(0,l.jsxs)(`summary`,{className:`cursor-pointer text-sm`,children:[(0,l.jsx)(`code`,{className:`font-mono text-xs font-medium`,children:e.name}),(0,l.jsx)(`span`,{className:`ml-2 rounded bg-muted px-1.5 py-0.5 text-[10px] uppercase text-muted-foreground`,children:e.source})]}),e.description&&(0,l.jsx)(`p`,{className:`mt-2 whitespace-pre-wrap text-xs text-muted-foreground`,children:e.description}),e.parameters!=null&&(0,l.jsx)(`pre`,{className:`mt-2 overflow-x-auto rounded bg-muted p-2 font-mono text-[11px]`,children:JSON.stringify(e.parameters,null,2)})]},e.name))}),(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:z?z.grants.map(e=>`${e.label}: ${Bt(e.binding)}`).join(`; `):`Unbound — no canvas tools are injected. Bind under Access / ACL.`})]}),(0,l.jsxs)(`section`,{className:`space-y-3 rounded-lg border p-4`,children:[(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Tools Config`}),(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`config.tools JSON, merged server-side — e.g. {"canvas": {"enabled": false}} gates the canvas tools. Saved with Save Changes.`})]}),(0,l.jsx)(`textarea`,{value:St,onChange:e=>{Ct(e.target.value);try{JSON.parse(e.target.value),Tt(null)}catch(e){Tt(e instanceof Error?e.message:`Invalid JSON`)}},className:`${p} min-h-[120px] font-mono text-xs`}),wt&&(0,l.jsxs)(`p`,{className:`text-xs text-destructive`,children:[`Invalid JSON (not saved): `,wt]})]}),(0,l.jsxs)(`section`,{className:`space-y-3 rounded-lg border p-4`,children:[(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Skills`}),(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Installed skills are saved immediately, independent of Save Changes.`})]}),tt.length===0?(0,l.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-sm text-muted-foreground`,children:`No skills installed.`}):tt.map(e=>(0,l.jsxs)(`div`,{className:`flex items-start justify-between gap-3 rounded-md border p-3`,children:[(0,l.jsxs)(`div`,{className:`min-w-0`,children:[(0,l.jsx)(`div`,{className:`truncate text-sm font-medium`,children:e.name}),(0,l.jsx)(`div`,{className:`truncate text-xs text-muted-foreground`,children:e.package?e.source:e.description||`No description`})]}),(0,l.jsxs)(`div`,{className:`flex shrink-0 gap-2`,children:[(0,l.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>{N(e.name),P(e.description||``),I(e.content||``),R(e.source||``)},children:`Edit`}),(0,l.jsx)(a,{type:`button`,variant:`destructive`,size:`sm`,disabled:at===(e.source||e.name),onClick:()=>Nt(e.source||e.name),children:at===(e.source||e.name)?`Removing…`:`Remove`})]})]},e.name)),(0,l.jsxs)(`div`,{className:`space-y-4 rounded-md border p-4`,children:[(0,l.jsx)(f,{label:`Package Source`,hint:`Use this for whole pi packages. Leave empty to save inline SKILL.md content.`,children:(0,l.jsx)(o,{value:L,onChange:e=>R(e.target.value),placeholder:`npm:@foo/pi-tools or git:github.com/badlogic/pi-doom`})}),(0,l.jsxs)(`div`,{className:`grid gap-4 md:grid-cols-2`,children:[(0,l.jsx)(f,{label:`Name`,children:(0,l.jsx)(o,{value:M,onChange:e=>N(e.target.value),placeholder:`skill-name, or read from frontmatter`,disabled:!!L.trim()})}),(0,l.jsx)(f,{label:`Description`,children:(0,l.jsx)(o,{value:nt,onChange:e=>P(e.target.value),placeholder:`What this skill helps with`,disabled:!!L.trim()})})]}),(0,l.jsx)(f,{label:`SKILL.md Content`,children:(0,l.jsx)(`textarea`,{value:F,onChange:e=>I(e.target.value),placeholder:`# Skill instructions…`,disabled:!!L.trim(),className:`${p} min-h-[160px] font-mono text-xs`})}),(0,l.jsxs)(`div`,{className:`flex gap-2`,children:[(0,l.jsx)(a,{type:`button`,disabled:rt||!L.trim()&&!F.trim(),onClick:Mt,children:rt?`Saving…`:`Install / Update Skill`}),(0,l.jsx)(a,{type:`button`,variant:`outline`,onClick:jt,children:`Clear`})]})]})]}),(0,l.jsxs)(`section`,{className:`space-y-3 rounded-lg border p-4`,children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:`MCP Servers`}),(_.config?.mcp?.servers||[]).length===0?(0,l.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-sm text-muted-foreground`,children:`No MCP servers configured.`}):(_.config?.mcp?.servers||[]).map((e,t)=>(0,l.jsxs)(`div`,{className:`rounded-md border p-3`,children:[(0,l.jsx)(`div`,{className:`text-sm font-medium`,children:e.name}),(0,l.jsxs)(`div`,{className:`font-mono text-xs text-muted-foreground`,children:[e.command,` `,(e.args||[]).join(` `)]})]},t))]})]}),g===`access`&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsxs)(`section`,{className:`space-y-3 rounded-lg border p-4`,children:[(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:`Canvas Access`}),(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Add named connections to workspaces, paths or contexts, with permissions for each. Every connection has its own scoped token. Overlapping grants are additive: a whole-workspace grant is not restricted by a context on that workspace.`})]}),st===_.id?z?(0,l.jsxs)(`div`,{className:`space-y-2`,children:[z.grants.map(e=>(0,l.jsxs)(`div`,{className:`space-y-2 rounded-md border p-3`,children:[(0,l.jsx)(`div`,{className:`text-sm font-medium`,children:e.label||e.id}),(0,l.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:Bt(e.binding)}),(0,l.jsxs)(`div`,{className:`text-xs text-muted-foreground`,children:[`Permissions: `,e.permissions.join(`, `)]}),(0,l.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,l.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,disabled:V,onClick:()=>Lt(e),children:`Edit`}),(0,l.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,disabled:V,onClick:()=>It(e.id),children:`Rotate Token`}),(0,l.jsx)(a,{type:`button`,variant:`destructive`,size:`sm`,disabled:V,onClick:()=>Rt(e.id),children:`Remove`})]})]},e.id)),(0,l.jsx)(a,{type:`button`,variant:`destructive`,size:`sm`,disabled:V,onClick:zt,children:`Revoke All Access`})]}):(0,l.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-sm text-muted-foreground`,children:`Unbound — this agent has no canvas access.`}):(0,l.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-sm text-muted-foreground`,children:`Loading…`}),U&&(0,l.jsxs)(`div`,{className:`space-y-2 rounded-md border border-warning/50 bg-warning/10 p-3`,children:[(0,l.jsx)(`div`,{className:`text-xs font-medium`,children:`Agent token — shown once, store it now`}),(0,l.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,l.jsx)(`code`,{className:`flex-1 truncate rounded bg-background px-2 py-1 font-mono text-xs`,children:U}),(0,l.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>navigator.clipboard?.writeText(U),children:`Copy`}),(0,l.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>W(null),children:`Dismiss`})]}),(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Managed agents receive their connections automatically. External runtimes use the CANVAS_CONNECTIONS JSON array.`})]})]}),(0,l.jsxs)(`section`,{className:`space-y-4 rounded-lg border p-4`,children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold`,children:q?`Edit Connection`:`Add Connection`}),(0,l.jsx)(f,{label:`Connection name`,hint:`Agents use this name to select the scope for each tool call.`,children:(0,l.jsx)(o,{value:G,disabled:q,onChange:e=>K(e.target.value),placeholder:`bar, baz, baf`})}),(0,l.jsx)(f,{label:`Scope`,hint:`Context bindings follow the context live; global spans all workspaces.`,children:(0,l.jsxs)(`select`,{value:Y,onChange:e=>lt(e.target.value),className:m,children:[(0,l.jsx)(`option`,{value:`context`,children:`Context (follows live)`}),(0,l.jsx)(`option`,{value:`workspace`,children:`Workspace`}),(0,l.jsx)(`option`,{value:`path`,children:`Workspace path`}),(0,l.jsx)(`option`,{value:`global`,children:`Global (all workspaces)`})]})}),Y===`context`&&(0,l.jsx)(f,{label:`Context`,children:(0,l.jsxs)(`select`,{value:Z,onChange:e=>pt(e.target.value),className:m,children:[(0,l.jsx)(`option`,{value:``,children:`Select a context…`}),yt.map(e=>(0,l.jsxs)(`option`,{value:e.id,children:[e.id,` — `,e.url]},e.id))]})}),(Y===`workspace`||Y===`path`)&&(0,l.jsx)(f,{label:`Workspace`,children:(0,l.jsxs)(`select`,{value:X,onChange:e=>ut(e.target.value),className:m,children:[(0,l.jsx)(`option`,{value:``,children:`Select a workspace…`}),_t.map(e=>(0,l.jsx)(`option`,{value:e.name||e.id,children:e.label||e.name},e.id))]})}),Y===`path`&&(0,l.jsx)(f,{label:`Base path`,hint:`The agent is clamped to this subtree.`,children:(0,l.jsx)(o,{value:dt,onChange:e=>ft(e.target.value),placeholder:`/work/projects/foo`})}),(0,l.jsx)(f,{label:`Permissions`,children:(0,l.jsxs)(`div`,{className:`flex gap-4 text-sm`,children:[(0,l.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,l.jsx)(`input`,{type:`checkbox`,checked:mt,onChange:e=>ht(e.target.checked)}),` read`]}),(0,l.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,l.jsx)(`input`,{type:`checkbox`,checked:Q,onChange:e=>gt(e.target.checked)}),` write`]})]})}),(0,l.jsx)(a,{type:`button`,disabled:V,onClick:Ft,children:V?`Working…`:q?`Save Connection`:`Add Connection`}),q&&(0,l.jsx)(a,{type:`button`,variant:`outline`,onClick:()=>{K(``),J(!1)},children:`Cancel Edit`})]})]}),g===`memory`&&(0,l.jsxs)(`section`,{className:`rounded-lg border border-dashed p-6 text-center`,children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold text-muted-foreground`,children:`Memory Engine`}),(0,l.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:`Loop-based memory management. Settings coming soon.`})]}),g===`integrations`&&(0,l.jsxs)(`section`,{className:`rounded-lg border border-dashed p-6 text-center`,children:[(0,l.jsx)(`h2`,{className:`text-sm font-semibold text-muted-foreground`,children:`Integrations`}),(0,l.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:`IMAP, chat, SQL and REST API accounts. Coming soon.`})]}),Ut&&(0,l.jsx)(a,{type:`submit`,disabled:je,children:je?`Saving…`:`Save Changes`})]})]})})}export{h as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{g as r,v as i}from"./chunk-62JRHF6Z-vspAGgtK.js";import{n as a,t as o}from"./HomeFab-
|
|
1
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{g as r,v as i}from"./chunk-62JRHF6Z-vspAGgtK.js";import{n as a,t as o}from"./HomeFab-DRmbW2Uu.js";var s=e(n(),1),c=`share-target-inbox`,l=t(),u={"too-large":`Android shares are limited to 100 MiB in total for temporary device storage. Nothing was uploaded. Use Add File to upload larger files directly.`,"stash-failed":`Canvas couldn't hold on to the shared file — device storage may be full. Try again, or upload it from the app.`,"empty-share":`Canvas received no files or text from the sharing app. Try again, or use Add File to select the photo directly.`,"empty-file":`The sharing app delivered an empty file. Try again, or use Add File to select the original directly.`,expired:`Nothing shared, or the share expired.`};async function d(e){let t=await caches.open(c),n=null,r=Date.now()+3e5;for(;Date.now()<r;){let r=await t.match(`/share-target-inbox/${e}/meta`);if(!r)return null;if(n=await r.json(),n?.status===`error`)throw Error(n.error||`stash-failed`);if(n?.status!==`receiving`)break;await new Promise(e=>setTimeout(e,300))}if(!n||n.status===`receiving`)throw Error(`stash-failed`);let i=[];for(let r=0;r<n.fileNames.length;r++){let a=await t.match(`/share-target-inbox/${e}/file-${r}`);if(!a)throw Error(`stash-failed`);let o=await a.blob();i.push(new File([o],n.fileNames[r],{type:o.type}))}let o=i.length?await a(i):null;if(await Promise.all(n.fileNames.map((n,r)=>t.delete(`/share-target-inbox/${e}/file-${r}`))),await t.delete(`/share-target-inbox/${e}/meta`),o)return{kind:o.kind,data:{files:o.files}};if(![n.title,n.text,n.url].some(e=>e.trim()))throw Error(`empty-share`);let s=n.text.trim(),l=n.url||(m(s)?s:``);return l?{kind:`link`,data:{url:l,title:n.title}}:{kind:`note`,data:{title:n.title,content:n.text}}}var f=new Map;function p(e){let t=f.get(e);return t||(t=d(e),f.set(e,t),t.finally(()=>setTimeout(()=>f.delete(e),6e4)).catch(()=>{})),t}function m(e){if(!e||/\s/.test(e))return!1;try{let t=new URL(e);return t.protocol===`http:`||t.protocol===`https:`}catch{return!1}}function h(){let[e]=i(),t=r(),[n,a]=(0,s.useState)(null),[c,d]=(0,s.useState)(null);(0,s.useEffect)(()=>{let t=!1;async function n(){let n=e.get(`error`);if(n){d(n);return}let r=e.get(`token`),i=r?await p(r):null;t||(i?a(i):d(`expired`))}return n().catch(e=>{t||d(e instanceof Error?e.message:`stash-failed`)}),()=>{t=!0}},[e]);let f=()=>t(`/home`,{replace:!0});return c?(0,l.jsxs)(`div`,{className:`flex h-full flex-col items-center justify-center gap-3 px-6 text-center`,children:[(0,l.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:u[c]??u.expired}),(0,l.jsx)(`button`,{type:`button`,onClick:()=>t(`/apps/add/file`,{replace:!0}),className:`text-sm font-medium text-primary underline underline-offset-4`,children:`Add File`}),(0,l.jsx)(`button`,{type:`button`,onClick:f,className:`text-sm font-medium text-primary underline underline-offset-4`,children:`Go to Canvas`})]}):n?(0,l.jsx)(o,{initialKind:n.kind,initialData:n.data,onInitialCardClose:f}):(0,l.jsx)(`div`,{className:`flex h-full items-center justify-center text-sm text-muted-foreground`,children:`Receiving shared content on this device… No upload has started.`})}export{h as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{h as r}from"./chunk-62JRHF6Z-vspAGgtK.js";import{t as i}from"./button-SeUZ_Pvi.js";import{t as a}from"./input-BOtCd4HP.js";import{t as o}from"./api-CA6WiiYM.js";import{n as s}from"./use-toast-BlLDqSUO.js";import{At as c}from"./index-
|
|
1
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{h as r}from"./chunk-62JRHF6Z-vspAGgtK.js";import{t as i}from"./button-SeUZ_Pvi.js";import{t as a}from"./input-BOtCd4HP.js";import{t as o}from"./api-CA6WiiYM.js";import{n as s}from"./use-toast-BlLDqSUO.js";import{At as c}from"./index-CXPA9Fj8.js";import{n as l}from"./page-header-DrDt1sQ2.js";import{t as u}from"./use-settings-back-DGmLAD63.js";var d=e(n(),1),f=t();function p(){let e=r(),{showToast:t}=s(),n=new URLSearchParams(e.search),p=e=>{try{let t=new URL(e);return t.pathname.includes(`/rest/v2/workspaces/`)&&!t.pathname.includes(`/rest/v2/pub/`)?t.pathname=t.pathname.replace(`/rest/v2/workspaces/`,`/rest/v2/pub/workspaces/`):t.pathname.includes(`/rest/v2/contexts/`)&&!t.pathname.includes(`/rest/v2/pub/`)&&(t.pathname=t.pathname.replace(`/rest/v2/contexts/`,`/rest/v2/pub/contexts/`)),t.toString()}catch{return e}},m=p(n.get(`url`)||``),h=sessionStorage.getItem(`sharedToken:last`)||``,[g,_]=(0,d.useState)(m),[v,y]=(0,d.useState)(h),[b,x]=(0,d.useState)(null),[S,C]=(0,d.useState)([]),[w,T]=(0,d.useState)(!1),E=(0,d.useMemo)(()=>{try{let e=new URL(g);return e.pathname.includes(`/pub/workspaces/`)?`workspace`:e.pathname.includes(`/pub/contexts/`)?`context`:`unknown`}catch{return`unknown`}},[g]),D=()=>({Authorization:`Bearer ${v.trim()}`}),O=async()=>{if(!(!g||!v)){T(!0);try{let e=p(g),t=await o.get(e,{skipAuth:!0,headers:D()});x(t);let n=await o.get(`${e}/documents`,{skipAuth:!0,headers:D()}),r=Array.isArray(n)?n:Array.isArray(n?.data)?n.data:[];C(Array.isArray(r)?r:[])}catch(e){let n=g.includes(`/rest/v2/workspaces/`)?`Ensure the URL uses /rest/v2/pub/workspaces/<workspace-id> and the token matches that workspace.`:g.includes(`/rest/v2/contexts/`)?`Ensure the URL uses /rest/v2/pub/contexts/<context-id>.`:void 0;t({title:`Error`,description:`${e instanceof Error?e.message:`Failed to load shared resource`}${n?`: ${n}`:``}`,variant:`destructive`}),x(null),C([])}finally{T(!1)}}},k=(0,d.useRef)(O);return(0,d.useEffect)(()=>{k.current()},[]),(0,f.jsxs)(`div`,{className:`space-y-4`,children:[(0,f.jsx)(l,{onBack:u(),title:`Shared Resource Viewer`,description:`Open a resource someone shared with you.`}),(0,f.jsxs)(`div`,{className:`grid gap-2 md:grid-cols-3`,children:[(0,f.jsx)(a,{value:g,onChange:e=>_(e.target.value),placeholder:`Full pub URL`}),(0,f.jsx)(a,{value:v,onChange:e=>y(e.target.value),placeholder:`Access token (canvas-...)`}),(0,f.jsx)(i,{onClick:O,disabled:w||!g||!v,children:`Load`})]}),(0,f.jsxs)(`div`,{className:`text-sm text-muted-foreground`,children:[`Type: `,E]}),w?(0,f.jsx)(`div`,{className:`text-center py-8 text-muted-foreground`,children:`Loading...`}):(0,f.jsxs)(`div`,{className:`grid gap-4 md:grid-cols-2`,children:[(0,f.jsxs)(`div`,{className:`border rounded p-3`,children:[(0,f.jsx)(`h2`,{className:`font-semibold mb-2`,children:`Metadata`}),(0,f.jsx)(`pre`,{className:`text-xs overflow-auto max-h-80`,children:JSON.stringify(b,null,2)})]}),(0,f.jsxs)(`div`,{className:`border rounded p-3`,children:[(0,f.jsxs)(`h2`,{className:`font-semibold mb-2`,children:[`Documents (`,S.length,`)`]}),S.length===0?(0,f.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:`No documents`}):(0,f.jsx)(`ul`,{className:`space-y-2 text-sm`,children:S.slice(0,100).map((e,t)=>(0,f.jsxs)(`li`,{className:`border rounded p-2`,children:[(0,f.jsx)(`div`,{className:`font-mono text-xs`,children:e.id}),(0,f.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:e.schema})]},t))})]})]}),(0,f.jsx)(c,{className:`mt-8`})]})}export{p as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{X as r,vn as i}from"./ui-CDoK3F3U.js";import{t as a}from"./LinkToCard-
|
|
1
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{X as r,vn as i}from"./ui-CDoK3F3U.js";import{t as a}from"./LinkToCard-DGpvNE_V.js";import{g as o,zt as s}from"./workspace-cv6Hrfhh.js";import{n as c}from"./relation-events-CKio19hE.js";import{t as l}from"./useToastHelpers-CRrpIIdY.js";import{n as u,t as d}from"./LinkToSidePanel-eCy3nW4R.js";var f=e(n(),1),p=t();function m({value:e,onChange:t,onBlur:n,placeholder:r,innerRef:i}){let a=(0,f.useRef)(null),o=(0,f.useCallback)(()=>{let e=a.current;e&&(e.style.height=`auto`,e.style.height=`${e.scrollHeight}px`)},[]);return(0,f.useEffect)(()=>{o()},[e,o]),(0,p.jsx)(`textarea`,{ref:e=>{a.current=e,i?.(e)},value:e,onChange:e=>t(e.target.value),onBlur:n,placeholder:r,rows:1,spellCheck:!1,className:`w-full resize-none overflow-hidden border-0 bg-transparent p-0 text-sm leading-relaxed text-foreground outline-none placeholder:text-muted-foreground/60`})}function h({onLinkTo:e,onDelete:t}){return(0,p.jsxs)(`span`,{className:`reveal-on-hover flex items-center gap-0.5`,children:[(0,p.jsx)(`button`,{type:`button`,onClick:e,className:`rounded p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground`,"aria-label":`Link to…`,title:`Link to…`,children:(0,p.jsx)(i,{className:`h-3.5 w-3.5`})}),(0,p.jsx)(`button`,{type:`button`,onClick:t,className:`rounded p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-destructive`,"aria-label":`Delete`,title:`Delete (moves to trash)`,children:(0,p.jsx)(r,{className:`h-3.5 w-3.5`})})]})}function g({documentId:e,workspaceName:t,onClose:n}){let{showSuccessToast:r,showErrorToast:i}=l(),[m,h]=(0,f.useState)(!1);return(0,p.jsx)(u,{onClose:n,children:(0,p.jsx)(a,{onClose:n,onConfirm:async(t,a)=>{if(t.length){h(!0);try{for(let n of t)await s(a.workspaceName,n,[e],a.treeName,a.treeType);r(`Linked to ${t.length} path${t.length>1?`s`:``}`),n()}catch(e){i(e instanceof Error?e.message:`Failed to link document`),h(!1)}}},documentCount:1,saving:m,sizeClassName:d,tabs:t?[`context`,`directory`,`relations`]:[`context`,`directory`],relationWorkspaceName:t,relationExcludeIds:new Set([e]),onConfirmRelation:async({predicate:a,direction:s,targetIds:l})=>{if(!(!t||!l.length)){h(!0);try{await o(t,e,a,l,s),r(`Related to ${l.length} document${l.length===1?``:`s`}`),c(),n()}catch(e){i(e instanceof Error?e.message:`Failed to create relation`),h(!1)}}}})})}export{h as n,g as r,m as t};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/SketchEditor-
|
|
2
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{u as t}from"./code-editor-BOIngd5F.js";import{t as n}from"./preload-helper-Czpn1I53.js";var r=e(t(),1);window.EXCALIDRAW_ASSET_PATH=`/excalidraw/`;var i=(0,r.lazy)(()=>n(()=>import(`./SketchEditor-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/SketchEditor-DxIN-6wI.js","assets/rolldown-runtime-C0FnF6B9.js","assets/code-editor-BOIngd5F.js","assets/react-BHzhHVTZ.js","assets/preload-helper-Czpn1I53.js","assets/ui-CDoK3F3U.js","assets/utils-BxVxyehK.js","assets/button-SeUZ_Pvi.js","assets/utils-2pl1SbIp.js","assets/input-BOtCd4HP.js","assets/workspace-cv6Hrfhh.js","assets/api-CA6WiiYM.js","assets/alert-dialog-CFeuDt0T.js","assets/useAddTarget-BEgKjqGj.js","assets/use-toolbox-Ck_cLGgf.js","assets/context-1vR30CeC.js","assets/useToastHelpers-CRrpIIdY.js","assets/use-toast-BlLDqSUO.js","assets/blobs-WiXP9QRi.js","assets/sha256-65KIjGvZ.js","assets/chunk-K2UTITRG-BvHe9UPk.js","assets/chunk-SRAX5OIU-Dhm3gOdh.js","assets/chunk-6U3AYISY-C6-Mtja1.js","assets/chunk-Z3N5DIM6-D9TMVU7m.js","assets/EditorOverlay-D5t3xg4w.js","assets/SketchEditor-DtRVLazd.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{u as t}from"./code-editor-BOIngd5F.js";import{t as n}from"./preload-helper-Czpn1I53.js";var r=e(t(),1);window.EXCALIDRAW_ASSET_PATH=`/excalidraw/`;var i=(0,r.lazy)(()=>n(()=>import(`./SketchEditor-DxIN-6wI.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25])));export{i as t};
|