UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

670 lines (666 loc) 41.2 kB
import{m as e,o as t,p as n}from"./lit-runtime-BImxIzGR.js";import{o as r}from"./string-coerce-Dt6Kt5Fx.js";import{A as i,C as a,D as o,E as s,M as c,N as l,O as u,S as d,T as f,b as p,j as m,k as h,v as g,w as _,x as v,y,z as b}from"./index-B6YtUsIL.js";var x=`workboard-card-modal-title`,S=`workboard-card-modal-description`,C=`workboard-card-modal`,w=`workboard-card-detail-drawer`,T=`workboard-card-detail-title`,E=`workboard-card-detail-description`,D=[`a[href]`,`button:not([disabled])`,`input:not([disabled])`,`select:not([disabled])`,`textarea:not([disabled])`,`summary`,`[tabindex]:not([tabindex='-1'])`].join(`,`),O=null,k=null,A=[{id:`bugfix`,title:`Fix: `,notes:`Symptom: Cause: Acceptance: Proof:`,labels:`fix, test`,priority:`high`},{id:`docs`,title:`Docs: `,notes:`Page: Change: Source proof:`,labels:`docs`,priority:`normal`},{id:`release`,title:`Release: `,notes:`Scope: Verification: Closeout:`,labels:`release`,priority:`urgent`},{id:`pr_review`,title:`Review PR `,notes:`Surface: Risks: Proof:`,labels:`review`,priority:`normal`},{id:`plugin`,title:`Plugin: `,notes:`Boundary: Config/docs: Tests:`,labels:`plugin`,priority:`normal`}];function j(e){return r(`workboard.status.${e}`)}function M(e){return e?b(e,{month:`short`,day:`numeric`},``):``}function N(e){return e.canWrite!==!1}function P(e){if(e instanceof Element){k=e;return}k||=document.activeElement}function F(){let e=k;k=null,O=null,!(!(e instanceof HTMLElement)||!e.isConnected)&&requestAnimationFrame(()=>{e.isConnected&&e.focus()})}function I(e){try{e.focus({preventScroll:!0})}catch{e.focus()}}function L(e){return!e.isConnected||e.tabIndex<0?!1:!e.closest(`[hidden], [inert]`)}function ee(e){return[...e.querySelectorAll(D)].filter(L)}function te(e,t){requestAnimationFrame(()=>{if(!e.isConnected||O!==e)return;let n=document.activeElement;if(n instanceof Element&&e.contains(n))return;let r=t?e.querySelector(t):null;I(r&&L(r)?r:t?ee(e)[0]:e)})}function ne(e,t){if(!(e instanceof HTMLElement)){let e=O;if(!e)return;if(!e.isConnected){F();return}queueMicrotask(()=>{O===e&&!e.isConnected&&F()});return}O!==e&&(P(null),O=e),te(e,t)}function re(e,t){let n=ee(t);if(n.length===0){e.preventDefault(),I(t);return}let r=document.activeElement instanceof HTMLElement?document.activeElement:null,i=n[0],a=n[n.length-1],o=r?t.contains(r):!1;if(e.shiftKey&&(!o||r===i||r===t)){e.preventDefault(),I(a);return}!e.shiftKey&&(!o||r===a||r===t)&&(e.preventDefault(),I(i))}function ie(e,t,n){if(e.key===`Escape`){e.preventDefault(),e.stopPropagation(),n(),t.onRequestUpdate?.();return}e.key===`Tab`&&re(e,e.currentTarget)}function ae(e){switch(e.kind){case`created`:return r(`workboard.eventCreated`);case`edited`:return r(`workboard.eventEdited`);case`moved`:return e.toStatus?r(`workboard.eventMovedTo`,{status:j(e.toStatus)}):r(`workboard.eventMoved`);case`linked`:return r(`workboard.eventLinked`);case`specified`:return r(`workboard.eventSpecified`);case`decomposed`:return r(`workboard.eventDecomposed`);case`claimed`:return r(`workboard.eventClaimed`);case`heartbeat`:return r(`workboard.eventHeartbeat`);case`execution_updated`:return r(`workboard.eventExecutionUpdated`);case`attempt_started`:return r(`workboard.eventAttemptStarted`);case`attempt_updated`:return r(`workboard.eventAttemptUpdated`);case`comment_added`:return r(`workboard.eventCommentAdded`);case`link_added`:return r(`workboard.eventLinkAdded`);case`proof_added`:return r(`workboard.eventProofAdded`);case`artifact_added`:return r(`workboard.eventArtifactAdded`);case`attachment_added`:return r(`workboard.eventAttachmentAdded`);case`diagnostic`:return r(`workboard.eventDiagnostic`);case`notification`:return r(`workboard.eventNotification`);case`dispatch`:return r(`workboard.eventDispatch`);case`orchestration`:return r(`workboard.eventOrchestration`);case`protocol_violation`:return r(`workboard.eventProtocolViolation`);case`archived`:return r(`workboard.eventArchived`);case`unarchived`:return r(`workboard.eventUnarchived`);case`stale`:return r(`workboard.eventStale`)}return``}function oe(t){let i=(t.events??[]).toReversed().slice(0,4);return i.length===0?n:e` <ol class="workboard-events" aria-label=${r(`workboard.eventsLabel`)}> ${i.map(t=>e` <li> <span>${ae(t)}</span> <time>${M(t.at)}</time> </li> `)} </ol> `}function se(t,i){let a=t.metadata,o=[];return a?.templateId&&o.push(e`<span>${r(`workboard.template.${a.templateId}`)}</span>`),(i??t.taskId)&&o.push(e`<span>${r(`workboard.badgeTaskLinked`)}</span>`),a?.failureCount&&o.push(e` <span class="workboard-card__badge--warning"> ${g.alertTriangle}${r(`workboard.badgeFailures`,{count:String(a.failureCount)})} </span> `),a?.comments?.length&&o.push(e`<span >${r(`workboard.badgeComments`,{count:String(a.comments.length)})}</span >`),a?.proof?.length&&o.push(e`<span>${r(`workboard.badgeProof`,{count:String(a.proof.length)})}</span>`),a?.claim&&o.push(e`<span>${r(`workboard.badgeClaimed`,{owner:a.claim.ownerId})}</span>`),a?.diagnostics?.length&&o.push(e`<span class="workboard-card__badge--warning"> ${g.alertTriangle}${r(`workboard.badgeDiagnostics`,{count:String(a.diagnostics.length)})} </span>`),a?.stale&&o.push(e`<span class="workboard-card__badge--warning" >${g.alertTriangle}${r(`workboard.badgeStale`)}</span >`),o.length===0?n:e` <div class="workboard-card__badges">${o}</div> `}function ce(e,t){if(t.priority!==`all`&&e.priority!==t.priority)return!1;let n=t.query.trim().toLowerCase();return n?[e.title,e.notes,e.agentId,e.sessionKey,e.execution?.engine,e.execution?.mode,e.execution?.model,e.execution?.sessionKey,e.metadata?.templateId,e.metadata?.automation?.tenant,e.metadata?.automation?.idempotencyKey,e.metadata?.automation?.workspace?.kind,e.metadata?.automation?.workspace?.path,e.metadata?.automation?.workspace?.branch,...e.metadata?.automation?.skills??[],...e.metadata?.automation?.createdCardIds??[],...(e.metadata?.comments??[]).map(e=>e.body),...(e.metadata?.links??[]).flatMap(e=>[e.title,e.url,e.targetCardId]),...(e.metadata?.proof??[]).flatMap(e=>[e.label,e.command,e.url,e.note]),...(e.metadata?.artifacts??[]).flatMap(e=>[e.label,e.url,e.path,e.mimeType]),...(e.metadata?.attachments??[]).flatMap(e=>[e.fileName,e.mimeType,e.note]),...(e.metadata?.workerLogs??[]).map(e=>e.message),e.metadata?.workerProtocol?.state,e.metadata?.workerProtocol?.detail,e.metadata?.claim?.ownerId,...(e.metadata?.diagnostics??[]).flatMap(e=>[e.kind,e.severity,e.title,e.detail]),...(e.metadata?.notifications??[]).map(e=>e.message),...e.labels].filter(e=>typeof e==`string`).some(e=>e.toLowerCase().includes(n)):!0}function le(e,t){let n=e.filter(e=>e.status===t).map(e=>e.position);return(n.length?Math.max(...n):0)+1e3}function ue(e){if(e.archived||e.kind===`global`)return!1;let t=[e.key,e.label,e.displayName].filter(e=>typeof e==`string`).join(`:`).toLowerCase();return!/(^|:)heartbeat(:|$)/.test(t)}function R(e){return e.target instanceof Element?!!e.target.closest(`button, a, input, select, textarea`):!1}function z(e,t){return e?.name??e?.identity?.name??e?.id??t}function de(e,t){return e.agentId?.trim()||t?.defaultId||``}function B(e,t){let n=de(e,t);return n?t?.agents.find(e=>e.id===n):void 0}function fe(e,t){let n=e.agentId?.trim()||r(`workboard.defaultAgent`);return z(B(e,t),n)}function pe(e,t,n){if(n===`all`)return!0;let r=e.agentId?.trim();return n===`default`?!r:r===n||!r&&t?.defaultId===n}function me(e,t){let n=new Set,i=[{id:`all`,label:r(`workboard.allAgents`)},{id:`default`,label:r(`workboard.defaultAgent`)}];for(let e of t?.agents??[])n.has(e.id)||(n.add(e.id),i.push({id:e.id,label:z(e,e.id)}));for(let t of e){let e=t.agentId?.trim();!e||n.has(e)||(n.add(e),i.push({id:e,label:e}))}return i}function he(e){return r(e===`codex`?`workboard.engineOpenAI`:`workboard.engineClaude`)}function ge(e,t,n){if(!n)return null;let i=B(t,e.agentsList),a=i?.agentRuntime?.id?.trim();if(!a)return null;let o=a.toLowerCase();return o===`openclaw`||o===`pi`?null:r(`workboard.engineDisabledRuntime`,{agent:z(i,t.agentId??r(`workboard.defaultAgent`)),runtime:a})}function _e(t,n){let i=fe(n,t.agentsList);return e`<span class="workboard-agent-chip" title=${n.agentId?r(`workboard.agentLinked`,{agent:i}):r(`workboard.agentDefaultLinked`,{agent:i})}>${i}</span>`}function ve(t){return e` <span class="workboard-engine-mark workboard-engine-mark--${t}" aria-hidden="true"> ${t===`codex`?`OpenAI`:`Claude`} </span> `}function V(e,t,n,r){n===t.status||r.busyCardId===t.id||!e.connected||!e.client||h({host:e.host,client:e.client,cardId:t.id,status:n,position:le(r.cards,n),requestUpdate:e.onRequestUpdate})}function ye(t,i,a){let s=o(t.host),c=s.statuses.includes(i.status)?s.statuses:[i.status,...s.statuses];return c.length<2?n:e` <label class="workboard-card__move" title=${r(`workboard.fieldStatus`)}> <span class="workboard-card__move-icon" aria-hidden="true">${g.cornerDownRight}</span> <select class="workboard-card__move-select" aria-keyshortcuts="ArrowLeft ArrowRight" aria-label=${`${r(`workboard.fieldStatus`)}: ${i.title}`} .value=${i.status} ?disabled=${a||!t.connected||!t.client} @change=${e=>{let n=e.currentTarget;V(t,i,n.value,s)}} @keydown=${e=>{if(e.key!==`ArrowLeft`&&e.key!==`ArrowRight`)return;if(s.busyCardId===i.id||!t.connected||!t.client){e.preventDefault();return}let n=c[c.indexOf(i.status)+(e.key===`ArrowRight`?1:-1)];n&&(e.preventDefault(),V(t,i,n,s))}} > ${c.map(t=>e`<option value=${t} ?selected=${t===i.status}> ${j(t)} </option>`)} </select> </label> `}function H(e,t){e.detailCardId=t.id,e.detailCommentBody=``}function U(e){e.detailCardId=null,e.detailCommentBody=``}function W(e){if(!e.detailCardId||e.draftOpen)return null;let t=e.cards.find(t=>t.id===e.detailCardId)??null;return!t||t.metadata?.archivedAt&&!e.showArchived?null:t}function G(e){e.draftOpen=!1,e.editingCardId=null,e.draftTitle=``,e.draftNotes=``,e.draftStatus=`todo`,e.draftPriority=`normal`,e.draftLabels=``,e.draftAgentId=``,e.draftSessionKey=``,e.draftTemplateId=``,e.draftCommentBody=``}function be(e){G(e),e.draftOpen=!0}function xe(e,t){e.draftOpen=!0,e.editingCardId=t.id,e.draftTitle=t.title,e.draftNotes=t.notes??``,e.draftStatus=t.status,e.draftPriority=t.priority,e.draftLabels=t.labels.join(`, `),e.draftAgentId=t.agentId??``,e.draftSessionKey=t.sessionKey??``,e.draftTemplateId=t.metadata?.templateId??``,e.draftCommentBody=``}function Se(e,t){let n=A.find(e=>e.id===t);n&&(e.draftTemplateId=n.id,e.draftTitle=n.title,e.draftNotes=n.notes,e.draftLabels=n.labels,e.draftPriority=n.priority)}function Ce(a){let s=o(a.host),c=a.agentsList?.agents??[],l=a.sessions.filter(ue);if(!s.draftOpen)return n;let u=!!s.editingCardId,d=(s.editingCardId?s.cards.find(e=>e.id===s.editingCardId)??null:null)?.metadata?.comments??[],f=u&&s.busyCardId===s.editingCardId;return e` <div class="workboard-modal" role="presentation" @click=${e=>{e.target===e.currentTarget&&(G(s),a.onRequestUpdate?.())}} > <form id=${C} class="workboard-draft" role="dialog" aria-modal="true" aria-labelledby=${x} aria-describedby=${S} tabindex="-1" ${t(e=>ne(e,`[data-workboard-autofocus='true']`))} @keydown=${e=>ie(e,a,()=>G(s))} @submit=${e=>{e.preventDefault(),!(s.loading||f)&&i({host:a.host,client:a.client,requestUpdate:a.onRequestUpdate})}} > <div class="workboard-modal__header"> <div> <h2 id=${x}> ${r(u?`workboard.editCard`:`workboard.newCard`)} </h2> <p id=${S}> ${r(u?`workboard.editCardHelp`:`workboard.newCardHelp`)} </p> </div> <button class="btn btn--icon workboard-card__icon" type="button" title=${r(`common.cancel`)} aria-label=${r(`common.cancel`)} @click=${()=>{G(s),a.onRequestUpdate?.()}} > ${g.x} </button> </div> ${u?n:e` <div class="workboard-template-strip" aria-label=${r(`workboard.templatesLabel`)}> ${A.map(t=>e` <button class="btn btn--xs ${s.draftTemplateId===t.id?`workboard-template-strip__button--active`:``}" type="button" @click=${()=>{Se(s,t.id),a.onRequestUpdate?.()}} > ${r(`workboard.template.${t.id}`)} </button> `)} </div> `} <div class="workboard-draft__main"> <label class="workboard-field"> <span>${r(`workboard.fieldTitle`)}</span> <input class="input workboard-draft__title" data-workboard-autofocus="true" placeholder=${r(`workboard.titlePlaceholder`)} .value=${s.draftTitle} @input=${e=>{s.draftTitle=e.currentTarget.value,a.onRequestUpdate?.()}} /> </label> <label class="workboard-field"> <span>${r(`workboard.fieldNotes`)}</span> <textarea class="input workboard-draft__notes" placeholder=${r(`workboard.notesPlaceholder`)} .value=${s.draftNotes} @input=${e=>{s.draftNotes=e.currentTarget.value,a.onRequestUpdate?.()}} ></textarea> </label> </div> <div class="workboard-draft__meta"> <label class="workboard-field"> <span>${r(`workboard.fieldStatus`)}</span> <select class="input" .value=${s.draftStatus} @change=${e=>{s.draftStatus=e.currentTarget.value,a.onRequestUpdate?.()}} > ${s.statuses.map(t=>e`<option value=${t} ?selected=${s.draftStatus===t}> ${j(t)} </option>`)} </select> </label> <label class="workboard-field"> <span>${r(`workboard.fieldPriority`)}</span> <select class="input" .value=${s.draftPriority} @change=${e=>{s.draftPriority=e.currentTarget.value,a.onRequestUpdate?.()}} > ${y.map(t=>e`<option value=${t} ?selected=${s.draftPriority===t}> ${t} </option>`)} </select> </label> <label class="workboard-field"> <span>${r(`workboard.fieldAgent`)}</span> <select class="input" .value=${s.draftAgentId} @change=${e=>{s.draftAgentId=e.currentTarget.value,a.onRequestUpdate?.()}} > <option value="" ?selected=${!s.draftAgentId}> ${r(`workboard.defaultAgent`)} </option> ${c.map(t=>e`<option value=${t.id} ?selected=${s.draftAgentId===t.id}> ${t.name??t.identity?.name??t.id} </option>`)} </select> </label> <label class="workboard-field"> <span>${r(`workboard.fieldSession`)}</span> <select class="input" .value=${s.draftSessionKey} @change=${e=>{s.draftSessionKey=e.currentTarget.value,a.onRequestUpdate?.()}} > <option value="" ?selected=${!s.draftSessionKey}> ${r(`workboard.noLinkedSession`)} </option> ${l.map(t=>e`<option value=${t.key} ?selected=${s.draftSessionKey===t.key} > ${t.displayName??t.label??t.key} </option>`)} </select> </label> <label class="workboard-field workboard-field--wide"> <span>${r(`workboard.fieldLabels`)}</span> <input class="input" placeholder=${r(`workboard.labelsPlaceholder`)} .value=${s.draftLabels} @input=${e=>{s.draftLabels=e.currentTarget.value,a.onRequestUpdate?.()}} /> </label> </div> ${u?e` <section class="workboard-field workboard-field--wide" aria-labelledby="workboard-card-comments-title" > <span id="workboard-card-comments-title"> ${r(`workboard.badgeComments`,{count:String(d.length)})} </span> ${d.length?e` <ol> ${d.map(t=>e`<li>${t.body}</li>`)} </ol> `:n} <textarea class="input workboard-comments__input" aria-labelledby="workboard-card-comments-title" maxlength="2000" .value=${s.draftCommentBody} @input=${e=>{s.draftCommentBody=e.currentTarget.value,a.onRequestUpdate?.()}} ></textarea> <div class="workboard-modal__actions"> <button class="btn" type="button" ?disabled=${s.loading||f||!s.draftCommentBody.trim()} @click=${()=>{p({host:a.host,client:a.client,requestUpdate:a.onRequestUpdate})}} > ${g.plus} ${r(`common.create`)} </button> </div> </section> `:n} <div class="workboard-modal__actions"> <button class="btn primary" ?disabled=${s.loading||f||!s.draftTitle.trim()} > ${r(u?`common.save`:`common.create`)} </button> <button class="btn" type="button" @click=${()=>{G(s),a.onRequestUpdate?.()}} > ${r(`common.cancel`)} </button> </div> </form> </div> `}function K(e){switch(e.state){case`running`:return{label:r(`workboard.lifecycleRunning`),detail:r(`workboard.lifecycleRunningDetail`),tone:`live`};case`succeeded`:return{label:r(`workboard.lifecycleDone`),detail:r(`workboard.lifecycleDoneDetail`),tone:`done`};case`failed`:return{label:r(`workboard.lifecycleNeedsReview`),detail:r(`workboard.lifecycleNeedsReviewDetail`),tone:`blocked`};case`stale`:return{label:r(`workboard.lifecycleStale`),detail:r(`workboard.lifecycleStaleDetail`),tone:`blocked`};case`idle`:return{label:r(`workboard.lifecycleLinked`),detail:r(`workboard.lifecycleIdleDetail`),tone:`idle`};case`missing`:return{label:r(`workboard.lifecycleMissing`),detail:r(`workboard.lifecycleMissingDetail`),tone:`blocked`};case`unlinked`:return{label:r(`workboard.lifecycleUnlinked`),detail:r(`workboard.lifecycleUnlinkedDetail`),tone:`idle`}}throw Error(`Unknown workboard lifecycle state.`)}function q(e){return e.status===`queued`||e.status===`running`?e.progressSummary??e.title??e.taskId:e.terminalSummary??e.error??e.progressSummary??e.title??e.taskId}function J(e,t){switch(e.status){case`queued`:case`running`:return t.state===`running`;case`completed`:return t.state===`succeeded`;case`failed`:case`cancelled`:case`timed_out`:return t.state===`failed`}return!1}function Y(e){return e?.status===`queued`||e?.status===`running`}function X(e,t,n){let r=e.tasksByCardId.get(n.id),i=_(n,t),a=Y(r),o=n.sessionKey??n.execution?.sessionKey;return!a&&(!o||!i)}function we(e){if(e.missing)return r(`workboard.dependencyMissing`,{parent:e.title});let t=e.status?j(e.status):r(`workboard.unknownStatus`);return`${e.title} (${t})`}function Te(e){return e.blockedParents.length===0?null:r(`workboard.dependenciesBlockedTitle`,{parents:e.blockedParents.map(we).join(`, `)})}function Ee(t){if(t.parents.length===0)return n;let i=t.blockedParents.length;return e` <div class="workboard-dependencies" title=${Te(t)??r(`workboard.dependenciesReadyTitle`,{count:String(t.parents.length)})}> ${i>0?e` <span class="workboard-dependency workboard-dependency--blocked"> ${g.alertTriangle}${r(`workboard.dependenciesBlocked`,{count:String(i)})} </span> `:e` <span class="workboard-dependency workboard-dependency--ready"> ${r(`workboard.dependenciesReady`,{count:String(t.parents.length)})} </span> `} </div> `}function De(t){return t.parents.length===0?n:e` <section class="workboard-detail__section"> <h3>${r(`workboard.dependencies`)}</h3> <ul class="workboard-detail__list workboard-detail__dependencies"> ${t.parents.map(t=>e` <li class=${t.done?`is-done`:`is-blocked`}> ${t.done?e`<span class="workboard-detail__dependency-spacer"></span>`:g.alertTriangle} <span>${t.title}</span> <span> ${t.missing?r(`workboard.dependencyStatusMissing`):t.status?j(t.status):r(`workboard.unknownStatus`)} </span> </li> `)} </ul> </section> `}function Oe(t,n,i){let a=s(t,n,i),o=K(a),c=a.session,l=t.execution,u=a.state===`stale`,d=i?J(i,a):!1,f=i&&d?r(`workboard.taskStatus.${i.status}`):null;return e` <div class="workboard-card__lifecycle"> <span class="workboard-lifecycle workboard-lifecycle--${o.tone}"> ${f??(u||!l?o.label:`${l.engine} ${l.mode}`)} </span> <span class="workboard-card__lifecycle-detail"> ${i&&d?q(i):u?o.detail:c?.displayName??c?.label??o.detail} </span> </div> `}function Z(t,i,a,s,c={}){let l=o(t.host).busyCardId===i.id,u=ge(t,i,a),d=l||!t.connected||!!u||!!i.metadata?.archivedAt,f=u||(a?r(s===`autonomous`?`workboard.runEngine`:`workboard.openEngine`,{engine:he(a)}):r(`workboard.runDefaultAgent`));return e` <button class="btn btn--xs workboard-card__start workboard-card__start--${s} ${c.iconOnly?`workboard-card__start--icon`:``} ${a?``:`workboard-card__start--default`}" type="button" title=${f} aria-label=${f} ?disabled=${d} @click=${async()=>{let e=await m({host:t.host,client:t.client,card:i,...a?{engine:a}:{},mode:s,requestUpdate:t.onRequestUpdate});e&&t.onOpenSession(e)}} > ${a?e`${ve(a)}${c.iconOnly?n:e`<span >${r(s===`autonomous`?`workboard.run`:`workboard.open`)}</span >`}`:e`${s===`autonomous`?g.play:g.penLine}${c.iconOnly?n:e`<span>${r(`workboard.start`)}</span>`}`} </button> `}function ke(t,r){let i=t.canModelOverride!==!1;return e` <div class="workboard-card__execution-controls"> ${Z(t,r,null,`autonomous`)} ${i?e`${Z(t,r,`codex`,`autonomous`)} ${Z(t,r,`claude`,`autonomous`)}`:n} ${Z(t,r,`codex`,`manual`)} ${Z(t,r,`claude`,`manual`)} </div> `}function Q(t,r){if(typeof r!=`string`&&typeof r!=`number`)return n;let i=String(r).trim();return i?e` <div class="workboard-detail__row"> <span>${t}</span> <strong>${i}</strong> </div> `:n}function $(t,r,i=n){let a=r.map(e=>e.trim()).filter(Boolean).slice(-6);return a.length===0?i:e` <section class="workboard-detail__section"> <h3>${t}</h3> <ol class="workboard-detail__list"> ${a.map(t=>e`<li>${t}</li>`)} </ol> </section> `}function Ae(i){let a=o(i.host),c=W(a);if(!c)return n;let l=a.tasksByCardId.get(c.id),u=s(c,i.sessions,l),d=K(u),m=l?J(l,u):!1,h=c.sessionKey??c.execution?.sessionKey,_=N(i),v=c.metadata?.comments??[],y=c.metadata?.attempts??[],b=c.metadata?.links??[],x=c.metadata?.proof??[],S=c.metadata?.artifacts??[],C=c.metadata?.attachments??[],D=c.metadata?.diagnostics??[],O=c.metadata?.workerLogs??[],k=c.metadata?.workerProtocol,A=c.metadata?.automation,P=(c.events??[]).slice(-6).toReversed(),F=a.busyCardId===c.id,I=_&&X(a,i.sessions,c),L=f(c,a.cards);return e` <aside id=${w} class="workboard-detail-drawer" role="dialog" aria-modal="true" aria-labelledby=${T} aria-describedby=${E} tabindex="-1" ${t(e=>ne(e))} @keydown=${e=>ie(e,i,()=>U(a))} > <div class="workboard-detail"> <header class="workboard-detail__header"> <div> <span class="workboard-card__priority">${c.priority}</span> <h2 id=${T}> <span class="workboard-sr-only">${r(`workboard.detailTitle`)}: </span>${c.title} </h2> </div> <button class="btn btn--icon workboard-card__icon" type="button" title=${r(`common.cancel`)} aria-label=${r(`common.cancel`)} @click=${()=>{U(a),i.onRequestUpdate?.()}} > ${g.x} </button> </header> <section class="workboard-detail__section"> <div class="workboard-card__lifecycle"> <span class="workboard-lifecycle workboard-lifecycle--${d.tone}"> ${d.label} </span> <span id=${E} class="workboard-card__lifecycle-detail"> ${l&&m?q(l):u.session?.displayName??d.detail} </span> </div> <div class="workboard-detail__grid"> ${Q(r(`workboard.fieldStatus`),j(c.status))} ${Q(r(`workboard.fieldAgent`),c.agentId??r(`workboard.defaultAgent`))} ${Q(r(`workboard.detailTask`),l?.taskId??c.taskId)} ${Q(r(`workboard.fieldSession`),h)} ${Q(r(`workboard.detailRun`),c.runId??c.execution?.runId)} ${Q(r(`workboard.detailUpdated`),M(c.updatedAt))} </div> </section> ${c.notes?e` <section class="workboard-detail__section"> <h3>${r(`workboard.fieldNotes`)}</h3> <p>${c.notes}</p> </section> `:n} ${De(L)} ${$(r(`workboard.fieldLabels`),c.labels)} ${$(r(`workboard.badgeAttempts`,{count:String(y.length)}),y.map(e=>[e.status,e.model,e.sessionKey,e.error].filter(Boolean).join(` - `)))} ${$(r(`workboard.badgeLinks`,{count:String(b.length)}),b.map(e=>[e.type,e.title,e.targetCardId,e.url].filter(Boolean).join(` - `)))} ${$(r(`workboard.detailProof`),x.map(e=>[e.status,e.label,e.command,e.url,e.note].filter(Boolean).join(` - `)))} ${$(r(`workboard.badgeArtifacts`,{count:String(S.length)}),S.map(e=>[e.label,e.url,e.path,e.mimeType].filter(Boolean).join(` - `)))} ${$(r(`workboard.badgeAttachments`,{count:String(C.length)}),C.map(e=>[e.fileName,e.mimeType,e.note].filter(Boolean).join(` - `)))} ${$(r(`workboard.detailDiagnostics`),D.map(e=>`${e.severity}: ${e.title}`))} ${$(r(`workboard.detailWorkerLogs`),O.map(e=>`${e.level}: ${e.message}`))} ${k?$(r(`workboard.detailWorkerProtocol`),[k.state,k.detail??``,k.updatedAt?r(`workboard.detailUpdatedValue`,{time:M(k.updatedAt)}):``]):n} ${A?$(r(`workboard.detailAutomation`),[A.tenant?r(`workboard.detailAutomationTenant`,{tenant:A.tenant}):``,A.boardId?r(`workboard.detailAutomationBoard`,{board:A.boardId}):``,A.skills?.length?r(`workboard.detailAutomationSkills`,{skills:A.skills.join(`, `)}):``,A.workspace?r(`workboard.detailAutomationWorkspace`,{workspace:[A.workspace.kind,A.workspace.path,A.workspace.branch].filter(Boolean).join(` `)}):``,A.dispatchCount?r(`workboard.badgeDispatches`,{count:String(A.dispatchCount)}):``,A.lastDispatchAt?r(`workboard.detailUpdatedValue`,{time:M(A.lastDispatchAt)}):``,A.summary?r(`workboard.detailAutomationSummary`,{summary:A.summary}):``]):n} ${$(r(`workboard.eventsLabel`),P.map(e=>`${ae(e)} ${M(e.at)}`))} <section class="workboard-detail__section"> <h3>${r(`workboard.detailOperatorNotes`)}</h3> ${v.length?e` <ol class="workboard-detail__list"> ${v.slice(-6).map(t=>e`<li>${t.body}</li>`)} </ol> `:e`<p>${r(`workboard.detailNoNotes`)}</p>`} ${_?e` <textarea class="input workboard-detail__note" maxlength="2000" placeholder=${r(`workboard.detailNotePlaceholder`)} .value=${a.detailCommentBody} @input=${e=>{a.detailCommentBody=e.currentTarget.value,i.onRequestUpdate?.()}} ></textarea> <button class="btn" type="button" ?disabled=${F||!a.detailCommentBody.trim()} @click=${()=>p({host:i.host,client:i.client,cardId:c.id,body:a.detailCommentBody,requestUpdate:i.onRequestUpdate})} > ${g.plus} ${r(`workboard.detailAddNote`)} </button> `:n} </section> <div class="workboard-detail__actions"> ${h?e` <button class="btn" type="button" @click=${()=>i.onOpenSession(h)} > ${g.messageSquare} ${r(`workboard.openSession`)} </button> `:n} ${I?ke(i,c):n} </div> </div> </aside> `}function je(t){let i=t.lastDispatchSummary;return i?e` <div class="callout"> ${r(i.started+i.failures+i.promoted+i.blocked+i.reclaimed+i.orchestrated===0?`workboard.dispatchSummaryEmpty`:`workboard.dispatchSummary`,{started:String(i.started),failures:String(i.failures),promoted:String(i.promoted),blocked:String(i.blocked),reclaimed:String(i.reclaimed),orchestrated:String(i.orchestrated)})} </div> `:n}function Me(t,i){let a=o(t.host),s=a.tasksByCardId.get(i.id),l=_(i,t.sessions),u=a.busyCardId===i.id,p=a.syncingCardIds.has(i.id),m=Y(s),h=m||l?.hasActiveRun===!0||l?.hasActiveRun!==!1&&l?.status===`running`,y=i.sessionKey??i.execution?.sessionKey,b=N(t),x=b&&X(a,t.sessions,i),S=!!i.metadata?.archivedAt,C=f(i,a.cards);return e` <article class="workboard-card priority-${i.priority} ${u?`workboard-card--busy`:``} ${S?`workboard-card--archived`:``} workboard-card--openable" role="button" tabindex="0" title=${r(`workboard.viewDetails`)} aria-haspopup="dialog" aria-expanded=${a.detailCardId===i.id?`true`:`false`} aria-controls=${w} draggable=${b?`true`:`false`} @click=${e=>{R(e)||(P(e.currentTarget),H(a,i),t.onRequestUpdate?.())}} @keydown=${e=>{R(e)||e.key!==`Enter`&&e.key!==` `||(P(e.currentTarget),H(a,i),t.onRequestUpdate?.(),e.preventDefault())}} @dragstart=${e=>{if(!b){e.preventDefault();return}a.draggedCardId=i.id,e.dataTransfer?.setData(`text/plain`,i.id),e.dataTransfer?.setDragImage(e.currentTarget,16,16),t.onRequestUpdate?.()}} @dragend=${()=>{a.draggedCardId=null,t.onRequestUpdate?.()}} > <div class="workboard-card__top"> <div class="workboard-card__chips"> <span class="workboard-card__priority">${i.priority}</span> ${_e(t,i)} ${S?e`<span class="workboard-card__archived">${r(`workboard.archived`)}</span>`:n} ${h?e`<span class="workboard-live">${r(`workboard.live`)}</span>`:n} ${p?e`<span class="workboard-live">${r(`common.saving`)}</span>`:n} </div> <div class="workboard-card__quick-actions"> ${x?Z(t,i,null,`autonomous`,{iconOnly:!0}):n} ${b&&!S?e` <button class="btn btn--icon workboard-card__icon" type="button" title=${r(`workboard.editCard`)} aria-label=${r(`workboard.editCard`)} aria-haspopup="dialog" @click=${e=>{P(e.currentTarget),xe(a,i),t.onRequestUpdate?.()}} > ${g.edit} </button> `:n} ${b?e` <button class="btn btn--icon workboard-card__icon" type="button" title=${r(S?`workboard.unarchiveCard`:`workboard.archiveCard`)} aria-label=${r(S?`workboard.unarchiveCard`:`workboard.archiveCard`)} ?disabled=${u} @click=${()=>v({host:t.host,client:t.client,cardId:i.id,archived:!S,requestUpdate:t.onRequestUpdate})} > ${S?g.archiveRestore:g.archive} </button> `:n} </div> </div> <h3>${i.title}</h3> ${i.notes?e`<p>${i.notes}</p>`:n} ${Oe(i,t.sessions,s)} ${Ee(C)} ${i.labels.length?e`<div class="workboard-labels"> ${i.labels.map(t=>e`<span>${t}</span>`)} </div>`:n} ${se(i,s)} <div class="workboard-card__meta"> <span>${y??r(`workboard.noLinkedSession`)}</span> <span>${M(i.updatedAt)}</span> </div> ${oe(i)} <div class="workboard-card__actions"> <button class="btn btn--icon workboard-card__icon" title=${r(`workboard.viewDetails`)} aria-label=${r(`workboard.viewDetails`)} aria-haspopup="dialog" aria-expanded=${a.detailCardId===i.id?`true`:`false`} aria-controls=${w} @click=${e=>{P(e.currentTarget),H(a,i),t.onRequestUpdate?.()}} > ${g.panelRightOpen} </button> ${y?e` <button class="btn btn--icon workboard-card__icon" title=${r(`workboard.openSession`)} @click=${()=>t.onOpenSession(y)} > ${g.messageSquare} </button> ${b&&h?e` <button class="btn btn--icon workboard-card__icon" title=${r(`workboard.stopSession`)} ?disabled=${u||!t.connected} @click=${()=>c({host:t.host,client:t.client,card:i,requestUpdate:t.onRequestUpdate})} > ${g.stop} </button> `:n} `:n} ${!y&&b&&m?e` <button class="btn btn--icon workboard-card__icon" title=${r(`workboard.stopSession`)} ?disabled=${u||!t.connected} @click=${()=>c({host:t.host,client:t.client,card:i,requestUpdate:t.onRequestUpdate})} > ${g.stop} </button> `:n} ${b?e` ${ye(t,i,u)} <button class="btn btn--icon workboard-card__icon workboard-card__delete" type="button" title=${r(`workboard.deleteCard`)} aria-label=${r(`workboard.deleteCard`)} ?disabled=${u} @click=${()=>d({host:t.host,client:t.client,cardId:i.id,requestUpdate:t.onRequestUpdate})} > ${g.trash} </button> `:n} </div> </article> `}function Ne(t,n,i){let a=o(t.host),s=N(t);return e` <section class="workboard-column workboard-column--${n} ${a.draggedCardId?`workboard-column--drop`:``}" @dragover=${e=>{s&&a.draggedCardId&&e.preventDefault()}} @drop=${e=>{if(e.preventDefault(),!s)return;let r=e.dataTransfer?.getData(`text/plain`)||a.draggedCardId;r&&h({host:t.host,client:t.client,cardId:r,status:n,position:le(a.cards,n),requestUpdate:t.onRequestUpdate})}} > <div class="workboard-column__header"> <h2>${j(n)}</h2> <span>${i.length}</span> </div> <div class="workboard-column__cards"> ${i.length?i.map(e=>Me(t,e)):e`<div class="workboard-empty">${r(`workboard.emptyColumn`)}</div>`} </div> </section> `}function Pe(t){let i=o(t.host);if(t.pluginEnabled&&(u({host:t.host,client:t.client,requestUpdate:t.onRequestUpdate}),l({host:t.host,client:t.client,sessions:t.sessions,canWrite:t.canWrite,requestUpdate:t.onRequestUpdate})),!t.pluginEnabled)return e` <section class="workboard"> <div class="callout"> ${r(`workboard.disabledHelpStart`)} <code>${r(`workboard.enableConfigKey`)}</code>${r(`workboard.disabledHelpEnd`)} </div> </section> `;let s=i.cards.filter(e=>i.showArchived||!e.metadata?.archivedAt).filter(e=>pe(e,t.agentsList,i.agentFilter)).filter(e=>ce(e,{query:i.query,priority:i.priorityFilter})),c=N(t),d=me(i.cards,t.agentsList),f=new Map;for(let e of i.statuses)f.set(e,[]);for(let e of s)f.get(e.status)?.push(e);let p=i.draftOpen||!!W(i);return e` <section class="workboard"> <div class="workboard-main" ?inert=${p} aria-hidden=${p?`true`:n}> <div class="workboard-toolbar"> <div class="workboard-toolbar__filters"> <input class="input" type="search" title=${r(`workboard.searchPlaceholder`)} placeholder=${r(`workboard.searchPlaceholder`)} .value=${i.query} @input=${e=>{i.query=e.currentTarget.value,t.onRequestUpdate?.()}} /> <select class="input" title=${r(`workboard.allPriorities`)} .value=${i.priorityFilter} @change=${e=>{i.priorityFilter=e.currentTarget.value,t.onRequestUpdate?.()}} > <option value="all">${r(`workboard.allPriorities`)}</option> ${y.map(t=>e`<option value=${t}>${t}</option>`)} </select> <select class="input" title=${r(`workboard.agentFilter`)} .value=${i.agentFilter} @change=${e=>{i.agentFilter=e.currentTarget.value,t.onRequestUpdate?.()}} > ${d.map(t=>e`<option value=${t.id}>${t.label}</option>`)} </select> <button class="btn workboard-archive-toggle ${i.showArchived?`active`:``}" type="button" title=${i.showArchived?r(`workboard.hideArchived`):r(`workboard.showArchived`)} aria-pressed=${i.showArchived} @click=${()=>{i.showArchived=!i.showArchived,t.onRequestUpdate?.()}} > ${i.showArchived?g.eye:g.eyeOff} ${i.showArchived?r(`workboard.hideArchivedShort`):r(`workboard.showArchivedShort`)} </button> <div class="workboard-layout-toggle" role="group" aria-label=${r(`workboard.layout`)}> <button class="btn btn--icon ${i.layout===`compact`?`active`:``}" type="button" title=${r(`workboard.layoutCompact`)} aria-label=${r(`workboard.layoutCompact`)} aria-pressed=${i.layout===`compact`} @click=${()=>{i.layout=`compact`,t.onRequestUpdate?.()}} > ${g.layoutCompact} </button> <button class="btn btn--icon ${i.layout===`comfortable`?`active`:``}" type="button" title=${r(`workboard.layoutComfortable`)} aria-label=${r(`workboard.layoutComfortable`)} aria-pressed=${i.layout===`comfortable`} @click=${()=>{i.layout=`comfortable`,t.onRequestUpdate?.()}} > ${g.layoutComfortable} </button> </div> </div> <div class="workboard-toolbar__actions"> <button class="btn" type="button" title=${r(`common.refresh`)} ?disabled=${i.loading} @click=${()=>u({host:t.host,client:t.client,requestUpdate:t.onRequestUpdate,force:!0})} > ${i.loading?r(`common.refreshing`):r(`common.refresh`)} </button> ${c?e` <button class="btn" type="button" title=${r(`workboard.dispatch`)} ?disabled=${i.loading} @click=${()=>a({host:t.host,client:t.client,requestUpdate:t.onRequestUpdate})} > ${g.zap} ${r(`workboard.dispatch`)} </button> `:n} ${c?e` <button class="btn primary" type="button" title=${r(`workboard.newCard`)} aria-haspopup="dialog" aria-expanded=${i.draftOpen?`true`:`false`} aria-controls=${C} @click=${e=>{P(e.currentTarget),be(i),t.onRequestUpdate?.()}} > ${g.plus} ${r(`workboard.newCard`)} </button> `:n} </div> </div> ${i.error?e`<div class="callout danger">${i.error}</div>`:n} ${je(i)} <div class="workboard-board workboard-board--${i.layout}"> ${i.statuses.map(e=>Ne(t,e,f.get(e)??[]))} </div> </div> ${Ce(t)} ${Ae(t)} </section> `}export{Pe as renderWorkboard}; //# sourceMappingURL=workboard-DNcFqqrs.js.map