openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
670 lines (666 loc) • 41.2 kB
JavaScript
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