openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
100 lines • 14.5 kB
JavaScript
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{R as t,wr as n,z as r}from"./control-ui-foundation-Cydpkyqa.js";import{As as i,Bi as a,Bn as o,C as ee,Do as s,Eo as c,Hi as l,J as u,Ls as d,Oo as f,Sc as te,Ui as p,Vi as ne,Vs as re,Wi as m,bc as ie,cn as ae,k as oe,w as se,wn as ce,zi as le,zn as ue}from"./control-ui-core-Rwzhj6nO.js";import{$ as h,K as g,X as _,at as v,h as de,m as fe,q as y}from"./lit-runtime-CV_MH99K.js";import{An as pe,_ as me,_n as he,cn as ge,en as b,g as x,jn as S,nn as C,sn as w,tn as T}from"./control-ui-core-YphAl4aM.js";import{Yt as E,en as D}from"./control-ui-core-vvcQQV2m.js";import{B as O,U as k,V as A,z as j}from"./control-ui-boot-shared-BYq7Cchl.js";import{Uo as M}from"./control-ui-boot-shared-DfZ39Yj9.js";import{At as N,Ct as P,Dt as F,Et as I,K as L,L as R,Mt as _e,Nt as ve,Q as ye,St as z,Tt as B,V,X as be,_t as H,bt as U,jt as xe,kt as Se,q as Ce,vt as W,wt as we}from"./control-ui-boot-chat-_QSl8fbH.js";import{Is as Te,Ls as Ee}from"./control-ui-boot-shared-CXVvK2AW.js";import{n as De,t as Oe}from"./settings-workspace-Bseic8Tf.js";import{n as ke,t as Ae}from"./agent-scope-control-6x2VZZ2e.js";function je(e,t){let n=e.childSessionKey??e.sessionKey;if(!n)return y;let r=t.sessionRow(n),i=m({face:l(r),sessionKey:n,fallbackAgentId:t.agentId,basePath:t.basePath,mainKey:t.mainKey,row:r,preferenceDerivedFace:!0}).href;return _`<a
class="session-link"
href=${i}
=${e=>{u(e)&&(e.preventDefault(),t.onNavigateToChat(n))}}
>${D(`tasksPage.openSession`)}</a
>`}function Me(e,t){let n=e.status===`queued`||e.status===`running`,r=_e(e.updatedAt??e.createdAt),i=Se(e),a=ve(e),o=t.cancellingTaskIds.has(e.id),s=e.terminalOutcome===`blocked`,c=s&&e.deliveryStatus===`failed`,l=s&&e.deliveryStatus===`dismissed`,u=n&&t.canCancel||s&&t.canCopy||c&&t.canCancel;return _`
<div class="settings-row task-row" data-task-id=${e.id}>
<div class="settings-row__text task-row__content">
<div class="settings-row__title">${a}</div>
<div class="task-row__facts">
<span data-task-status
>${ye({kind:Ne(e.status),label:xe(e.status)})}</span
>
<span>${N(e)}</span>
${e.agentId?_`<span>${D(`tasksPage.agent`,{agent:e.agentId})}</span>`:y}
</div>
${i?_`<div class="settings-row__desc">${i}</div>`:y}
${s?_`<div class="task-row__warning">
<span
>${D(l?`tasksPage.deliveryDismissed`:`tasksPage.deliveryBlocked`)}</span
>
${c?_`<span class="muted">${D(`tasksPage.duplicateRisk`)}</span>`:y}
</div>`:y}
</div>
<div class="settings-row__control task-row__control">
<div class="task-row__links">
${r>0?_`<span title=${ee(r)}
>${se(r)}</span
>`:_`<span>${D(`common.na`)}</span>`}
${je(e,t)}
</div>
${u?_`<div class="task-row__actions">
${n&&t.canCancel?_`<button
class="btn btn--sm"
type="button"
aria-label=${D(`tasksPage.cancelTask`,{title:a})}
?disabled=${o||!t.connected}
=${()=>t.onCancel(e.taskId)}
>
${D(o?`tasksPage.cancelling`:`common.cancel`)}
</button>`:y}
${s&&t.canCopy?_`<button
class="btn btn--sm"
type="button"
?disabled=${o||!t.connected}
=${()=>t.onCopyResult(e.taskId)}
>
${D(`tasksPage.copyResult`)}
</button>`:y}
${c&&t.canCancel?_`
<button
class="btn btn--sm"
type="button"
?disabled=${o||!t.connected}
=${()=>t.onRetry(e.taskId)}
>
${D(`tasksPage.retryDelivery`)}
</button>
<button
class="btn btn--sm"
type="button"
?disabled=${o||!t.connected}
=${()=>t.onDismiss(e.taskId)}
>
${D(`tasksPage.dismissDelivery`)}
</button>
`:y}
</div>`:y}
</div>
</div>
`}function Ne(e){switch(e){case`completed`:return`ok`;case`failed`:case`timed_out`:return`danger`;case`queued`:case`running`:return`warn`;case`cancelled`:return`muted`}return e}function G(e,...t){return e.filter(e=>t.includes(e.status)).length}function Pe(e,t){let n=e===`active`?[[G(t,`running`),D(`tasksPage.status.running`)],[G(t,`queued`),D(`tasksPage.status.queued`)]]:[[G(t,`completed`),D(`tasksPage.status.completed`)],[G(t,`failed`,`timed_out`),D(`tasksPage.status.failed`)]];return _`<span class="task-heading-facts">
${n.map(([e,t],n)=>_`
${n>0?_`<span aria-hidden="true">·</span>`:y}
<span><strong>${e}</strong> ${t}</span>
`)}
</span>`}function K(e,t,n,r,i){let a=n.length===0?V(r):de(n,e=>e.id,e=>Me(e,i));return _`<div data-task-section=${e}>
${be({title:_`${t}${Pe(e,n)}`},a)}
</div>`}function Fe(e){let{active:t,recent:n}=F(e.tasks);return L(_`<div class="tasks-page-list">
${e.connected?y:_`<div class="callout warn">${D(`tasksPage.disconnected`)}</div>`}
${e.error?_`<div class="callout danger" role="alert">${e.error}</div>`:y}
${e.copyResultError?_`<div class="callout danger" role="alert">${e.copyResultError}</div>`:y}
${e.loading&&e.tasks.length===0?V(D(`tasksPage.loading`)):y}
${!e.loading&&e.tasks.length===0?V(D(`tasksPage.empty`)):y}
${K(`active`,D(`tasksPage.active`),t,D(`tasksPage.emptyActive`),e)}
${K(`recent`,D(`tasksPage.recent`),n,D(`tasksPage.emptyRecent`),e)}
</div>`,{wide:!0})}function q(){return(q=e((()=>{g(),fe(),R(),E(),oe(),a(),W()})))()}function J(e,t){return t?e.agentId?.trim()?e.agentId.trim().toLowerCase()===t:[e.sessionKey,e.childSessionKey,e.ownerKey].some(e=>d(e)?.agentId===t):!0}function Ie(e){return e instanceof w&&e.gatewayCode===`INVALID_REQUEST`}async function Le(e){let t=[],n,r=new Set;for(;;){let i;try{i=await e.client.request(`tasks.list`,{status:[`queued`,`running`],limit:500,...e.agentId?{agentId:e.agentId}:{},...n===void 0?{}:{cursor:n}},{signal:e.signal})}catch(e){throw n!==void 0&&Ie(e)?new X(e):e}let a=B(i);if(!a)throw Error(D(`tasksPage.invalidResponse`));if(t=U(t,a.tasks),a.nextCursor===void 0)return t;if(!a.nextCursor||r.has(a.nextCursor))throw new X(Error(D(`tasksPage.invalidResponse`)));r.add(a.nextCursor),n=a.nextCursor}}async function Y(e){let[t,n]=await Promise.all([Le(e),e.client.request(`tasks.list`,{status:Z,sortBy:`endedAt`,limit:200,...e.agentId?{agentId:e.agentId}:{}},{signal:e.signal})]),r=B(n);if(!r)throw Error(D(`tasksPage.invalidResponse`));return{active:t,recent:r.tasks}}async function Re(e){try{return await Y(e)}catch(t){if(!(t instanceof X))throw t;return await Y(e)}}var X,Z,Q;function $(){return($=e((()=>{r(),j(),g(),h(),ge(),he(),me(),C(),Ae(),R(),Oe(),E(),ce(),f(),a(),i(),W(),Ee(),te(),o(),q(),X=class extends Error{constructor(e){super(`task list continuation failed`),this.reason=e}},Z=[`completed`,`failed`,`timed_out`,`cancelled`],Q=class extends ie{constructor(...e){super(...e),this.tasks=[],this.error=null,this.copyResultError=null,this.cancellingTaskIds=new Set,this.taskRefreshEvents=null,this.taskSnapshotInvalidated=!1,this.copyResultAttempt=0,this.gateway=new Te(this,{getGateway:()=>this.context?.gateway,onIdentityChange:()=>{this.tasks=[],this.taskSnapshotInvalidated=!1,this.error=null,this.copyResultError=null},invalidateRequests:()=>this.cancelGatewayWork(),onSnapshot:()=>{this.gateway.connected&&this.context.agents.ensureList()},ensureInitialData:()=>void this.refreshTasks()}),this.observeAgentScope=M(()=>{this.gateway.invalidate(),this.cancelGatewayWork(),this.invalidateTaskSnapshot(),this.gateway.connected&&this.refreshTasks(),this.requestUpdate()}),this.listTask=new O(this,{autoRun:!1,args:()=>[this.gateway.connected?this.gateway.gateway:null,this.gateway.connected?this.gateway.client:null,this.context?.agentSelection.state.scopeId??null],task:async([e,t,n],{signal:r})=>{if(!e||!t)return A;let i={gateway:e,client:t,scopeId:n,events:[]};return this.taskRefreshEvents=i,{...await Re({client:t,agentId:n??void 0,signal:r}),buffer:i}},onComplete:({active:e,recent:t,buffer:n})=>{let r=U(e,t);for(let e of n.events)r=H(r,e).tasks;this.taskSnapshotInvalidated=!1,this.tasks=r,this.taskRefreshEvents===n&&(this.taskRefreshEvents=null)},onError:e=>{e instanceof X?this.invalidateTaskSnapshot():this.taskRefreshEvents=null,this.error=c(e instanceof X?e.reason:e,D(`tasksPage.loadFailed`))}}),this.subscriptions=new ue(this).effect(()=>this.context?.gateway,e=>e.subscribeEvents(t=>{if(this.gateway.gateway!==e||this.context.gateway!==e||!this.gateway.connected||t.event!==`task`)return;let n=this.context.agentSelection.state.scopeId,r=z(t.payload);if((r?.action===`deleted`||r?.action===`upserted`&&J(r.task,n))&&this.bufferTaskRefreshEvent(r),this.taskSnapshotInvalidated)return;let i=H(this.tasks,t.payload);if(i.refetch){this.refreshTasks();return}this.tasks=i.tasks.filter(e=>J(e,n))})).effect(()=>this.context?.agentSelection,e=>this.observeAgentScope(e)).watch(()=>this.context?.agents,(e,t)=>e.subscribe(t))}bufferTaskRefreshEvent(e){let t=this.taskRefreshEvents;e&&e.action!==`restored`&&t&&t.gateway===this.gateway.gateway&&t.client===this.gateway.client&&t.scopeId===this.context.agentSelection.state.scopeId&&t.events.push(e)}invalidateTaskSnapshot(){this.taskRefreshEvents=null,this.taskSnapshotInvalidated=!0,this.tasks=[]}disconnectedCallback(){this.copyResultAttempt+=1,this.copyResultError=null,this.subscriptions.clear(),super.disconnectedCallback()}cancelGatewayWork(){this.copyResultAttempt+=1,this.copyResultError=null,this.taskRefreshEvents=null,this.listTask.run([null,null,null]),this.cancellingTaskIds=new Set}refreshTasks(){let e=this.gateway.gateway,t=this.gateway.client;if(!e||this.context.gateway!==e||!this.gateway.connected||!t)return Promise.resolve();let n=this.context.agentSelection.state.scopeId;return this.error=null,this.copyResultError=null,this.listTask.run([e,t,n])}async cancelTask(e){let t=this.gateway.capture(),n=this.gateway.gateway;if(!(!t||!n||this.context.gateway!==n||this.cancellingTaskIds.has(e))){this.cancellingTaskIds=new Set([...this.cancellingTaskIds,e]),this.error=null;try{let n=await t.client.request(`tasks.cancel`,{taskId:e});if(!this.gateway.isCurrent(t))return;let r=P(n);if(r?.task){let e=z({action:`upserted`,task:r.task});this.bufferTaskRefreshEvent(e),this.tasks=H(this.tasks,{action:`upserted`,task:r.task}).tasks}r?.cancelled||(this.error=s(r?.reason,D(`tasksPage.cancelFailed`)))}catch(e){this.gateway.isCurrent(t)&&(this.error=c(e,D(`tasksPage.cancelFailed`)))}finally{if(this.gateway.isCurrent(t)){let t=new Set(this.cancellingTaskIds);t.delete(e),this.cancellingTaskIds=t}}}}async recoverTask(e,t){let n=this.gateway.capture(),r=this.gateway.gateway;if(!(!n||!r||this.context.gateway!==r||this.cancellingTaskIds.has(e))){this.cancellingTaskIds=new Set([...this.cancellingTaskIds,e]),this.error=null;try{let r=t===`retry`?await n.client.request(`tasks.retry`,{taskIds:[e]}):await n.client.request(`tasks.dismiss`,{taskIds:[e]});if(!this.gateway.isCurrent(n))return;let i=I(r)?.results[0];if(!i?.ok){this.error=s(i?.reason,D(`tasksPage.recoveryFailed`));return}if(i.task){let e=z({action:`upserted`,task:i.task});this.bufferTaskRefreshEvent(e),this.tasks=H(this.tasks,e).tasks}}catch(e){this.gateway.isCurrent(n)&&(this.error=c(e,D(`tasksPage.recoveryFailed`)))}finally{if(this.gateway.isCurrent(n)){let t=new Set(this.cancellingTaskIds);t.delete(e),this.cancellingTaskIds=t}}}}async copyTaskResult(e){let t=++this.copyResultAttempt,n=this.gateway.capture(),r=this.gateway.gateway;if(!(!n||!r||this.context.gateway!==r))try{let r=we(await n.client.request(`tasks.get`,{taskId:e}));if(!this.gateway.isCurrent(n)||t!==this.copyResultAttempt)return;let i=r?.result??r?.progressSummary;if(!i){this.copyResultError=D(`tasksPage.recoveryFailed`);return}let a=await ae(i,()=>this.gateway.isCurrent(n)&&t===this.copyResultAttempt);this.gateway.isCurrent(n)&&t===this.copyResultAttempt&&(this.copyResultError=a?null:D(`common.copyFailed`))}catch(e){this.gateway.isCurrent(n)&&t===this.copyResultAttempt&&(this.copyResultError=c(e,D(`tasksPage.recoveryFailed`)))}}render(){let e=ne(this.context);return _`
${Ce({title:S(`tasks`),subtitle:pe(`tasks`),actions:_`
${ke({agents:this.context.agents.state.agentsList?.agents??[],selection:this.context.agentSelection})}
<button
class="btn"
type="button"
?disabled=${!this.gateway.connected||this.listTask.status===k.PENDING}
=${()=>void this.refreshTasks()}
>
${this.listTask.status===k.PENDING?D(`common.refreshing`):D(`common.refresh`)}
</button>
`})}
${De(Fe({basePath:this.context.basePath,agentId:e,mainKey:re({agentsList:this.context.agents.state.agentsList,hello:this.context.gateway.snapshot.hello}),connected:this.gateway.connected,canCopy:b(this.context.gateway.snapshot.hello?.auth??null),canCancel:T(this.context.gateway.snapshot.hello?.auth??null),loading:this.listTask.status===k.PENDING,error:this.error,copyResultError:this.copyResultError,tasks:this.tasks,cancellingTaskIds:this.cancellingTaskIds,sessionRow:e=>le(this.context,e),onCancel:e=>void this.cancelTask(e),onRetry:e=>void this.recoverTask(e,`retry`),onDismiss:e=>void this.recoverTask(e,`dismiss`),onCopyResult:e=>void this.copyTaskResult(e),onNavigateToChat:e=>{let t=p(this.context,e);this.context.navigate(t,m({context:this.context,face:t,sessionKey:e,preferenceDerivedFace:!0}).options)}}))}
`}},n([t({context:x,subscribe:!0})],Q.prototype,`context`,void 0),n([v()],Q.prototype,`tasks`,void 0),n([v()],Q.prototype,`error`,void 0),n([v()],Q.prototype,`copyResultError`,void 0),n([v()],Q.prototype,`cancellingTaskIds`,void 0),customElements.get(`openclaw-tasks-page`)||customElements.define(`openclaw-tasks-page`,Q)})))()}$();
//# sourceMappingURL=tasks-page-DRDmfiYt.js.map