openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
192 lines • 15.6 kB
JavaScript
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{wr as t}from"./control-ui-foundation-Cydpkyqa.js";import{E as n,Sc as r,T as i,an as a,b as o,bc as s,in as c,k as l,rn as u}from"./control-ui-core-Rwzhj6nO.js";import{$ as d,C as f,K as p,X as m,at as h,b as g,q as _,r as v,st as y,t as b}from"./lit-runtime-CV_MH99K.js";import{Gt as x,Ht as S,Wt as C,Yt as w,Z as T,en as E}from"./control-ui-core-vvcQQV2m.js";import{dn as D,un as O}from"./control-ui-boot-shared-DfZ39Yj9.js";import{cn as k,ln as A,sn as j,un as M}from"./control-ui-boot-chat-_QSl8fbH.js";import{Go as N,Ko as P}from"./control-ui-boot-shared-CXVvK2AW.js";function F(e){return e.digest?e.running?e.activeRunId&&e.digest.runId===e.activeRunId?e.digest:null:e.digest:null}function I(e,t){return(e.health===`done`||e.health===`failed`)&&(t??0)<e.updatedAt}function L(e){return E(`chat.rail.health.${e}`)}function R(e){return E(`chat.pullRequests.${e===`draft`?`draft`:e}`)}function z(e){let t=e.checks;return t?t.state===`passing`?E(`chat.rail.checksPassing`,{count:String(t.passed)}):t.state===`failing`?E(`chat.rail.checksFailing`,{count:String(t.failed)}):E(`chat.rail.checksPending`,{count:String(t.running)}):null}function B(e){return e.exchanges.length>0||e.pendingQuestion!==null||e.failedQuestion!==null||e.draft.length>0}function V(e){return W[e]}var H,U,W,G;function K(){return(K=e((()=>{p(),d(),g(),b(),x(),O(),A(),j(),S(),T(),w(),l(),P(),r(),u(),H=class{constructor(e=c()){this.displayPreference=e,this.autoExpandedRunIds=new Set,this.autoExpandedRunId=null,this.transientExpanded=!1,this.manualOpen=!1}resetTransientState(){this.transientExpanded=!1,this.autoExpandedRunId=null,this.manualOpen=!1}tryAutoOpen(){return this.displayPreference!==`off`&&(this.transientExpanded=!0,!0)}mode(e){let t=F(e),n=t!==null&&(e.running||I(t,e.lastReadAt))||e.hasCompanionActivity||this.manualOpen||this.transientExpanded;if(this.displayPreference===`off`||!n)return this.autoExpandedRunId=null,`hidden`;let r=e.activeRunId??t?.runId??null;return(t?.health===`stuck`||t?.health===`waiting-on-user`)&&r&&!this.autoExpandedRunIds.has(r)&&(this.autoExpandedRunIds.add(r),this.autoExpandedRunId=r),this.displayPreference===`card`||this.transientExpanded||r!==null&&this.autoExpandedRunId===r?`expanded`:`pill`}expand(){this.displayPreference=`card`,this.transientExpanded=!1,this.autoExpandedRunId=null,a(`card`)}collapse(){this.displayPreference=`pill`,this.transientExpanded=!1,this.autoExpandedRunId=null,this.manualOpen=!1,a(`pill`)}hide(){this.displayPreference=`off`,this.resetTransientState(),a(`off`)}openExplicitly(){this.displayPreference=`pill`,this.transientExpanded=!0,this.autoExpandedRunId=null,this.manualOpen=!0,a(`pill`)}},U=[`changed`,`stopped`,`remaining`],W={busy:`chat.rail.askBusy`,"history-unavailable":`chat.rail.askHistoryUnavailable`,missing:`chat.rail.askMissing`,"model-unavailable":`chat.rail.askModelUnavailable`,"rate-limited":`chat.rail.askRateLimited`,unavailable:`chat.rail.askUnavailable`},G=class extends s{constructor(...e){super(...e),this.sessionKey=``,this.digest=null,this.running=!1,this.activeRunId=null,this.pullRequests=[],this.companion={exchanges:[],loading:!1,pendingQuestion:null,failedQuestion:null,hint:null,retryable:!1,draft:``},this.connected=!1,this.command=null,this.consumedCommandGeneration=0,this.embedded=!1,this.now=Date.now(),this.railState=new H,this.clock=null,this.renderedMode=`hidden`,this.reportedMode=null,this.terminalAgeReference=Date.now()}disconnectedCallback(){this.stopClock(),super.disconnectedCallback()}willUpdate(e){e.has(`sessionKey`)&&(this.terminalAgeReference=Date.now(),this.railState.resetTransientState()),e.has(`digest`)&&this.digest&&(this.digest.health===`done`||this.digest.health===`failed`)&&(this.terminalAgeReference=Date.now()),e.has(`command`)&&this.applyPaneCommand()}applyPaneCommand(){let e=this.command;if(!(!e||e.generation<=this.consumedCommandGeneration)){if(this.onCommandConsumed?.(e.generation),e.intent===`open`){this.railState.tryAutoOpen()&&this.onVisibilityChange?.(!0);return}if(this.renderedMode===`expanded`){this.railState.collapse();return}this.railState.openExplicitly(),this.onVisibilityChange?.(!0)}}updated(){this.running&&this.startedAt!=null&&F(this.input())?this.scheduleClock():this.stopClock(),this.reportedMode!==this.renderedMode&&(this.reportedMode=this.renderedMode,this.onModeChange?.(this.renderedMode))}input(){return{running:this.running,activeRunId:this.activeRunId,digest:this.digest,lastReadAt:this.lastReadAt,hasCompanionActivity:B(this.companion)}}scheduleClock(){this.clock===null&&(this.clock=globalThis.setTimeout(()=>{this.clock=null,this.now=Date.now()},1e3))}stopClock(){this.clock!==null&&(globalThis.clearTimeout(this.clock),this.clock=null)}collapse(){this.railState.collapse(),this.requestUpdate()}expand(){this.railState.expand(),this.requestUpdate()}hide(){this.railState.hide(),this.onVisibilityChange?.(!1),this.requestUpdate()}submit(){let e=this.companion.draft.trim();!e||!this.connected||this.companion.pendingQuestion||!this.onSubmit||this.onSubmit(e)}renderStatus(e){let t=e.health===`done`||e.health===`failed`,n=e.health===`stuck`||e.health===`waiting-on-user`;return m`
<span
class="chat-session-rail__status ${n?`chat-session-rail__status--critical`:``}"
data-health=${e.health}
>
${t?m`<span class="chat-session-rail__status-icon" aria-hidden="true"
>${e.health===`done`?C.check:C.x}</span
>`:m`<span class="chat-session-rail__status-dot" aria-hidden="true"></span>`}
<span>${L(e.health)}</span>
</span>
`}renderPullRequests(){let e=this.pullRequests.slice(0,2);return e.length===0?_:m`
<div class="chat-session-rail__prs" aria-label=${E(`chat.rail.pullRequests`)}>
${e.map(e=>{let t=z(e);return m`
<a
class="chat-session-rail__pr"
href=${e.url}
target="_blank"
rel="noopener noreferrer"
title=${e.title}
>
<span>#${e.number}</span>
<span>${R(e.state)}</span>
${t?m`<span class="chat-session-rail__pr-checks">${t}</span>`:_}
</a>
`})}
</div>
`}renderDigestDetails(e){return e?m`
${e.assessment?m`<p class="chat-session-rail__assessment">${e.assessment}</p>`:_}
${this.renderPullRequests()}
`:_}renderExchange(e,t,r){return m`
<article class="chat-session-rail__exchange">
<div class="chat-session-rail__question" dir=${N(e)}>
${e}
</div>
<div class="chat-session-rail__answer" dir=${N(t)}>
${v(D(t))}
</div>
<time class="chat-session-rail__timestamp" datetime=${new Date(r).toISOString()}>
${E(`chat.rail.asOf`,{time:n(r,{hour:`numeric`,minute:`2-digit`},``)})}
</time>
</article>
`}renderStarters(){let e=!this.connected||this.companion.pendingQuestion!==null;return m`
<div class="chat-session-rail__starters">
${U.map(t=>{let n=E(`chat.rail.starters.${t}`);return m`
<button
class="chip chat-session-rail__starter"
type="button"
?disabled=${e}
=${()=>this.onSubmit?.(n)}
>
${C.spark}<span>${n}</span>
</button>
`})}
</div>
`}renderThread(){let e=`${this.companion.exchanges.length}:${this.companion.pendingQuestion??``}:${this.companion.failedQuestion??``}`;return m`
<div class="chat-session-rail__thread" aria-live="polite" ${f(t=>{!(t instanceof HTMLElement)||t.dataset.railScrollKey===e||(t.dataset.railScrollKey=e,t.scrollTop=t.scrollHeight)})}>
${this.companion.loading&&this.companion.exchanges.length===0?k(`chat`,E(`chat.thread.loading`)):_}
${!this.companion.loading&&this.companion.exchanges.length===0&&!this.companion.pendingQuestion?M({icon:C.bot,heading:E(`chat.sidePanel.companion`),description:E(`chat.rail.empty`)}):_}
${this.companion.exchanges.map(e=>this.renderExchange(e.question,e.answer,e.ts))}
${this.companion.failedQuestion&&this.companion.hint?m`
<article class="chat-session-rail__exchange chat-session-rail__exchange--error">
<div class="chat-session-rail__question">${this.companion.failedQuestion}</div>
<div class="chat-session-rail__hint">
${E(V(this.companion.hint))}
</div>
${this.companion.retryable&&this.connected&&this.onSubmit?m`
<button
class="btn btn--secondary chat-session-rail__retry"
type="button"
=${()=>this.onSubmit?.(this.companion.failedQuestion??``)}
>
${E(`chat.rail.askRetry`)}
</button>
`:_}
</article>
`:_}
${this.companion.pendingQuestion?m`
<article class="chat-session-rail__exchange chat-session-rail__exchange--pending">
<div class="chat-session-rail__question">${this.companion.pendingQuestion}</div>
<div class="chat-session-rail__hint">${E(`chat.rail.askPending`)}</div>
</article>
`:_}
</div>
`}render(){let e=this.input(),t=this.embedded?`expanded`:this.railState.mode(e);if(this.renderedMode=t,t===`hidden`)return _;let n=F(e);if(t===`pill`)return m`
<div class="chat-session-rail chat-session-rail--pill" aria-live="polite">
${n?this.renderStatus(n):_}
<button
class="chat-session-rail__expand"
type="button"
aria-label=${E(`chat.rail.expand`)}
=${()=>this.expand()}
>
<span class="chat-session-rail__headline"
>${n?.headline??E(`chat.rail.title`)}</span
>
</button>
<button
class="btn btn--ghost btn--icon chat-icon-btn chat-session-rail__hide"
type="button"
aria-label=${E(`chat.rail.close`)}
=${()=>this.hide()}
>
${C.x}
</button>
<button
class="btn btn--ghost btn--icon chat-icon-btn chat-session-rail__toggle"
type="button"
aria-label=${E(`chat.rail.expand`)}
=${()=>this.expand()}
>
${C.chevronDown}
</button>
</div>
`;let r=this.running&&this.startedAt!=null?o(Math.max(0,this.now-this.startedAt)):null,a=n&&(n.health===`done`||n.health===`failed`)?E(`chat.rail.finished`,{time:i(Math.max(0,this.terminalAgeReference-n.updatedAt))}):null;return m`
<section
class="chat-session-rail chat-session-rail--expanded ${this.embedded?`chat-session-rail--embedded`:``}"
role="region"
aria-label=${E(`chat.rail.title`)}
tabindex="-1"
=${e=>{!this.embedded&&e.key===`Escape`&&(e.preventDefault(),e.stopPropagation(),this.collapse())}}
>
${this.embedded?_:m`<header class="rail-header chat-session-rail__header">
<div class="rail-header__copy chat-session-rail__header-copy">
<div class="chat-session-rail__status-row">
${n?this.renderStatus(n):m`<strong>${E(`chat.rail.title`)}</strong>`}
${r?m`<span class="chat-session-rail__timing">${r}</span>`:a?m`<span class="chat-session-rail__timing">${a}</span>`:_}
</div>
${n?m`<strong class="chat-session-rail__headline"
>${n.headline}</strong
>`:m`<span class="chat-session-rail__subtitle"
>${E(`chat.rail.subtitle`)}</span
>`}
</div>
<div class="rail-header__actions chat-session-rail__actions">
<button
class="rail-header__action chat-session-rail__hide"
type="button"
aria-label=${E(`chat.rail.close`)}
=${()=>this.hide()}
>
${C.x}
</button>
<button
class="rail-header__action chat-session-rail__toggle"
type="button"
aria-label=${E(`chat.rail.collapse`)}
=${()=>this.collapse()}
>
${C.chevronUp}
</button>
</div>
</header>`}
${n?m`<div class="chat-session-rail__digest">${this.renderDigestDetails(n)}</div>`:_}
${this.renderThread()}
${this.companion.exchanges.length===0&&!this.companion.pendingQuestion?this.renderStarters():_}
<form
class="agent-chat__input chat-session-rail__composer"
=${e=>{e.preventDefault(),this.submit()}}
>
<div class="agent-chat__composer-input-row">
<label class="agent-chat__composer-combobox chat-session-rail__prompt">
<input
class="chat-session-rail__input"
type="text"
maxlength="400"
autocomplete="off"
aria-label=${E(`chat.rail.askLabel`)}
.value=${this.companion.draft}
placeholder=${this.companion.pendingQuestion?E(`chat.rail.askPending`):E(`chat.rail.askPlaceholder`)}
?disabled=${!this.connected||this.companion.pendingQuestion!==null}
=${e=>{this.onDraftChange?.(e.currentTarget.value)}}
/>
</label>
</div>
<div class="agent-chat__composer-footer">
<div class="agent-chat__composer-trail">
<div class="agent-chat__composer-actions">
<button
class="chat-send-btn"
type="submit"
aria-label=${E(`chat.rail.askSubmit`)}
?disabled=${!this.connected||this.companion.pendingQuestion!==null||!this.companion.draft.trim()}
>
${C.arrowUp}
</button>
</div>
</div>
</div>
</form>
</section>
`}},t([y({attribute:!1})],G.prototype,`sessionKey`,void 0),t([y({attribute:!1})],G.prototype,`digest`,void 0),t([y({attribute:!1})],G.prototype,`running`,void 0),t([y({attribute:!1})],G.prototype,`activeRunId`,void 0),t([y({attribute:!1})],G.prototype,`startedAt`,void 0),t([y({attribute:!1})],G.prototype,`lastReadAt`,void 0),t([y({attribute:!1})],G.prototype,`pullRequests`,void 0),t([y({attribute:!1})],G.prototype,`companion`,void 0),t([y({attribute:!1})],G.prototype,`connected`,void 0),t([y({attribute:!1})],G.prototype,`command`,void 0),t([y({attribute:!1})],G.prototype,`consumedCommandGeneration`,void 0),t([y({attribute:!1})],G.prototype,`onCommandConsumed`,void 0),t([y({attribute:!1})],G.prototype,`onSubmit`,void 0),t([y({attribute:!1})],G.prototype,`onDraftChange`,void 0),t([y({attribute:!1})],G.prototype,`onModeChange`,void 0),t([y({attribute:!1})],G.prototype,`onVisibilityChange`,void 0),t([y({type:Boolean})],G.prototype,`embedded`,void 0),t([h()],G.prototype,`now`,void 0),customElements.get(`openclaw-chat-session-rail`)||customElements.define(`openclaw-chat-session-rail`,G)})))()}K();export{G as ChatSessionRailElement,H as ChatSessionRailState};
//# sourceMappingURL=chat-session-rail-BFM_PgRc.js.map