UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

559 lines • 72.8 kB
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./chat-html-preview-element-eYSaWZE7.js","./gateway-runtime-C77LeWZN.js","./session-snapshot-database-BBKeXATO.js","./control-ui-boot-shared-CkXlyZBY.js","./control-ui-boot-shared-gZIpWrfw.js","./control-ui-boot-shared-SQHdJTzb.js","./config-runtime-BecGLziM.js","./plugin-contracts-runtime-ByiEPbv_.js","./markdown-runtime-ORQpioyT.js","./control-ui-boot-chat-Ye5j4vAg.js","./sidebar-update-runtime-DQZboSgD.js","./control-ui-boot-chat-XPUNenUd.js","./control-ui-boot-chat-k_u3nGjS.js","./chat-transcript-styles-BN-TorbW.js","./control-ui-boot-chat-styles-BcslGtWC.js","./widget-sandbox-host-COBvR0Ux.js","./sandbox-host-Dm6XHU23.js","./control-ui-core-DI-Q_yCI.css","./control-ui-boot-shared-styles-DUf4zEvn.css","./control-ui-boot-shared-DIWJGbGi.css","./sidebar-update-runtime-Bpn2ByHA.css","./chat-transcript-styles-B0IJwY9P.css","./control-ui-boot-chat-styles-SRk09zDG.css","./control-ui-boot-chat-C2DT0d4M.css","./mcp-app-view-registration-B3yat5MI.js","./mcp-app-routing-DFzELUUu.js","./mcp-app-confirm-BOrRV_eo.js","./file-editor-view-Bh_qvyOa.js","./dist-BVfGhkDR.js","./code-language-CpyNAFNt.js"])))=>i.map(i=>d[i]);
import{n as e}from"./rolldown-runtime-8BhlS34s.js";import{Au as t,Hs as n,Ic as r,Jr as i,Ku as a,Lc as o,Nu as s,Pu as c,Yr as l,cl as u,ju as d,ll as ee,xu as f,yu as p,zu as m}from"./control-ui-core-CBJ5efDh.js";import{Ai as te,Fi as ne,Ji as re,Ki as h,Ui as g,Vi as ie,ca as _,di as ae,dr as oe,fi as v,ki as se,n as ce,qi as le,r as ue,sa as y,ur as de,zi as fe}from"./control-ui-core-DtLivg_r.js";import{C as pe,G as b,J as x,T as me,W as S,Z as C,_ as he,at as w,c as T,i as ge,l as E,o as D,rt as O,y as k}from"./lit-runtime-IOnANfcZ.js";import{An as _e,J as ve,Mn as ye,Nn as A,Pn as be,_r as xe,hr as Se,jn as Ce,kn as we}from"./control-ui-boot-shared-UG5ko-VG.js";import{Li as Te,Ur as Ee,Wr as De,Zr as j,ci as Oe,ma as M,pa as N}from"./ui-CmSP4d14.js";import{D as ke,F as Ae,M as je,T as Me,j as Ne}from"./control-ui-boot-shared-VLPz5vN2.js";import{An as Pe,At as Fe,Bt as Ie,Ht as Le,Kt as Re,Mi as ze,Mn as Be,Nn as Ve,Ut as He,Vt as Ue,bt as We,ci as Ge,cn as Ke,ei as qe,jt as Je,kt as Ye,li as Xe,on as Ze,ti as Qe,vt as $e}from"./control-ui-boot-shared-XreXSF7h.js";import{$s as et,Cs as tt,I as nt,Js as P,Ks as rt,Qp as F,Qs as it,R as at,Sc as ot,Ss as I,Ts as L,Xs as st,Zp as ct,Zs as R,_s as lt,bs as ut,ec as dt,gs as ft,ms as pt,ps as mt,vs as ht,ws as z,xc as gt,xs as _t,ys as vt}from"./control-ui-boot-shared-dOnP4mAA.js";import{p as yt}from"./control-ui-boot-shared-Q8KG_noF.js";import"./control-ui-boot-shared-styles-BXPMRytW.js";import{T as B,at as bt,it as xt,nt as St,w as V}from"./control-ui-boot-chat-CGYcTLro.js";import{Cn as Ct,Dn as H,En as wt,Sn as Tt,Tn as Et,_r as Dt,bn as Ot,gr as kt,hr as At,vr as jt,wn as Mt,xn as Nt,yn as Pt,yr as Ft}from"./control-ui-boot-chat-B-b-JQel.js";import{H as It,U as Lt,nt as Rt,rt as zt}from"./control-ui-boot-chat-CmENwCKi.js";var Bt;function Vt(){return(Vt=e((()=>{c(),f(),Bt=class{constructor(e,t,n){this.host=e,this.content=t,this.runtime=n,this.error=null,this.request=null,this.onDownload=async()=>{let e=this.content();if(e?.kind!==`attachment`||!e.download||this.request)return;let t=new AbortController,{connectionEpoch:n,sessionKey:r,agentId:i}=this.runtime();this.request=t,this.error=null,this.host.requestUpdate();let a=()=>{let a=this.runtime();return this.host.isConnected&&this.content()===e&&this.request===t&&a.connectionEpoch===n&&a.sessionKey===r&&a.agentId===i&&!t.signal.aborted};try{let n=await e.download(t.signal);if(!a())return;if(!n)throw Error(m(`chat.attachments.unavailable`));ve(e.title,n)}catch(e){a()&&(this.error=p(e))}finally{this.request===t&&(this.request=null,this.host.requestUpdate())}}}get pending(){return this.request!==null}cancel(){(this.request||this.error!==null)&&(this.request?.abort(),this.request=null,this.error=null,this.host.requestUpdate())}}})))()}var Ht;function Ut(){return(Ut=e((()=>{l(),Ht=class{constructor(e,t){this.host=e,this.content=t,this.feedback={},this.attempts=new Map,this.timers=new Map,this.copy=e=>{let t=this.content();if(t?.kind!==`file`)return;let n=(this.attempts.get(e)??0)+1;this.attempts.set(e,n);let r=()=>this.attempts.get(e)===n&&this.content()===t&&this.host.isConnected;i(e===`path`?t.path:t.content,r).then(t=>{r()&&(this.feedback={...this.feedback,[e]:t?`copied`:`failed`},this.host.requestUpdate(),globalThis.clearTimeout(this.timers.get(e)),this.timers.set(e,globalThis.setTimeout(()=>{this.timers.delete(e),this.feedback={...this.feedback,[e]:void 0},this.host.requestUpdate()},t?1500:2e3)))})},e.addController(this)}reset(){for(let e of this.timers.values())globalThis.clearTimeout(e);this.timers.clear();for(let[e,t]of this.attempts)this.attempts.set(e,t+1);this.feedback={},this.host.isConnected&&this.host.requestUpdate()}hostConnected(){this.reset()}hostDisconnected(){this.reset()}}})))()}function Wt(e,t){return e.split(`;`,1)[0]?.trim().toLowerCase()===`text/html`||/\.html?$/i.test(t)}function Gt(e,t,n,r,i,a){e.requestWhileActive(U,!0);let o=e.visibleState;return x`
    ${o?.status===`error`?v({error:o.error,stale:o.stale,onRetry:()=>e.retry()}):o?x`<div role="status">${m(`common.loading`)}</div>`:b}
    <openclaw-chat-html-preview
      .html=${t}
      .sourceIdentity=${n}
      .title=${r}
      .embedSandboxMode=${i}
      .sessionFileSource=${a}
    ></openclaw-chat-html-preview>
  `}var U,Kt;function W(){return(W=e((()=>{S(),ie(),g(),ae(),c(),V(),M(),B(),U={tagName:`openclaw-chat-html-preview`,get label(){return m(`chat.detailPanel.renderPreview`)},loadModule:()=>N(()=>import(`./chat-html-preview-element-eYSaWZE7.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]),import.meta.url)},Kt=class{constructor(e,t,n){this.host=e,this.content=t,this.text=n,this.source=!1,this.preview=null,this.loader=new fe(e),e.addController(this)}get file(){let e=this.content();return e?.kind===`file`&&Wt(e.mimeType??``,e.name)?e:null}get showing(){return this.file!==null&&!this.source}reset(e,t){this.source=t;let n=this.file;this.preview=n&&!t?e??n.content:null}showSource(){this.source||(this.source=!0,this.host.requestUpdate())}toggle(){this.source&&(this.preview=this.text()),this.source=!this.source,this.host.requestUpdate()}discard(e){this.preview!==null&&(this.preview=e,this.host.requestUpdate())}hostDisconnected(){this.loader.requestWhileActive(U,!1)}controls(e){let t=this.file;if(t)return{source:this.source,onToggle:e.onToggle,presentation:this.preview===null?b:Gt(this.loader,this.preview,t.draftKey??[e.runtime.sessionKey??``,e.runtime.agentId??``,t.root??``,t.path].join(`\0`),t.name,e.mode,t.sessionFileSource),sourceFallback:e.error?x`
            ${v({error:e.error,stale:h(e.error),onRetry:e.onRetry})}
            <pre class="sidebar-attachment-preview__text">${this.text()}</pre>
          `:void 0}}}})))()}function qt(e){let{settings:t,values:n}=e,r=()=>Object.entries(n).some(([e,n])=>t.values[e]!==n),i=r=>{let i=t.schema.properties[r];if(!i)return b;let a=t.schema.required?.includes(r)??!1,o=n[r];return x`<label class="mcp-app-settings__field"
      ><span>${i.title}</span
      >${i.description?x`<small class="muted">${i.description}</small>`:b}
      ${i.type===`boolean`?x`<input
              type="checkbox"
              .checked=${D(o===!0)}
              ?disabled=${e.busy}
              @change=${t=>{t.currentTarget instanceof HTMLInputElement&&e.onChange(r,t.currentTarget.checked)}}
            />`:i.type===`string`&&i.enum?x`<select
                .value=${D(String(o??``))}
                ?required=${a}
                ?disabled=${e.busy}
                @change=${t=>{t.currentTarget instanceof HTMLSelectElement&&e.onChange(r,t.currentTarget.value)}}
              >
                ${i.enum.map(e=>x`<option .value=${e} .selected=${e===o}>${e}</option>`)}
              </select>`:i.type===`string`?x`<input
                  type="text"
                  .value=${D(String(o??``))}
                  ?required=${a}
                  ?disabled=${e.busy}
                  minlength=${k(i.minLength)}
                  maxlength=${k(i.maxLength)}
                  pattern=${k(i.pattern)}
                  @input=${t=>{t.currentTarget instanceof HTMLInputElement&&e.onChange(r,t.currentTarget.value)}}
                />`:x`<input
                  type="number"
                  .value=${D(String(o??``))}
                  ?required=${a}
                  ?disabled=${e.busy}
                  min=${k(i.minimum)}
                  max=${k(i.maximum)}
                  step=${i.multipleOf??(i.type===`integer`?1:`any`)}
                  @input=${t=>{let n=t.currentTarget;n instanceof HTMLInputElement&&Number.isFinite(n.valueAsNumber)&&e.onChange(r,n.valueAsNumber)}}
                />`}
    </label>`},a=new Set(t.layout?.flatMap(e=>e.items.flatMap(e=>e.kind===`property`?[e.property]:[])));return x`<form
    class="mcp-app-settings"
    @submit=${t=>{t.preventDefault(),r()&&t.currentTarget instanceof HTMLFormElement&&t.currentTarget.reportValidity()&&e.onSave()}}
  >
    <p class="muted">${m(`mcpApp.settingsDescription`)}</p>
    ${t.layout?.map(t=>x`<fieldset ?disabled=${e.busy}>
          <legend>${t.title}</legend>
          ${t.items.map(t=>t.kind===`property`?i(t.property):x`<div class="mcp-app-settings__field"><button type="button" class="btn" @click=${()=>e.onTool(t.tool)}>${t.title}</button>${t.description?x`<small>${t.description}</small>`:b}</div>`)}
        </fieldset>`)}
    ${Object.keys(t.schema.properties).filter(e=>!a.has(e)).map(i)}
    <button type="submit" class="btn primary" ?disabled=${e.busy||!r()}>
      ${m(`mcpApp.save`)}
    </button>
  </form>`}function Jt(){return(Jt=e((()=>{S(),he(),ge(),c(),we(),_e()})))()}var G;function Yt(){return(Yt=e((()=>{De(),S(),C(),T(),te(),oe(),c(),we(),f(),s(),o(),Jt(),ue(),M(),_e(),G=class extends d{constructor(...e){super(...e),this.viewId=``,this.busy=!1,this.error=null,this.notice=``,this.settings=null,this.values={},this.generation=0,this.ownerScope=-1,this.launchIdentity=``,this.unmount=new ce(this),this.subscriptions=new r(this).watch(()=>this.context?.gateway,(e,t)=>e.subscribe(t))}currentLaunchIdentity(){let e=this.launch;return JSON.stringify([e?.sessionKey,e?.agentId,e?.serverName,e?.entrypoint.toolName,e?.filePath,e?.settings,e?.quickAction])}willUpdate(e){let t=this.context?de(this.context.gateway).key:-1,n=this.currentLaunchIdentity();(e.has(`launch`)&&n!==this.launchIdentity||t!==this.ownerScope)&&(this.launchIdentity=n,this.ownerScope=t,this.generation++,this.viewId=``,this.settings=null,this.busy=!1,this.error=null,this.launch&&this.context&&this.launch.owner===this.context.gateway.snapshot.client&&this.open())}async operation(e,t){let n=this.context,r=this.launch,i=n?.gateway.snapshot.client;if(!n||!r||!i||i!==r.owner||n.gateway.snapshot.phase!==`connected`){this.error=m(`mcpApp.disconnected`);return}let a=++this.generation,o=this.currentLaunchIdentity(),s=de(n.gateway).key,c=()=>this.isConnected&&a===this.generation&&this.currentLaunchIdentity()===o&&n.gateway.snapshot.client===i&&de(n.gateway).key===s;this.busy=!0,this.error=null,this.notice=``;try{let n=await e(i,r);c()&&t(n)}catch(e){c()&&(this.error=p(e))}finally{c()&&(this.busy=!1)}}async open(){if(this.launch?.settings){await this.readSettings();return}await this.operation(async(e,t)=>{if((await N(()=>import(`./mcp-app-view-registration-B3yat5MI.js`),__vite__mapDeps([24,1,2,4,3,5,7,6,8,10,25,9,11,12,13,14,26,16,17,18,19,20,21,22,23]),import.meta.url)).registerMcpAppView(),this.launch?.sessionKey!==t.sessionKey||this.launch?.serverName!==t.serverName||this.launch?.entrypoint.toolName!==t.entrypoint.toolName||e!==this.context?.gateway.snapshot.client||!this.isConnected)throw Error(m(`mcpApp.disconnected`));return await e.request(`mcp.app.launch`,{sessionKey:t.sessionKey,agentId:t.agentId,serverName:t.serverName,toolName:t.entrypoint.toolName,entrypointType:t.entrypoint.entrypoint.type,...t.quickAction?{quickAction:!0}:{},...t.filePath?{filePath:t.filePath}:{},...t.deepLink?{deepLink:t.deepLink}:{}})},e=>{if(e.toolResult?.isError||!e.viewId&&!e.toolResult)throw Error(m(`mcpApp.errors.requestFailed`));e.viewId?this.viewId=e.viewId:this.notice=m(`mcpApp.actionComplete`)})}params(e){return{sessionKey:this.launch.sessionKey,agentId:this.launch.agentId,serverName:this.launch.serverName,action:e}}async readSettings(){await this.operation(e=>e.request(`mcp.app.settings`,this.params(`read`)),e=>{this.settings=e,this.values={...e.values}})}async saveSettings(){let e=Object.fromEntries(Object.entries(this.values).filter(([e,t])=>this.settings?.values[e]!==t));Object.keys(e).length&&await this.operation(async t=>{if((await t.request(`mcp.app.settings`,{...this.params(`update`),arguments:{set:e}})).toolResult?.isError)throw Error(m(`mcpApp.errors.requestFailed`));return await t.request(`mcp.app.settings`,this.params(`read`))},e=>{this.settings=e,this.values={...e.values},this.notice=m(`mcpApp.settingsSaved`)})}async runTool(e){await this.operation(async(t,n)=>{if((await N(()=>import(`./mcp-app-view-registration-B3yat5MI.js`),__vite__mapDeps([24,1,2,4,3,5,7,6,8,10,25,9,11,12,13,14,26,16,17,18,19,20,21,22,23]),import.meta.url)).registerMcpAppView(),this.launch!==n||this.context?.gateway.snapshot.client!==t||!this.isConnected)throw Error(m(`mcpApp.disconnected`));return t.request(`mcp.app.settings`,{...this.params(`tool`),toolName:e})},e=>{if(e.toolResult?.isError){this.error=m(`mcpApp.errors.requestFailed`);return}e.viewId?(this.settings=null,this.viewId=e.viewId):this.notice=m(`mcpApp.actionComplete`)})}disconnectedCallback(){this.generation++,this.subscriptions.clear(),super.disconnectedCallback()}render(){let e=this.launch;return e?x`<section class="mcp-app-panel">
      <div class="mcp-app-panel__toolbar">
        <strong>${e.entrypoint.title}</strong><span class="muted">${e.serverName}</span>
        ${e.settings&&!this.settings?x`<button
                class="btn btn--sm"
                ?disabled=${this.busy}
                @click=${()=>{this.viewId=``,this.readSettings()}}
              >
                ${m(`mcpApp.settings`)}
              </button>`:b}
      </div>
      ${this.busy?x`<p role="status">${m(`mcpApp.loading`)}</p>`:b}
      ${this.error?x`<p role="alert">${this.error}</p>
              <button class="btn" @click=${()=>void this.open()}>${m(`mcpApp.retry`)}</button>`:b}
      ${this.notice?x`<p role="status">${this.notice}</p>`:b}
      ${this.settings?qt({settings:this.settings,values:this.values,busy:this.busy,onChange:(e,t)=>{this.values={...this.values,[e]:t}},onSave:()=>void this.saveSettings(),onTool:e=>void this.runTool(e)}):b}
      ${this.unmount.render(this.viewId,()=>this.viewId?E(this.viewId,x`<mcp-app-view
                  .sessionKey=${e.sessionKey}
                  .agentId=${e.agentId??``}
                  .viewId=${this.viewId}
                  .title=${e.entrypoint.title}
                  .deepLink=${e.deepLink}
                  .onRelaunch=${()=>void this.open()}
                  .relaunching=${this.busy}
                ></mcp-app-view>`):b,()=>[this])}
    </section>`:b}},j([Ee({context:se,subscribe:!0})],G.prototype,`context`,void 0),j([w({attribute:!1})],G.prototype,`launch`,void 0),j([O()],G.prototype,`viewId`,void 0),j([O()],G.prototype,`busy`,void 0),j([O()],G.prototype,`error`,void 0),j([O()],G.prototype,`notice`,void 0),j([O()],G.prototype,`settings`,void 0),j([O()],G.prototype,`values`,void 0),customElements.get(`openclaw-mcp-app-panel`)||customElements.define(`openclaw-mcp-app-panel`,G)})))()}function Xt(e,t){let n=e.split(`;`,1)[0]?.trim().toLowerCase()??``;return n===`application/pdf`||(!n||n===`application/octet-stream`)&&/\.pdf$/i.test(t)}var K,Zt,q;function Qt(){return(Qt=e((()=>{S(),C(),c(),s(),I(),st(),ut(),K=16777216,Zt=1e4,q=class extends t{constructor(...e){super(...e),this.src=``,this.sourceIdentity=``,this.label=``,this.mimeType=``,this.status=`loading`,this.previewUrl=null}connectedCallback(){super.connectedCallback(),this.requestUpdate(`src`)}disconnectedCallback(){this.cancelLoad(),this.revokePreviewUrl(),super.disconnectedCallback()}willUpdate(e){(e.has(`src`)||e.has(`sourceIdentity`)||e.has(`sizeBytes`))&&(this.cancelLoad(),(!this.src||!this.previewUrl||!this.sourceIdentity||e.has(`sourceIdentity`)||e.has(`sizeBytes`))&&(this.revokePreviewUrl(),this.status=`loading`),this.src&&this.loadPdf())}cancelLoad(){this.abortController?.abort(),this.abortController=void 0}revokePreviewUrl(){this.previewUrl&&URL.revokeObjectURL(this.previewUrl),this.previewUrl=null,this.previewBytes=void 0}async loadPdf(){if(this.sizeBytes!==void 0&&this.sizeBytes>K){this.status=`error`;return}let e=new AbortController;this.abortController=e;let t=setTimeout(()=>e.abort(),Zt);try{let t=await fetch(this.src,{credentials:`same-origin`,redirect:`error`,signal:e.signal});if(!t.ok)throw await t.body?.cancel().catch(()=>void 0),Error(`PDF attachment unavailable`);let n=await _t(t,K);if(!n)throw Error(`PDF attachment exceeds preview limit`);if(this.abortController!==e||!this.isConnected)return;let r=new Uint8Array(n);if(this.previewBytes?.length===r.length&&this.previewBytes.every((e,t)=>e===r[t]))return;this.revokePreviewUrl(),this.previewBytes=r,this.previewUrl=URL.createObjectURL(new Blob([n],{type:`application/pdf`})),this.status=`ready`}catch{this.abortController===e&&this.isConnected&&(this.revokePreviewUrl(),this.status=`error`)}finally{clearTimeout(t),this.abortController===e&&(this.abortController=void 0)}}render(){let e=it(this.src);return x`
      <div class="sidebar-pdf-preview" aria-label=${this.label}>
        <div class="sidebar-pdf-preview__surface">
          ${this.status===`loading`?z():this.status===`error`||!this.previewUrl?x`<div class="sidebar-attachment-preview__unavailable" role="alert">
                    ${m(`chat.attachments.previewUnavailable`)}
                    ${L({kind:`document`,label:this.label,mimeType:this.mimeType,sizeBytes:this.sizeBytes,downloadHref:e??void 0})}
                  </div>`:x`<iframe
                    class="sidebar-pdf-preview__frame"
                    title=${this.label}
                    src=${this.previewUrl}
                    referrerpolicy="no-referrer"
                  ></iframe>`}
        </div>
      </div>
    `}},j([w()],q.prototype,`src`,void 0),j([w()],q.prototype,`sourceIdentity`,void 0),j([w()],q.prototype,`label`,void 0),j([w()],q.prototype,`mimeType`,void 0),j([w({type:Number})],q.prototype,`sizeBytes`,void 0),j([O()],q.prototype,`status`,void 0),j([O()],q.prototype,`previewUrl`,void 0),customElements.get(`openclaw-chat-pdf-preview`)||customElements.define(`openclaw-chat-pdf-preview`,q)})))()}function $t(e,t){let n=e.split(`;`,1)[0]?.trim().toLowerCase()??``;return n.startsWith(`text/`)||/^application\/(?:(?:[\w.-]+\+)?(?:json|xml)|javascript|x-javascript|yaml|x-yaml)$/.test(n)?!0:(!n||n===`application/octet-stream`)&&/\.(?:txt|md|markdown|html?|log|csv|tsv|json|jsonl|xml|yaml|yml)$/i.test(t)}var J;function en(){return(en=e((()=>{S(),C(),T(),Me(),ie(),Ze(),_(),Rt(),$e(),c(),V(),ee(),ot(),s(),I(),mt(),W(),B(),J=class extends t{constructor(...e){super(...e),this.plainText=!1,this.actions=b,this.embedSandboxMode=`scripts`,this.src=``,this.sourceIdentity=``,this.label=``,this.mimeType=``,this.text=null,this.failed=!1,this.source=!1,this.htmlPreviewLoader=new fe(this),this.loadVersion=0}connectedCallback(){super.connectedCallback(),this.requestUpdate(`src`)}disconnectedCallback(){this.cancelLoad(),this.htmlPreviewLoader.requestWhileActive(U,!1),super.disconnectedCallback()}get htmlDocument(){return!this.plainText&&Wt(this.mimeType,this.label)}willUpdate(e){e.has(`sourceIdentity`)&&(this.source=!1);let t=e.has(`plainText`)||e.has(`mimeType`)||e.has(`label`);(t||e.has(`src`)||e.has(`sourceIdentity`)||e.has(`sizeBytes`))&&(this.cancelLoad(),(t||!this.src||!this.sourceIdentity||e.has(`sourceIdentity`)||e.has(`sizeBytes`))&&(this.text=null),this.failed=!1,this.src&&this.loadText())}cancelLoad(){this.loadVersion+=1,this.abortController?.abort(),this.abortController=void 0}async loadText(){let e=this.loadVersion,t=new AbortController;this.abortController=t;try{let n=await pt(this.src,this.sizeBytes,t.signal,this.htmlDocument?`html`:`full`);e===this.loadVersion&&this.isConnected&&(this.text=n)}catch{e===this.loadVersion&&this.isConnected&&(this.text=null,this.failed=!0)}finally{this.abortController===t&&(this.abortController=void 0)}}retry(){this.cancelLoad(),this.text=null,this.failed=!1,this.loadText()}render(){let e=this.htmlDocument,t=this.mimeType.split(`;`,1)[0]?.trim().toLowerCase(),n=!this.plainText&&(t===`text/markdown`||t===`text/x-markdown`||/\.(?:md|markdown)$/i.test(this.label)),r=x`<pre
      class="sidebar-attachment-preview__text"
      tabindex="0"
      aria-label=${this.label}
      ?hidden=${e&&!this.source}
    >
${this.text}</pre>`,i=this.text===null?z():x`${E(this.sourceIdentity||this.loadVersion,x`${E(this.text,e?x`<div class="chat-html-preview" ?hidden=${this.source}>
                      ${Gt(this.htmlPreviewLoader,this.text,this.sourceIdentity||this.src,this.label,this.embedSandboxMode)}
                    </div>
                    ${r}`:n&&!this.source?x`<article
                      class="sidebar-attachment-preview__markdown sidebar-markdown-reader sidebar-markdown"
                      dir=${gt(this.text)}
                      aria-label=${this.label}
                      ${zt()}
                    >
                      ${ke(We(this.text,{mode:`document`,remoteImages:!1,codeBlockInteraction:`interactive`}))}
                    </article>`:r)}`)}`;return x`
      <div class="sidebar-file-toolbar">
        <span class="sidebar-file-toolbar__type" title=${this.mimeType}
          >${this.mimeType||this.label.split(`.`).at(-1)}</span
        >
        ${this.sizeBytes===void 0?b:x`<span>${u(this.sizeBytes)}</span>`}
        <span class="sidebar-file-toolbar__actions">
          ${this.text!==null&&!this.failed?E(this.loadVersion,Ke(this.text,m(`common.copy`))):b}
          ${this.actions}
          ${this.failed?x`<button class="btn btn--sm" type="button" @click=${()=>this.retry()}>${m(`common.retry`)}</button>`:b}
          ${(n||e)&&this.text!==null?x`<button
                  class="btn btn--sm"
                  type="button"
                  aria-pressed=${String(this.source)}
                  @click=${()=>{this.source=!this.source}}
                >
                  ${this.source?m(`chat.workspaceFiles.preview`):m(e?`chat.detailPanel.viewSource`:`chat.detailPanel.viewRawText`)}
                </button>`:b}
          <a
            class="rail-header__action"
            href=${this.src||b}
            download=${this.label}
            target="_blank"
            rel="noreferrer"
            aria-label=${m(`chat.mediaPlayer.download`,{filename:this.label})}
            >${y.download}</a
          >
        </span>
      </div>
      ${this.failed?x`<p class="muted" role="status">
              ${m(e?`chat.attachments.htmlPreviewUnavailable`:`chat.attachments.textPreviewUnavailable`)}
            </p>`:i}
    `}},j([w({type:Boolean})],J.prototype,`plainText`,void 0),j([w({attribute:!1})],J.prototype,`actions`,void 0),j([w()],J.prototype,`embedSandboxMode`,void 0),j([w()],J.prototype,`src`,void 0),j([w()],J.prototype,`sourceIdentity`,void 0),j([w()],J.prototype,`label`,void 0),j([w()],J.prototype,`mimeType`,void 0),j([w({type:Number})],J.prototype,`sizeBytes`,void 0),j([O()],J.prototype,`text`,void 0),j([O()],J.prototype,`failed`,void 0),j([O()],J.prototype,`source`,void 0),customElements.get(`openclaw-chat-text-attachment`)||customElements.define(`openclaw-chat-text-attachment`,J)})))()}function tn(e,t){return e.every(e=>e.kind!==`add`&&e.kind!==`ctx`||e.lineNo===void 0||t[e.lineNo-1]===e.text)}function nn(e,t,n){return Array.from({length:n},(n,r)=>({kind:`ctx`,lineNo:t+r,text:e[t+r-1]}))}function rn(e,t,n,r,i){let a=e.findIndex(e=>e.kind===`skip`&&e.gap===t),o=t.newStart+t.count-1;if(a<0||t.newStart<1||t.count<1||o>n.length||!tn(e,n))return null;let s=r===`all`||t.count<=on?t.count:Math.min(an,t.count),c=t.count-s,l=nn(n,r===`up`?t.newStart+c:t.newStart,s);return c>0&&l.splice(r===`up`?0:l.length,0,{kind:`skip`,text:i(c),gap:r===`up`?{...t,count:c}:{oldStart:t.oldStart+s,newStart:t.newStart+s,count:c}}),[...e.slice(0,a),...l,...e.slice(a+1)]}var an,on;function sn(){return(sn=e((()=>{Se(),an=20,on=25})))()}function cn(e,t){let n=[],r=!1,i=!1,a=0,o=0,s,c,l=e.replace(/\r\n/g,`
`).split(`
`);l.at(-1)===``&&l.pop();for(let e of l){let l=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(e);if(l){let e=Number.parseInt(l[1]??``,10),r=Number.parseInt(l[2]??``,10),u=s===void 0?e-1:e-s;u>0&&n.push({kind:`skip`,text:t(u),gap:{oldStart:s??e-u,newStart:c??r-u,count:u}}),a=e,o=r,i=!0;continue}if(!i||e.startsWith(`\\`))continue;if(n.length>=ln){r=!0;break}let u=e.startsWith(`+`)?`add`:e.startsWith(`-`)?`del`:`ctx`;n.push({kind:u,lineNo:u===`del`?a:o,text:e.slice(1)}),u!==`add`&&(a+=1),u!==`del`&&(o+=1),s=a,c=o}return{lines:n,truncated:r}}var ln;function un(){return(un=e((()=>{ln=600})))()}var Y;function dn(){return(dn=e((()=>{S(),C(),Ze(),Xe(),_(),qe(),ze(),c(),A(),s(),Y=class extends d{constructor(...e){super(...e),this.menu=null,this.onAction=()=>{},this.onClose=()=>{},this.menuLifecycle=new Ge(this,{getTrigger:()=>this.menu?.trigger??null,onClose:()=>this.onClose()}),this.handleSelect=e=>{e.preventDefault();let t=e.detail.item.value;if(!t)return;let n={"collapse-all":{kind:`collapse-all`},"expand-all":{kind:`expand-all`},"toggle-split":{kind:`toggle-split`},"toggle-wrap":{kind:`toggle-wrap`},"scope:all":{kind:`scope`,value:{scope:`all`}},"scope:uncommitted":{kind:`scope`,value:{scope:`uncommitted`}}},r=this.menu?.kind===`file`?this.menu:null;if(r&&(t===`open-file`||t===`reveal-file`)){this.run({kind:t,path:r.path});return}let i=n[t];if(i){this.run(i);return}if(t.startsWith(`open-editor:`)){let e=t.slice(12);if(Ce.includes(e)){let t=this.menu?.kind===`file`?this.menu.absolutePath:void 0;t&&this.run({kind:`open-editor`,editor:e,path:t})}return}t.startsWith(`scope:commit:`)&&this.run({kind:`scope`,value:{scope:`commit`,commit:t.slice(13)}})},this.handleAfterHide=e=>{e.currentTarget instanceof Node&&e.currentTarget.isConnected&&this.onClose()}}connectedCallback(){super.connectedCallback(),Qe(this)}run(e){this.onClose(),this.onAction(e)}renderFileMenu(e){return x`
      ${this.renderCopyRow(e.path,m(`chat.sessionDiff.copyPath`))}
      <wa-dropdown-item class="session-menu__item" value="open-file" ?disabled=${!e.canOpenFile}>
        <span slot="icon" class="session-menu__icon" aria-hidden="true">${y.fileText}</span>
        <span class="session-menu__text">${m(`chat.sessionDiff.openFile`)}</span>
      </wa-dropdown-item>
      ${e.canReveal?x`<wa-dropdown-item class="session-menu__item" value="reveal-file">
              <span slot="icon" class="session-menu__icon" aria-hidden="true">${y.folder}</span>
              <span class="session-menu__text">${m(`chat.sessionDiff.revealInFileTree`)}</span>
            </wa-dropdown-item>`:b}
      ${e.absolutePath?x`<wa-dropdown-item class="session-menu__item">
              <span slot="icon" class="session-menu__icon" aria-hidden="true"
                >${y.externalLink}</span
              >
              <span class="session-menu__text">${m(`chat.sessionDiff.openInEditor`)}</span>
              ${Ce.map(e=>x`<wa-dropdown-item
                  slot="submenu"
                  class="session-menu__item"
                  value=${`open-editor:${e}`}
                >
                  <span class="session-menu__text">${ye[e]}</span>
                </wa-dropdown-item>`)}
            </wa-dropdown-item>`:b}
    `}renderViewMenu(e){return x`
      ${this.renderMenuItem(`collapse-all`,m(`chat.sessionDiff.collapseAll`))}
      ${this.renderMenuItem(`expand-all`,m(`chat.sessionDiff.expandAll`))}
      <div class="session-menu__separator" role="separator"></div>
      ${this.renderMenuItem(`toggle-wrap`,m(e.wrap?`chat.sessionDiff.disableWrapping`:`chat.sessionDiff.enableWrapping`))}
      ${this.renderMenuItem(`toggle-split`,m(e.split?`chat.sessionDiff.switchUnified`:`chat.sessionDiff.switchSplit`))}
    `}renderScopeMenu(e){let t=e.active.scope===`commit`?e.active.commit:null;return x`
      ${this.renderMenuItem(`scope:all`,m(`chat.sessionDiff.allChanges`),e.active.scope===`all`)}
      ${this.renderMenuItem(`scope:uncommitted`,m(`chat.sessionDiff.uncommitted`),e.active.scope===`uncommitted`)}
      ${e.result.commits?.length?x`<div class="session-menu__separator" role="separator"></div>
              ${e.result.commits.map((e,n)=>this.renderMenuItem(`scope:commit:${e.sha}`,x`<span class="session-diff-menu__sha">${e.sha}</span>
                    <span class="session-diff-menu__subject">${e.subject}</span>
                    ${n===0?x`<span class="session-diff-menu__head"
                            >${m(`chat.sessionDiff.head`)}</span
                          >`:b}`,t===e.sha))}`:b}
      ${e.result.mergeBase?x`<div class="session-menu__separator" role="separator"></div>
              <div class="session-diff-menu__merge-base">
                <span>${m(`chat.sessionDiff.mergeBase`)}</span>
                <span class="session-diff-menu__sha">${e.result.mergeBase.sha}</span>
                <span class="session-diff-menu__subject">${e.result.mergeBase.subject}</span>
              </div>`:b}
    `}renderMenuItem(e,t,n){return x`<wa-dropdown-item
      class=${n===void 0?`session-menu__item`:`session-menu__item session-diff-menu__scope-item`}
      value=${e}
      role=${n===void 0?b:`menuitemradio`}
      aria-checked=${n===void 0?b:String(n)}
    >
      <span class="session-menu__text">${t}</span>
      ${n?x`<span slot="details" class="session-menu__check" aria-hidden="true"
              >${y.check}</span
            >`:b}
    </wa-dropdown-item>`}renderSyncMenu(e){return x`<div class="session-diff-menu__sync">
      <strong>${m(`chat.sessionDiff.syncLocally`)}</strong>
      <p>${m(`chat.sessionDiff.syncDescription`)}</p>
      ${this.renderCopyRow(e.command,m(`chat.sessionDiff.copyCommand`),!0)}
      ${this.renderCopyRow(e.root,m(`chat.sessionDiff.checkoutPath`))}
      ${this.renderCopyRow(e.branch,m(`chat.sessionDiff.branchName`))}
      <p class="session-diff-menu__note">${m(`chat.sessionDiff.uncommittedStay`)}</p>
    </div>`}renderCopyRow(e,t,n=!1){return x`<div class="session-diff-menu__copy-row ${n?`is-command`:``}">
      <span class="session-diff-menu__copy-label">${t}</span>
      <code title=${e}>${e}</code>
      ${Ke(e,t)}
    </div>`}render(){let e=this.menu;if(!e)return b;let t=e.kind===`scope`?e.placement??`top-start`:`bottom-end`,n=e.kind===`sync`?360:e.kind===`scope`?340:240,r=e.kind===`file`?m(`chat.sessionDiff.fileActions`,{path:e.path}):e.kind===`scope`?m(`chat.sessionDiff.scopeMenu`):e.kind===`sync`?m(`chat.sessionDiff.syncLocally`):m(`chat.sessionDiff.viewOptions`),i=Math.max(8,Math.min(e.anchor.x,window.innerWidth-8)),a=Math.max(8,Math.min(e.anchor.y,window.innerHeight-8));return x`<wa-dropdown
      class="session-menu session-diff-menu session-diff-menu--${e.kind}"
      style=${`--session-diff-menu-width:${n}px`}
      .open=${!0}
      placement=${t}
      .distance=${4}
      aria-label=${r}
      @wa-select=${this.handleSelect}
      @wa-after-hide=${this.handleAfterHide}
    >
      <button
        slot="trigger"
        type="button"
        tabindex="-1"
        aria-hidden="true"
        style="position:fixed;left:${i}px;top:${a}px;width:1px;height:1px;opacity:0;pointer-events:none"
      ></button>
      ${e.kind===`file`?this.renderFileMenu(e):e.kind===`scope`?this.renderScopeMenu(e):e.kind===`sync`?this.renderSyncMenu(e):this.renderViewMenu(e)}
    </wa-dropdown>`}},j([w({attribute:!1})],Y.prototype,`menu`,void 0),j([w({attribute:!1})],Y.prototype,`onAction`,void 0),j([w({attribute:!1})],Y.prototype,`onClose`,void 0),customElements.get(`openclaw-session-diff-menu`)||customElements.define(`openclaw-session-diff-menu`,Y)})))()}function fn(e){let t=[];for(let n=0;n<e.length;){let r=e[n];if(!r)break;if(r.kind!==`add`&&r.kind!==`del`){t.push({kind:`span`,line:r}),n+=1;continue}let i=[],a=[];for(;n<e.length;){let t=e[n];if(t?.kind===`del`)i.push(t);else if(t?.kind===`add`)a.push(t);else break;n+=1}let o=Math.max(i.length,a.length);for(let e=0;e<o;e+=1)t.push({kind:`pair`,...i[e]?{left:i[e]}:{},...a[e]?{right:a[e]}:{}})}return t}function pn(e,t,n){let r=t===`left`?`-`:`+`;return x`<div
    class="session-diff-split__side session-diff-split__side--${t} ${e?`session-diff-split__side--filled`:``}"
  >
    <span class="session-diff-split__gutter">${e?.lineNo??``}</span>
    <span class="session-diff-split__sign">${e?r:``}</span>
    <span class="session-diff-split__text">${e?n(e):``}</span>
  </div>`}function mn(e,t,n){let r=fn(e);return Ft(e,n,e=>x`<div
      class="session-diff-split code-highlight"
      role="figure"
      aria-label=${m(`chat.toolCards.fileChanges`)}
    >
      ${r.map(n=>n.kind===`pair`?x`<div class="session-diff-split__row session-diff-split__row--pair">
            ${pn(n.left,`left`,e)}
            ${pn(n.right,`right`,e)}
          </div>`:n.line.kind===`skip`?x`<div class="session-diff-split__row session-diff-split__row--skip">
            ${(t(n.line)??n.line.text)||`⋯`}
          </div>`:x`<div class="session-diff-split__row session-diff-split__row--context">
          <span class="session-diff-split__gutter">${n.line.lineNo??``}</span>
          <span class="session-diff-split__sign"></span>
          <span class="session-diff-split__text">${e(n.line)}</span>
        </div>`)}
    </div>`)}function hn(){return(hn=e((()=>{S(),c(),jt()})))()}function gn(){try{let e=JSON.parse(a()?.getItem(X)??`null`);return{split:e?.split===!0,wrap:e?.wrap===!0}}catch{return{split:!1,wrap:!1}}}function _n(e){try{a()?.setItem(X,JSON.stringify(e))}catch{}}function vn(e){let t=Math.min(e.additions,e.deletions);return{added:e.additions-t,removed:e.deletions-t,modified:t}}function yn(e){return e.reduce((e,t)=>{let n=vn(t);return e.added+=n.added,e.removed+=n.removed,e.modified+=n.modified,e},{added:0,removed:0,modified:0})}function bn(e){let t=e.replaceAll(`\\`,`/`),n=t.lastIndexOf(`/`);return n<0?{directory:``,name:t}:{directory:t.slice(0,n),name:t.slice(n+1)}}function xn(e){return/^[A-Za-z0-9_./:@+-]+$/.test(e)?e:`'${e.replaceAll(`'`,`'\\''`)}'`}var X,Z,Q;function Sn(){return(Sn=e((()=>{Ne(),S(),C(),T(),Pe(),_(),It(),c(),ne(),sn(),un(),A(),f(),s(),At(),dn(),hn(),X=`openclaw.control.sessionDiff.v1`,Z={added:[`A`,`chat.sessionDiff.statusAdded`],deleted:[`D`,`chat.sessionDiff.statusDeleted`],renamed:[`R`,`chat.sessionDiff.statusRenamed`],modified:[`M`,`chat.sessionDiff.statusModified`]},Q=class extends d{constructor(){super(),this.owner=null,this.execNode=null,this.loader=null,this.loadFileText=null,this.openFile=null,this.revealFile=null,this.collapsedPaths=new Set,this.menu=null,this.scope={scope:`all`},this.split=gn().split,this.wrap=gn().wrap,this.fileTextCache=new WeakMap,this.unavailableFileText=new WeakSet,this.prefetchedDiffResult=null,this.diffTask=new je(this,{args:()=>[this.loader,this.owner,this.scope],task:async([e,t,n])=>{if(!e)return null;let r=this.prefetchedDiffResult??await e(n);return this.prefetchedDiffResult=null,{owner:t,scope:n,result:r,views:r.files.map(e=>({file:e,parsed:e.patch?cn(e.patch,e=>m(`chat.sessionDiff.unmodifiedLines`,{count:String(e)})):null}))}},onComplete:e=>{let t=new Set(e?.views.map(e=>e.file.path)??[]);this.collapsedPaths=new Set([...this.collapsedPaths].filter(e=>t.has(e)))}}),Ve(this,()=>{this.menu=null})}get loading(){return this.loader!==null&&this.diffTask.status===Ae.PENDING}toggleFile(e){let t=new Set(this.collapsedPaths);t.has(e)?t.delete(e):t.add(e),this.collapsedPaths=t}openAnchoredMenu(e,t,n=`bottom-end`){e.stopPropagation();let r=e.currentTarget;if(!(r instanceof HTMLElement))return;let i=r.getBoundingClientRect();this.menu={...t,...t.kind===`scope`&&n!==`bottom-end`?{placement:n}:{},anchor:{x:n.endsWith(`start`)?i.left:i.right,y:n.startsWith(`top`)?i.top:i.bottom},trigger:r}}handleMenuAction(e){switch(e.kind){case`collapse-all`:{let e=this.diffTask.value?.views??[];this.collapsedPaths=new Set(e.map(e=>e.file.path));return}case`expand-all`:this.collapsedPaths=new Set;return;case`toggle-wrap`:case`toggle-split`:{let t=e.kind===`toggle-wrap`?`wrap`:`split`;this[t]=!this[t],_n({split:this.split,wrap:this.wrap});return}case`scope`:JSON.stringify(e.value)!==JSON.stringify(this.scope)&&(this.scope=e.value);return;case`open-file`:this.openFile?.(e.path);return;case`reveal-file`:this.revealFile?.(e.path);return;case`open-editor`:be(e.editor,e.path)}}renderSummary(e){let t=e.baseRef&&e.branch&&e.baseRef!==e.branch?`${e.baseRef} → ${e.branch}`:e.branch??e.baseRef??``,n=e.root&&e.branch?`git fetch ${xn(e.root)} ${xn(e.branch)} && git checkout FETCH_HEAD`:null;return x`
      <div class="session-diff__summary">
        <span
          class="session-diff__branch"
          title=${[t,e.root].filter(Boolean).join(`
`)}
        >
          ${y.gitBranch}
          <span class="session-diff__branch-label">${t}</span>
        </span>
        ${e.unavailableReason===`workspace_stopped`?b:Dt(yn(e.files))}
        <span class="session-diff__summary-spacer"></span>
        ${n&&e.root&&e.branch?x`<button
                class="btn btn--ghost btn--sm session-diff__toolbar-button"
                type="button"
                @click=${t=>this.openAnchoredMenu(t,{kind:`sync`,command:n,root:e.root,branch:e.branch})}
              >
                ${m(`chat.sessionDiff.sync`)} ${y.chevronDown}
              </button>`:b}
        <openclaw-tooltip .content=${m(`chat.sessionDiff.viewOptions`)}>
          <button
            class="btn btn--ghost btn--icon session-diff__toolbar-icon"
            type="button"
            aria-label=${m(`chat.sessionDiff.viewOptions`)}
            @click=${e=>this.openAnchoredMenu(e,{kind:`view`,split:this.split,wrap:this.wrap})}
          >
            ${y.moreHorizontal}
          </button>
        </openclaw-tooltip>
        <openclaw-tooltip .content=${m(`chat.sessionDiff.refresh`)}>
          <button
            class="btn btn--ghost btn--icon session-diff__refresh"
            type="button"
            aria-label=${m(`chat.sessionDiff.refresh`)}
            ?disabled=${this.loading}
            @click=${()=>void this.diffTask.run()}
          >
            ${y.refresh}
          </button>
        </openclaw-tooltip>
      </div>
    `}canExpandGaps(e){return this.scope.scope!==`commit`&&!!this.loadFileText&&e.file.binary!==!0&&e.parsed!==null&&!e.parsed.truncated&&!this.unavailableFileText.has(e)}loadFileLines(e){let t=this.fileTextCache.get(e);if(t)return t;let n=this.loadFileText,r=n?n(e.file.path).then(e=>e===null?null:xe(e)).catch(()=>null):Promise.resolve(null);return this.fileTextCache.set(e,r),r}async expandGap(e,t,n){let r=e.parsed,i=this.loader;if(!r||!t.gap||!i||!this.canExpandGaps(e))return;let a=this.scope,o;try{o=await i(a)}catch{return}if(this.loader!==i||this.scope!==a||!this.diffTask.value?.views.includes(e))return;let s=o.files.find(t=>t.path===e.file.path);if(!s||s.patch!==e.file.patch){this.fileTextCache.delete(e),this.prefetchedDiffResult=o,await this.diffTask.run();return}let c=await this.loadFileLines(e),l=c&&this.diffTask.value?.views.includes(e)?rn(r.lines,t.gap,c,n,e=>m(`chat.sessionDiff.unmodifiedLines`,{count:String(e)})):null;l?r.lines=l:this.unavailableFileText.add(e),this.requestUpdate()}renderGap(e,t){let n=t.gap;if(!n||!this.canExpandGaps(e))return t.text;let r=n.count<=25?n.count:20;return x`<span class="session-diff__gap-controls">
      ${[[`up`,`expandPreviousLines`,y.chevronUp],[`all`,`expandAllLines`,t.text],[`down`,`expandNextLines`,y.chevronDown]].map(([i,a,o])=>x`<button
          class=${i===`all`?`session-diff__gap-count`:b}
          type="button"
          aria-label=${m(`chat.sessionDiff.${a}`,{count:String(i===`all`?n.count:r)})}
          @click=${()=>void this.expandGap(e,t,i)}
        >
          ${o}
        </button>`)}
    </span>`}renderFileBody(e,t){let{file:n,parsed:r}=e;if(n.binary===!0||!r)return x`<div class="session-diff__note">
        ${m(n.binary===!0?`chat.sessionDiff.binaryFile`:t.unavailableReason===`workspace_stopped`?`chat.sessionDiff.workspaceStoppedFile`:`chat.sessionDiff.previewUnavailable`)}
      </div>`;let i=t=>this.renderGap(e,t);return x`
      ${this.split?mn(r.lines,i,n):kt(r.lines,`succeeded`,i,n)}
      ${r.truncated?x`<div class="session-diff__note">${m(`chat.sessionDiff.truncatedFile`)}</div>`:b}
    `}renderFile(e,t){let{file:n}=e,r=this.collapsedPaths.has(n.path),{directory:i,name:a}=bn(n.path),o=t.root?Be({root:t.root,path:n.path},this.execNode)??void 0:void 0,s=n.oldPath?`${n.oldPath} → ${n.path}`:n.path,[c,l]=Z[n.status]??Z.modified;return x`
      <section class="session-diff__file" data-status=${n.status}>
        <div class="session-diff__file-header">
          <button
            class="session-diff__file-toggle"
            type="button"
            aria-expanded=${String(!r)}
            title=${s}
            @click=${()=>this.toggleFile(n.path)}
          >
            <span class="session-diff__chevron ${r?``:`session-diff__chevron--open`}">
              ${y.chevronRight}
            </span>
            <span
              class="session-diff__status session-diff__status--${n.status}"
              title=${m(l)}
              >${c}</span
            >
            <span class="session-diff__path">
              ${n.oldPath?x`<span class="session-diff__old-path">${n.oldPath} →</span>`:b}
              <span class="session-diff__filename">${a}</span>
              ${i?x`<span class="session-diff__directory">${i}</span>`:b}
            </span>
            ${n.untracked===!0?x`<span class="session-diff__badge">${m(`chat.sessionDiff.untracked`)}</span>`:b}
            ${t.unavailableReason===`workspace_stopped`?b:Dt(vn(n))}
          </button>
          <button
            class="btn btn--ghost btn--icon session-diff__file-menu"
            type="button"
            aria-label=${m(`chat.sessionDiff.fileActions`,{path:n.path})}
            @click=${e=>this.openAnchoredMenu(e,{kind:`file`,path:n.path,...o?{absolutePath:o}:{},canOpenFile:!!this.openFile,canReveal:!!this.revealFile})}
          >
            ${y.moreHorizontal}
          </button>
        </div>
        ${r?b:x`<div
                class="session-diff__file-body"
                style=${`contain-intrinsic-size:auto ${Math.max(80,Math.min(12e3,(e.parsed?.lines.length??2)*19))}px`}
              >
                ${this.renderFileBody(e,t)}
              </div>`}
      </section>
    `}scopeTitle(e){let t=this.scope;if(t.scope===`uncommitted`)return m(`chat.sessionDiff.uncommitted`);if(t.scope===`commit`){let n=e.commits?.find(e=>e.sha===t.commit);return n?`${n.sha} ${n.subject}`:t.commit}return m(`chat.sessionDiff.allChanges`)}renderFooter(e){let t=e.branch??e.baseRef??m(`chat.sessionDiff.allChanges`),n=e.aheadCount&&e.baseRef?m(`chat.sessionDiff.commitsAhead`,{count:String(e.aheadCount),base:e.baseRef}):t;return x`<button
      class="session-diff__footer"
      type="button"
      aria-label=${m(`chat.sessionDiff.scopeMenu`)}
      @click=${t=>this.openAnchoredMenu(t,{kind:`scope`,active:this.scope,result:e},`top-start`)}
    >
      <span>${n}</span>${y.chevronUp}
    </button>`}renderBody(){if(this.diffTask.status===Ae.ERROR){let e=this.diffTask.error;return x`<div class="callout danger">${p(e)}</div>`}let e=this.diffTask.value;if(this.loading&&(!e||e.owner!==this.owner||e.scope!==this.scope))return Lt(`review`,m(`chat.sessionDiff.loading`));if(!e)return b;let{result:t,views:n}=e;return t.unavailableReason===`not_git`?x`<div class="session-diff__note">${m(`chat.sessionDiff.notGit`)}</div>`:t.unavailableReason===`unknown_session`?x`<div class="session-diff__note">${m(`chat.sessionDiff.unknownSession`)}</div>`:x`
      ${this.renderSummary(t)}
      ${t.unavailableReason===`workspace_stopped`?x`<div class="session-diff__note">${m(`chat.sessionDiff.workspaceStopped`)}</div>`:b}
      <button
        class="session-diff__section-title"
        type="button"
        aria-label=${m(`chat.sessionDiff.scopeMenu`)}
        @click=${e=>this.openAnchoredMenu(e,{kind:`scope`,active:this.scope,result:t},`bottom-start`)}
      >
        <span>${this.scopeTitle(t)}</span>${y.chevronDown}
      </button>
      <div class="session-diff__files">
        ${t.unavailableReason===`unknown_commit`?x`<div class="session-diff__note">${m(`chat.sessionDiff.unknownCommit`)}</div>`:t.files.length===0?t.unavailableReason===`workspace_stopped`||t.truncated===!0?b:x`<div class="session-diff__note">${m(`chat.sessionDiff.empty`)}</div>`:n.map(e=>this.renderFile(e,t))}
        ${t.truncated===!0?x`<div class="session-diff__note">${m(`chat.sessionDiff.truncatedResult`)}</div>`:b}
      </div>
      ${this.renderFooter(t)}
    `}render(){return x`
      <div
        class="session-diff ${this.wrap?`session-diff--wrap`:``}"
        aria-busy=${String(this.loading)}
      >
        ${this.renderBody()}
        ${this.menu?E(this.menu,x`<openclaw-session-diff-menu
                  .menu=${this.menu}
                  .onAction=${e=>this.handleMenuAction(e)}
                  .onClose=${()=>{this.menu=null}}
                ></openclaw-session-diff-menu>`):b}
      </div>
    `}},j([w({attribute:!1})],Q.prototype,`owner`,void 0),j([w({attribute:!1})],Q.prototype,`execNode`,void 0),j([w({attribute:!1})],Q.prototype,`loader`,void 0),j([w({attribute:!1})],Q.prototype,`loadFileText`,void 0),j([w({attribute:!1})],Q.prototype,`openFile`,void 0),j([w({attribute:!1})],Q.prototype,`revealFile`,void 0),j([O()],Q.prototype,`collapsedPaths`,void 0),j([O()],Q.prototype,`menu`,void 0),j([O()],Q.prototype,`scope`,void 0),j([O()],Q.prototype,`split`,void 0),j([O()],Q.prototype,`wrap`,void 0),customElements.get(`openclaw-session-diff`)||customElements.define(`openclaw-session-diff`,Q)})))()}function Cn(e,t,n,r,i){if(e.download&&i)return x`${L({kind:`document`,label:e.title,mimeType:e.mimeType??void 0,sizeBytes:e.sizeBytes,onDownload:i.onDownload,downloadPending:i.pending})}${i.error?x`<div role="alert">${i.error}</div>`:b}`;let a=e.resolveSource?.(t,n),o=a?a.status===`ready`?a:null:e,s=e.mimeType?.split(`;`,1)[0]?.trim().toLowerCase()??``,c=e.attachmentKind===`video`||s.startsWith(`video/`)?`video`:e.attachmentKind===`audio`||s.startsWith(`audio/`)?`audio`:e.attachmentKind===`image`||s.startsWith(`image/`)?`image`:`document`,l=(e.plainText?dt:c===`audio`||c===`video`?et:it)(o?.src??``),u=o?.authToken??null,d=a?.status===`pending`,ee=(s===`image/svg+xml`||(!s||s===`application/octet-stream`)&&(F(e.sourceIdentity??``,void 0)||F(l??``,void 0)||F(e.title,void 0)))&&R(l??``),f=(l||d)&&!ee&&c===`image`;if((l||d)&&c===`document`&&Xt(s,e.title)&&!R(l??``))return x`<openclaw-chat-pdf-preview
      .src=${l??``}
      .sourceIdentity=${[n.connectionEpoch??``,n.agentId??``,n.sessionKey??``,e.sourceIdentity??l??``].join(`\0`)}
      .label=${e.title}
      .mimeType=${e.mimeType??``}
      .sizeBytes=${o?.sizeBytes??e.sizeBytes}
    ></openclaw-chat-pdf-preview>`;if((l||d)&&$t(s,e.title)&&!R(l??``))return x`<openclaw-chat-text-attachment
      .plainText=${e.plainText??!1}
      .actions=${e.renderActions?.()??b}
      .embedSandboxMode=${r}
      .src=${l??``}
      .sourceIdentity=${[n.connectionEpoch??``,n.agentId??``,n.sessionKey??``,e.sourceIdentity??l??``].join(`\0`)}
      .label=${e.title}
      .mimeType=${e.mimeType??``}
      .sizeBytes=${o?.sizeBytes??e.sizeBytes}
    ></openclaw-chat-text-attachment>`;if(c===`video`&&(l||d))return x`<openclaw-chat-video-player
      .src=${l??``}
      .preview=${!0}
      .sourceIdentity=${e.sourceIdentity??e.src??l??``}
      .label=${e.title}
      .mimeType=${e.mimeType??``}
      .playback=${o?.playback??e.playback??`native`}
      .authToken=${u}
      .sizeBytes=${o?.sizeBytes??e.sizeBytes}
      .mediaWidth=${o?.width??e.width}
      .mediaHeight=${o?.height??e.height}
    ></openclaw-chat-video-player>`;if(!l||f){let t=o?.width??e.width,n=o?.height??e.height;return x`
      <div
        class="chat-assistant-attachment-card chat-assistant-attachment-card--${c} sidebar-attachment-preview__state-card"
        aria-busy=${d?`true`:b}
      >
        ${tt({kind:c,label:e.title,mimeType:e.mimeType??void 0,sizeBytes:o?.sizeBytes??e.sizeBytes,downloadHref:l??void 0,downloadPending:d,visualMode:`preview-with-favicon`})}
        <div
          class="sidebar-attachment-preview__state"
          style=${me({"--preview-ratio":t&&n?`${t} / ${n}`:void 0})}
        >
          ${d||f?z():b}
          ${f&&l?E(l,x`<img
                    class="sidebar-attachment-preview__image"
                    src=${l}
                    alt=${e.title}
                    .onload=${function(){this.dataset.preview=`ready`}}
                    .onerror=${function(){this.dataset.preview=`error`}}
                  />`):b}
          ${d?b:x`<div class="sidebar-attachment-preview__unavailable">
                  ${m(`chat.attachments.previewUnavailable`)}
                  ${a?.status===`error`?x`<span>${a.reason}</span>`:b}
                  ${(a?.status===`error`||a?.status===`unavailable`)&&a.onRetry?x`<button class="btn btn--sm" type="button" @click=${a.onRetry}>
                          ${m(`common.retry`)}
                        </button>`:b}
                </div>`}
        </div>
      </div>
    `}return c===`audio`?x`<openclaw-chat-audio-player
      .src=${l}
      .sourceIdentity=${e.sourceIdentity??e.src??l}
      .label=${e.title}
      .mimeType=${e.mimeType??``}
      .playback=${o?.playback??e.playback??`native`}
      .authToken=${u}
      .sizeBytes=${o?.sizeBytes??e.sizeBytes}
      .serverDurationMs=${o?.durationMs??e.durationMs}
      .voiceNote=${e.voiceNote===!0}
    ></openclaw-chat-audio-player>`:L({kind:e.attachmentKind??`document`,label:e.title,mimeType:e.mimeType??void 0,sizeBytes:o?.sizeBytes??e.sizeBytes,downloadHref:l})}function wn(e){if(!e)return null;let t=e.kind===`markdown`||e.kind===`file`,n=e.rawText??(t?e.content:``);return!t&&!n.trim()?null:{kind:`markdown`,content:yt(n,e.kind===`file`?e.language:t?void 0:`json`),rawText:n,...t?{fileLinkSessionKey:e.kind===`file`?e.sessionFileSource?.sessionKey:e.fileLinkSessionKey}:{}}}function Tn(e){let t=e.content,n=(t=`btn`,n)=>x`<button
    @click=${e.onViewRawText}
    class=${t}
    type="button"
    style=${n??b}
  >
    ${m(`chat.detailPanel.viewRawText`)}
  </button>`,r=t?.kind===`markdown`&&t.content.trim()?We(t.content,{codeBlockInteraction:`interactive`,fileLinks:!0,githubRepo:e.githubRepo??null,githubRepositories:e.githubRepositories,interactiveImages:e.onOpenImage!==void 0,sessionLinks:!0}):``,i=t?.kind===`canvas`?bt(e.embedSandboxMode??`scripts`,t.sandbox):``,a=t?.kind===`canvas`?xt(t.entryUrl,e.canvasPluginSurfaceUrl,e.allowExternalEmbedUrls??!1):null,o=t?.kind===`mcp-app`?t.title:t?.kind===`canvas`?t.title?.trim()||m(`chat.detailPanel.renderPreview`):t?.kind===`image`?t.title.trim()||m(`chat.detailPanel.imagePreview`):t?.kind===`attachment`?t.title.trim()||m(`chat.detailPanel.file`):t?.kind===`file`?t.name.trim()||m(`chat.detailPanel.file`):t?.kind===`session-diff`?m(`chat.sessionDiff.title`):t?.kind===`markdown`?m(e.showingRawText?`chat.detailPanel.viewSource`:`chat.detailPanel.markdownPreview`):m(`chat.detailPanel.toolDetails`);return x`
    <div
      class="sidebar-panel"
      data-file-session-key=${t?.kind===`markdown`?t.fileLinkSessionKey??b:t?.kind===`file`?t.sessionFileSource?.sessionKey??b:b}
    >
      ${e.embedded?b:x`<div class="sidebar-header">
              <div class="sidebar-title">${o}</div>
              <div class="sidebar-header__actions">
                <openclaw-tooltip .content=${m(`chat.detailPanel.close`)}>
                  <button
                    @click=${e.onClose}
                    class="btn"
                    type="button"
                    aria-label=${m(`chat.detailPanel.close`)}
                  >
                    ${y.x}
                  </button>
                </openclaw-tooltip>
              </div>
            </div> `}
      <div class="sidebar-content">
        ${e.error?x`
                ${v({error:e.error,stale:h(e.error),onRetry:e.onRetry})}
                ${t?.kind===`file`||t?.rawText?.trim()?n(`btn`,`margin-top: 12px;`):b}
              `:t?t.kind===`mcp-app`?x`<openclaw-mcp-app-panel .launch=${t.launch}></openclaw-mcp-app-panel>`:t.kind===`file`?Tt(t,e.onViewRawText,e.fileView,e.attachmentRuntime):t.kind===`session-diff`?x`<openclaw-session-diff
                        .owner=${t.owner}
                        .loader=${t.load}
                        .loadFileText=${t.loadFileText??null}
                        .execNode=${e.fileView?.execNode??null}
                        .openFile=${t.openFile??null}
                        .revealFile=${e.fileView?.onReveal??null}
                      ></openclaw-session-diff>`:t.kind===`canvas`||t.kind===`image`?E(t.kind,x`
                            <div class="chat-tool-card__preview" data-kind=${t.kind}>
                              <div class="chat-tool-card__preview-panel" data-side="front">
                                ${t.kind===`canvas`?E(`${i}\u0000${a??``}\u0000${t.preferredHeight??``}`,x`<iframe
                                          class="chat-tool-card__preview-frame"
                                          title=${o}
                                          sandbox=${i}
                                          src=${a??b}
                                          style=${t.preferredHeight?`height:${t.preferredHeight}px`:``}
                                        ></iframe>`):x`<button
                                        type="button"
                                        class="chat-tool-card__preview-image-button"
                                        aria-label=${m(`chat.imageLightbox.open`,{title:o})}
                                        @click=${()=>lt(e.onOpenImage,t.src,o)}
                                      >
                                        <img
                                          class="chat-tool-card__preview-image"
                                          src=${t.src}
                                          alt=${o}
                                          style="display:block;max-width:100%;height:auto;border-radius:8px;"
                                        />
                                      </button>`}
                              </div>
                              ${t.rawText?.trim()?x`
                                      <div style="margin-top: 12px;">${n()}</div>
                                    `:b}
                            </div>
                          `):t.kind===`attachment`?x`<div class="sidebar-attachment-preview">
                            ${Cn(t,e.onAttachmentUpdate,e.attachmentRuntime,e.embedSandboxMode??`scripts`,e.attachmentDownload)}
                          </div>`:x`
                            <section class="sidebar-markdown-shell">
                              <div class="sidebar-markdown-shell__toolbar">
                                <div class="sidebar-markdown-shell__intro">
                                  <div class="sidebar-markdown-shell__eyebrow">
                                    ${y.scrollText}
                                    <span
                                      >${m(e.showingRawText?`chat.detailPanel.viewSource`:`chat.detailPanel.renderedMarkdown`)}</span
                                    >
                                  </div>
                                  ${e.showingRawText?b:x`
                                          <div class="sidebar-markdown-shell__hint">
                                            ${m(`chat.detailPanel.renderedMarkdownHint`)}
                                          </div>
                                        `}
                                </div>
                                ${e.showingRawText?b:n(`btn btn--sm`)}
                              </div>
                              ${r?x`
                                      <article
                                        class="sidebar-markdown-reader sidebar-markdown"
                                        dir=${gt(t.content)}
                                      >
                                        ${ke(r)}
                                      </article>
                                    `:x`
                                      <div class="sidebar-markdown-empty">
                                        ${m(`chat.detailPanel.noPreviewableMarkdown`)}
                                      </div>
                                    `}
                            </section>
                          `:x` <div class="muted">${m(`chat.detailPanel.noContent`)}</div> `}
      </div>
    </div>
  `}function En(e){let t=e.content?.kind===`file`||e.content?.kind===`markdown`||e.content?.kind===`attachment`||e.content?.kind===`session-diff`;return x`
    <div
      class=${t?`sidebar-panel-host--fill`:``}
      ${e.content?.kind===`attachment`?b:zt()}
      @click=${e.onClick}
      @keydown=${e.onKeydown}
    >
      ${Tn(e)}
    </div>
  `}function Dn(e,t){if(at(e,t.onOpenImage??void 0))return;He(e);let r=Ue(e);if(r){t.onOpenWorkspaceFile?.(r);return}let i=Fe(e,t.basePath);i&&n(e)&&(e.preventDefault(),t.onOpenSessionLink?.(i))}function On(e,t){let n=Le(e);if(n){t.onOpenWorkspaceFile?.(n);return}let r=Je(e,t.basePath);r&&t.onOpenSessionLink?.(r)}function kn(){return(kn=e((()=>{S(),T(),pe(),Me(),g(),_(),ae(),Rt(),Re(),Ie(),Ye(),$e(),ne(),c(),V(),St(),ct(),ot(),I(),st(),nt(),vt(),Yt(),ht(),ft(),Qt(),Ot(),en(),Sn(),B()})))()}var $;function An(){return(An=e((()=>{Oe(),C(),Pe(),g(),c(),V(),A(),f(),s(),Vt(),Ut(),Et(),W(),rt(),kn(),Ot(),M(),B(),$=class extends d{constructor(){super(),this.content=null,this.fileNavigation=null,this.execNode=null,this.attachmentRuntime={},this.basePath=``,this.canvasPluginSurfaceUrl=null,this.embedSandboxMode=`scripts`,this.allowExternalEmbedUrls=!1,this.githubContext={},this.embedded=!1,this.onOpenWorkspaceFile=null,this.onOpenSessionLink=null,this.onRevealInWorkspace=null,this.onOpenImage=null,this.visibleContent=null,this.error=null,this.fileSearchOpen=!1,this.fileWrap=Nt(),this.fileSearchQuery=``,this.fileSearchMatchIndex=0,this.fileEditorMenuOpen=!1,this.fileCopy=new Ht(this,()=>this.visibleContent),this.fileEditorLoading=!1,this.fileEditing=!1,this.fileDirty=!1,this.fileReloading=!1,this.fileSaving=!1,this.fileSaveNotice=null,this.htmlPreview=new Kt(this,()=>this.visibleContent,()=>this.currentFileText()),this.fileOperationVersion=0,this.rawView=null,this.fileEditor=null,this.fileEditorLoad=null,this.fileDraftContent=null,this.fileSavedContent=``,this.fileHash=``,this.requestAttachmentUpdate=()=>this.requestUpdate(),this.attachmentDownload=new Bt(this,()=>this.content===this.visibleContent?this.content:null,()=>this.attachmentRuntime),this.toggleHtmlSource=()=>{this.fileSearchOpen=!1,this.htmlPreview.toggle()},this.retryFileEditor=()=>{let e=this.error,t=this.fileOperationVersion;h(e)?le({canReload:()=>this.isConnected&&this.error===e&&t===this.fileOperationVersion}):this.error=null},this.handleDocumentPointerDown=e=>{if(!this.fileEditorMenuOpen)return;let t=this.querySelector(`.sidebar-file-view__editor`);(!t||!e.composedPath().includes(t))&&(this.fileEditorMenuOpen=!1)},this.toggleFileWrap=()=>{this.fileWrap=!this.fileWrap,Ct(this.fileWrap)},this.toggleFileSearch=()=>{if(this.htmlPreview.showSource(),this.fileSearchOpen=!this.fileSearchOpen,this.fileEditorMenuOpen=!1,!this.fileSearchOpen){this.fileSearchQuery=``,this.fileSearchMatchIndex=0;return}this.updateComplete.then(()=>{this.querySelector(`.file-view__search input`)?.focus()})},this.updateFileSearch=e=>{this.fileSearchQuery=e,this.fileSearchMatchIndex=0,this.scrollToCurrentFileMatch()},this.handleFileSearchKeydown=e=>{if(e.key===`Escape`){e.preventDefault(),e.stopPropagation(),this.toggleFileSearch(),this.querySelector(`.sidebar-file-view__search-toggle`)?.focus({preventScroll:!0});return}e.key===`Enter`&&e.target instanceof HTMLInputElement&&(e.preventDefault(),this.moveFileSearch(e.shiftKey?-1:1))},this.openInEditor=e=>{let t=this.visibleContent;if(t?.kind!==`file`)return;let n=Be(t,this.execNode);n&&(this.fileEditorMenuOpen=!1,be(e,n,this.fileNavigation?.line??t.line))},this.editFile=async()=>{let e=this.visibleContent;if(e?.kind===`file`&&e.edit&&(this.htmlPreview.showSource(),await this.updateComplete,await this.ensureFileEditor(),this.visibleContent===e&&this.fileEditor)){if(this.fileEditing){this.fileEditor.focus();return}this.fileSavedContent=e.content,this.fileHash=e.edit.hash,this.fileDirty=!1,this.fileSaveNotice=null,this.fileSearchOpen=!1,this.fileSearchQuery=``,this.fileSearchMatchIndex=0,this.fileEditorMenuOpen=!1,this.fileEditing=!0,this.fileEditor.setEditable(!0),this.updateComplete.then(()=>this.fileEditor?.focus())}},this.discardFileEdits=()=>{if(!this.fileEditing||this.fileSaving)return;this.fileEditor?.setContent(this.fileSavedContent),this.fileDraftContent=null,this.htmlPreview.discard(this.fileSavedContent);let e=this.visibleContent;e?.kind===`file`&&(H(e,null),this.fileHash=e.edit?.hash??``),this.fileDirty=!1,this.fileSaveNotice=null,this.fileEditing=!1,this.fileEditor?.setEditable(!1)},this.saveFile=()=>{let e=this.visibleContent;if(e?.kind!==`file`||!e.edit||!this.fileEditing||!this.fileDirty||this.fileSaving)return;let t=this.fileOperationVersion;this.fileSaving=!0,this.fileSaveNotice=null,this.trackFileOperation(this.saveFileContent(e,this.currentFileText(),this.fileHash,t),t)},this.reloadFile=()=>this.startLatestFileOperation(`reload`),this.overwriteFile=()=>this.startLatestFileOperation(`overwrite`),this.close=()=>{this.dispatchEvent(new CustomEvent(`chat-detail-panel-close`,{bubbles:!0}))},this.showRawText=()=>{if(this.htmlPreview.file){this.htmlPreview.showSource();return}let e=wn(this.visibleContent);e&&(this.rawView={file:this.visibleContent?.kind===`file`?this.visibleContent:null},this.destroyFileEditor(),this.visibleContent=e,this.error=null)},this.handlePanelClick=e=>{Dn(e,this)},this.handlePanelKeyDown=e=>{On(e,this)},Ve(this)}connectedCallback(){super.connectedCallback(),document.addEventListener(`pointerdown`,this.handleDocumentPointerDown)}disconnectedCallback(){this.attachmentDownload.cancel(),document.removeEventListener(`pointerdown`,this.handleDocumentPointerDown),this.fileDirty&&(this.fileDraftContent=this.currentFileText()),this.destroyFileEditor(),P(this.requestAttachmentUpdate),super.disconnectedCallback()}willUpdate(e){let t=e.get(`attachmentRuntime`);if(t&&typeof t==`object`&&`connectionEpoch`in t&&t.connectionEpoch!==this.attachmentRuntime.connectionEpoch&&(P(this.requestAttachmentUpdate),this.attachmentDownload.cancel()),e.has(`fileNavigation`)&&this.fileNavigation&&this.content?.kind===`file`&&this.htmlPreview.showSource(),!e.has(`content`)){if(e.has(`fileNavigation`)&&this.fileNavigation&&this.content?.kind===`file`&&this.rawView){let e=this.rawView.file??this.content;this.rawView=null,this.visibleContent=e}return}P(this.requestAttachmentUpdate),this.attachmentDownload.cancel(),this.visibleContent=this.content,this.error=null,this.rawView=null,this.fileSearchOpen=!1,this.fileSearchQuery=``,this.fileSearchMatchIndex=0,this.fileEditorMenuOpen=!1,this.fileCopy.reset(),this.fileOperationVersion+=1,this.fileReloading=!1,this.fileSaving=!1,this.fileSaveNotice=null;let n=this.content?.kind===`file`&&this.content.edit?wt(this.content):void 0,r=this.content?.kind===`file`&&n?.content!==this.content.content?n:void 0;n&&!r&&this.content?.kind===`file`&&H(this.content,null),this.fileDraftContent=r?.content??null,this.fileSavedContent=this.content?.kind===`file`?this.content.content:``,this.fileHash=r?.expectedHash??(this.content?.kind===`file`?this.content.edit?.hash??``:``),this.fileEditing=!!r,this.fileDirty=!!r,this.htmlPreview.reset(this.fileDraftContent,!!(this.fileNavigation||this.content?.kind===`file`&&this.content.line!=null)),this.fileEditorLoading=this.content?.kind===`file`&&!this.htmlPreview.showing,this.destroyFileEditor()}updated(e){let t=this.visibleContent;t?.kind===`file`&&!this.rawView&&!this.htmlPreview.showing&&!this.error&&this.ensureFileEditor().then(()=>{this.syncFileEditor(),(e.has(`content`)||e.has(`fileNavigation`))&&(this.fileNavigation?.line??t.line)!=null&&this.scrollToFileLine(t)})}currentFileText(){return this.fileEditor?.getContent()??this.fileDraftContent??(this.visibleContent?.kind===`file`?this.visibleContent.content:``)}scrollToFileLine(e){let t=this.fileNavigation?.line??e.line;this.visibleContent===e&&!this.rawView&&t!=null&&this.fileEditor?.scrollToLine(t,!0)}destroyFileEditor(){this.fileOperationVersion+=1,this.fileEditor?.destroy(),this.fileEditor=null,this.fileEditorLoad=null}ensureFileEditor(){if(this.fileEditor)return Promise.resolve();if(this.fileEditorLoad)return this.fileEditorLoad;let e=this.visibleContent,t=this.querySelector(`.file-view__mount`);if(e?.kind!==`file`||!t||this.htmlPreview.showing)return Promise.resolve();let n=this.fileOperationVersion;return this.fileEditorLoading=!0,this.fileEditorLoad=N(async()=>{let{createFileEditorView:e}=await import(`./file-editor-view-Bh_qvyOa.js`);return{createFileEditorView:e}},__vite__mapDeps([27,28,29,1,2,17]),import.meta.url).then(async({createFileEditorView:e})=>{let r=this.visibleContent;if(n!==this.fileOperationVersion||r?.kind!==`file`)return;let i=await e({parent:t,content:this.fileDraftContent??r.content,name:r.name,editable:this.fileEditing,wrap:this.fileWrap,onSave:this.saveFile});if(n!==this.fileOperationVersion||!this.isConnected||this.visibleContent?.kind!==`file`){i.destroy();return}i.setContent(this.currentFileText()),this.fileEditor=i,this.fileDraftContent=null,i.onDocChanged(e=>{let t=Mt(r,{editing:this.fileEditing&&!this.fileReloading,content:e,dirty:!i.contentEquals(this.fileSavedContent),expectedHash:this.fileHash});t&&(this.fileDirty=t.dirty,this.fileHash=t.expectedHash,this.fileSaveNotice?.kind===`error`&&(this.fileSaveNotice=null))})}).catch(e=>{n===this.fileOperationVersion&&this.isConnected&&(this.error=Te(e,m(`lazyView.errorTitle`)),h(this.error)&&re())}).finally(()=>{n===this.fileOperationVersion&&(this.fileEditorLoad=null,this.fileEditorLoading=!1)}),this.fileEditorLoad}syncFileEditor(){let e=this.visibleContent,t=this.fileEditor;if(e?.kind!==`file`||!t)return;this.fileEditing||t.setContent(e.content),t.setEditable(this.fileEditing&&!this.fileReloading),t.setLineWrapping(this.fileWrap);let n=this.fileSearchMatches();t.setDecorations({targetLine:this.fileNavigation?.line??e.line,matches:n,currentMatch:n[this.fileSearchMatchIndex]??null})}fileSearchMatches(){let e=this.visibleContent;return e?.kind===`file`?Pt(e.content,this.fileSearchQuery):[]}async scrollToCurrentFileMatch(){await this.updateComplete;let e=this.fileSearchMatches()[this.fileSearchMatchIndex];e!=null&&this.fileEditor?.scrollToLine(e,!0)}moveFileSearch(e){let t=this.fileSearchMatches();t.length!==0&&(this.fileSearchMatchIndex=(this.fileSearchMatchIndex+e+t.length)%t.length,this.scrollToCurrentFileMatch())}updateSavedFile(e,t,n){let r=this.currentFileText();this.fileSavedContent=t,this.fileHash=n,this.fileDirty=!(this.fileEditor?.contentEquals(t)??r===t),this.fileDraftContent=!this.fileEditor&&this.fileDirty?r:null,H(e,this.fileDirty?{content:r,expectedHash:n}:null),this.fileSaveNotice=null,e.content=t,e.rawText=t,e.edit&&(e.edit.hash=n)}async saveFileContent(e,t,n,r){if(!e.edit)return;let i=await e.edit.save({content:t,expectedHash:n});r===this.fileOperationVersion&&this.visibleContent?.kind===`file`&&(i.ok?this.updateSavedFile(this.visibleContent,t,i.hash):this.fileSaveNotice=i.code===`conflict`?{kind:`conflict`}:{kind:`error`,message:i.message})}startLatestFileOperation(e){let t=this.visibleContent;if(t?.kind!==`file`||!t.edit||this.fileSaving)return;let n=this.fileOperationVersion,r;if(e===`reload`)this.fileSaving=!0,this.fileReloading=!0,this.fileEditor?.setEditable(!1),r=e=>{if(n===this.fileOperationVersion&&this.visibleContent?.kind===`file`){if(!e){this.fileSaveNotice={kind:`error`,message:m(`chat.detailPanel.reloadFailed`)};return}if(this.fileEditor?.setContent(e.content),this.fileDraftContent=this.fileEditor?null:e.content,this.htmlPreview.discard(e.content),this.updateSavedFile(this.visibleContent,e.content,e.hash),!e.editable&&this.visibleContent?.kind===`file`){H(this.visibleContent,null),this.fileEditing=!1,this.fileDirty=!1;let{edit:e,...t}=this.visibleContent;this.visibleContent=t}}};else{let e=this.currentFileText();this.fileSaving=!0,r=async r=>{if(n===this.fileOperationVersion){if(!r){this.fileSaveNotice={kind:`error`,message:m(`chat.detailPanel.overwriteLoadFailed`)};return}await this.saveFileContent(t,e,r.hash,n)}}}this.trackFileOperation(t.edit.fetchLatest().then(r),n)}trackFileOperation(e,t){e.catch(e=>{t===this.fileOperationVersion&&(this.fileSaveNotice={kind:`error`,message:p(e)})}).finally(()=>{t===this.fileOperationVersion&&(this.fileSaving=!1,this.fileReloading&&(this.fileReloading=!1,this.fileEditor?.setEditable(this.fileEditing)))})}render(){let e=this.htmlPreview.file,t=this.fileSearchMatches(),n=t.length?Math.min(this.fileSearchMatchIndex,t.length-1):0;return En({content:this.visibleContent,showingRawText:!!this.rawView,error:e?null:this.error,onRetry:this.retryFileEditor,fileView:{htmlPreview:this.htmlPreview.controls({error:this.error,onRetry:this.retryFileEditor,onToggle:this.toggleHtmlSource,runtime:this.attachmentRuntime,mode:this.embedSandboxMode}),copyFeedback:this.fileCopy.feedback,currentMatchIndex:n,dirty:this.fileDirty,execNode:this.execNode,editorMenuOpen:this.fileEditorMenuOpen,editing:this.fileEditing,loadingEditor:this.fileEditorLoading,mountKey:this.fileOperationVersion,matches:t,query:this.fileSearchQuery,saveNotice:this.fileSaveNotice,saving:this.fileSaving,searchOpen:this.fileSearchOpen,wrap:this.fileWrap,onCopy:this.fileCopy.copy,onDiscard:this.discardFileEdits,onEdit:()=>void this.editFile(),onNextMatch:()=>this.moveFileSearch(1),onOpenEditor:this.openInEditor,onOverwrite:this.overwriteFile,onPreviousMatch:()=>this.moveFileSearch(-1),onReload:this.reloadFile,onReveal:this.onRevealInWorkspace??void 0,onSave:this.saveFile,onSearchInput:this.updateFileSearch,onSearchKeydown:this.handleFileSearchKeydown,onEditorMenuOpenChange:e=>{this.fileEditorMenuOpen=e},onToggleSearch:this.toggleFileSearch,onToggleWrap:this.toggleFileWrap},canvasPluginSurfaceUrl:this.canvasPluginSurfaceUrl,embedSandboxMode:this.embedSandboxMode,allowExternalEmbedUrls:this.allowExternalEmbedUrls,...this.githubContext,embedded:this.embedded,onClose:this.close,onOpenImage:this.onOpenImage??void 0,onViewRawText:this.showRawText,onClick:this.handlePanelClick,onKeydown:this.handlePanelKeyDown,onAttachmentUpdate:this.requestAttachmentUpdate,attachmentRuntime:this.attachmentRuntime,attachmentDownload:this.attachmentDownload})}},j([w({attribute:!1})],$.prototype,`content`,void 0),j([w({attribute:!1})],$.prototype,`fileNavigation`,void 0),j([w({attribute:!1})],$.prototype,`execNode`,void 0),j([w({attribute:!1})],$.prototype,`attachmentRuntime`,void 0),j([w()],$.prototype,`basePath`,void 0),j([w()],$.prototype,`canvasPluginSurfaceUrl`,void 0),j([w()],$.prototype,`embedSandboxMode`,void 0),j([w({type:Boolean})],$.prototype,`allowExternalEmbedUrls`,void 0),j([w({attribute:!1})],$.prototype,`githubContext`,void 0),j([w({type:Boolean})],$.prototype,`embedded`,void 0),j([w({attribute:!1})],$.prototype,`onOpenWorkspaceFile`,void 0),j([w({attribute:!1})],$.prototype,`onOpenSessionLink`,void 0),j([w({attribute:!1})],$.prototype,`onRevealInWorkspace`,void 0),j([w({attribute:!1})],$.prototype,`onOpenImage`,void 0),j([O()],$.prototype,`visibleContent`,void 0),j([O()],$.prototype,`error`,void 0),j([O()],$.prototype,`fileSearchOpen`,void 0),j([O()],$.prototype,`fileWrap`,void 0),j([O()],$.prototype,`fileSearchQuery`,void 0),j([O()],$.prototype,`fileSearchMatchIndex`,void 0),j([O()],$.prototype,`fileEditorMenuOpen`,void 0),j([O()],$.prototype,`fileEditorLoading`,void 0),j([O()],$.prototype,`fileEditing`,void 0),j([O()],$.prototype,`fileDirty`,void 0),j([O()],$.prototype,`fileReloading`,void 0),j([O()],$.prototype,`fileSaving`,void 0),j([O()],$.prototype,`fileSaveNotice`,void 0),customElements.get(`openclaw-chat-detail-panel`)||customElements.define(`openclaw-chat-detail-panel`,$)})))()}An();