@nelsonlongxiang/dsh-open-a2a-net 0.6.38 → 0.6.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +342 -335
- package/README_zh.md +243 -236
- package/assets/nexusDist/assets/index-C7HagaGy.css +1 -1
- package/assets/nexusDist/assets/index-NkNSeIx6.js +9 -9
- package/cli/a2a.mjs +20 -5
- package/cli/serve.mjs +132 -0
- package/cordis.patch.yml +21 -21
- package/lib/a2a-client.js +1 -0
- package/lib/canvas-id.js +27 -0
- package/lib/canvas-store.js +7 -1
- package/lib/cli-deposit.js +2 -2
- package/lib/client.js +63 -63
- package/lib/config.js +125 -0
- package/lib/direct-forward.js +64 -18
- package/lib/faces/admin.js +4 -1
- package/lib/faces/wire.js +77 -7
- package/lib/flood-guard.js +3 -1
- package/lib/index.js +84 -172
- package/lib/lan-ip.js +20 -0
- package/lib/live-roots.js +39 -0
- package/lib/origin-claim.js +3 -2
- package/lib/peer-link-display.js +3 -2
- package/lib/queue-guard.js +3 -1
- package/lib/skill/references/cli.md +215 -203
- package/lib/skill/references/routing.md +4 -0
- package/lib/skill/references/setup.md +156 -153
- package/lib/task-auth.js +14 -10
- package/lib/types/canvas-id.d.ts +9 -0
- package/lib/types/cli-deposit.d.ts +6 -1
- package/lib/types/config.d.ts +278 -0
- package/lib/types/direct-forward.d.ts +25 -3
- package/lib/types/faces/admin.d.ts +2 -0
- package/lib/types/faces/wire.d.ts +26 -0
- package/lib/types/index.d.ts +3 -277
- package/lib/types/lan-ip.d.ts +7 -0
- package/lib/types/live-roots.d.ts +35 -0
- package/lib/types/origin-claim.d.ts +1 -0
- package/lib/types/peer-link-display.d.ts +2 -0
- package/lib/types/queue-guard.d.ts +2 -0
- package/lib/types/task-auth.d.ts +3 -0
- package/lib/types/types.d.ts +7 -0
- package/nexus-stage/package-lock.json +2262 -2262
- package/nexus-stage/src/edges.ts +72 -72
- package/nexus-stage/src/layout-wire.ts +158 -158
- package/nexus-stage/src/seat.ts +35 -35
- package/nexus-stage/src/stage-name.ts +13 -13
- package/nexus-stage/src/tokens.ts +31 -31
- package/package.json +219 -218
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
var To=Object.defineProperty;var _o=(e,t,o)=>t in e?To(e,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):e[t]=o;var Et=(e,t,o)=>_o(e,typeof t!="symbol"?t+"":t,o);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))s(n);new MutationObserver(n=>{for(const i of n)if(i.type==="childList")for(const r of i.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&s(r)}).observe(document,{childList:!0,subtree:!0});function o(n){const i={};return n.integrity&&(i.integrity=n.integrity),n.referrerPolicy&&(i.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?i.credentials="include":n.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function s(n){if(n.ep)return;n.ep=!0;const i=o(n);fetch(n.href,i)}})();const ln=6e4;function Oo(e,t,o=Date.now){let s=-ln;return{fault(n){const i=o();i-s>=ln&&(t(`[nexus] ${n}`),s=i),e.show(n)},clear(){e.hide(),s=-ln}}}function lt(e){return e.name??e.team??e.label??""}function ao(e,t){var i,r;const o=(c,l)=>c!==void 0&&c.trim()!==""?{name:c,remote:l}:void 0,s=(e.sessions??[]).find(c=>c.team===t);if(s!==void 0)return o(lt(s),!1);const n=(e.remote??[]).find(c=>c.team===t);return n!==void 0?o(lt(n),!0):o((r=(((i=e.canvas)==null?void 0:i.teams)??[]).find(c=>c.team===t))==null?void 0:r.name,!1)}function Fo(e,t){const o=ao(e,t);return o===void 0?t:o.remote?`${o.name}(远端)`:o.name}function zt(e,t,o,s=""){const n=ao(t,o);if(e.textContent=`${s}${(n==null?void 0:n.name)??o}`,e.title=o,(n==null?void 0:n.remote)===!0){const i=e.appendChild(document.createElement("span"));i.className="wb-row-remote",i.textContent="远端",i.title="名字由对端自行发布"}}const Po=60*6e4;function $t(e){var t;return e.direction==="inbound"||e.direction===void 0&&((t=e.peer)==null?void 0:t.startsWith("local:"))===!0}function Tn(e){var t;return((t=e.peer)==null?void 0:t.startsWith("local:"))===!0?e.peer.slice(6):void 0}function Dt(e,t){return e.settleable!==void 0?e.settleable===!1:t-e.startedAt>=Po}function hn(e,t){const o=(e.tasks??[]).filter(r=>r.receiptExpected!==!1),s=o.filter(r=>!$t(r)&&Dt(r,t)),n=o.filter(r=>$t(r)&&Dt(r,t)),i=e.tasksDead??[];return{stale:s,owedOverdue:n,deadLetters:i.filter(r=>r.reason!=="fire-forget"),expired:i.filter(r=>r.reason==="fire-forget")}}function ke(e,t){const o=document.createElement(e);return t!==void 0&&(o.className=t),o}function _n(e,t){const o=Math.max(0,Math.round((t-e)/1e3));if(o<90)return`${o}s`;const s=Math.round(o/60);if(s<90)return`${s}m`;const n=Math.round(s/60);return n<48?`${n}h`:`${Math.round(n/24)}d`}function jt(e,t,o,s,n){const i=ke("div",`wb-led-tile${n!==void 0?` is-${n}`:""}`);i.title=s,i.appendChild(ke("span","wb-led-tile-v")).textContent=String(o),i.appendChild(ke("span","wb-led-tile-k")).textContent=t,e.appendChild(i)}const bn=[{key:"completed",label:"完成",tone:"completed"},{key:"sync_completed",label:"同步完成",tone:"completed"},{key:"rejected",label:"拒绝",tone:"rejected"},{key:"failed",label:"失败",tone:"failed"},{key:"expired",label:"过期",tone:"abandoned"},{key:"abandoned",label:"放弃",tone:"abandoned"},{key:"unknown",label:"结论不明",tone:"unclassified"},{key:"unclassified",label:"未分类",tone:"unclassified"}];function Do(e,t,o){const s=ke("div","wb-led-split"),n=ke("div","wb-led-split-bar");n.setAttribute("role","img");const i=ke("div","wb-led-split-legend"),r=new Set(bn.map(u=>u.key)),c=bn.map(u=>[u.tone,u.label,t[u.key]??0]);for(const[u,b]of Object.entries(t))r.has(u)||c.push(["other",u,b]);const l=[];for(const[u,b,m]of c){if(m<=0)continue;const x=ke("span",`wb-led-seg is-${u}`);x.style.width=`${Math.max(2,m/o*100)}%`,n.appendChild(x);const N=ke("span","wb-led-split-item");N.appendChild(ke("i",`wb-led-swatch is-${u}`)),N.appendChild(document.createTextNode(`${b} ${m}`)),i.appendChild(N),l.push(`${b} ${m}`)}n.setAttribute("aria-label",`归档结局:${l.join(",")}`),s.append(n,i),e.appendChild(s)}function Ro(e,t){var Me;e.replaceChildren();const{state:o,now:s}=t,n=o.tasks??[],i=o.tasksDead??[],r=o.archivedCount??0,c=hn(o,s),l=n.filter(D=>D.receiptExpected===!1),u=n.filter(D=>D.receiptExpected!==!1),b=u.filter(D=>$t(D)),m=u.filter(D=>!$t(D)),x=c.stale,N=m.filter(D=>!Dt(D,s)),Y=c.stale.length,re=ke("div","wb-led-tiles");jt(re,"待回执",u.length,`要回执、仍未结算的任务(含陈旧与本机欠对方的入站行)${l.length>0?`;另有免回执 ${l.length} 条不计`:""}`),jt(re,"陈旧",Y,"我方派发、要回执、已等待 ≥1h 仍未回执(可催办);本机欠对方的入站行在「待本机回执」组另计,免回执行不算陈旧",Y>0?"warn":void 0),jt(re,"死信",c.deadLetters.length,"超过 24h TTL 仍未结算(unconsumed);需清账(abandon)才能移出。免回执到期另列,不算死信",c.deadLetters.length>0?"danger":void 0),jt(re,"已归档",r,"已离开台账并留档的任务(结算、拒绝或放弃),用于审计"),e.appendChild(re),r>0&&o.archivedSplit!==void 0&&Do(e,o.archivedSplit,r);const V=(D,U)=>{const ce=ke("div",`wb-led-card is-${U.tone}`),Re=ke("div","wb-led-card-head");Re.appendChild(ke("span",`wb-led-dir${U.inbound?" is-in":""}`)).textContent=U.inbound?"↙":"↗";const Ee=ke("span","wb-led-brief");Ee.textContent=U.brief!==void 0&&U.brief!==""?U.brief:"(无摘要——派发未带 brief)",(U.brief===void 0||U.brief==="")&&Ee.classList.add("is-missing"),Re.appendChild(Ee),ce.appendChild(Re);const le=ke("div","wb-led-meta"),He=le.appendChild(ke("span","wb-led-team"));U.inbound?U.sender!==void 0?zt(He,o,U.sender,"来自 "):He.textContent="来自 对端":zt(He,o,U.team,"发往 "),U.inbound&&zt(le.appendChild(ke("span","wb-led-to")),o,U.team,"至 "),le.appendChild(ke("span")).textContent=U.atText,le.appendChild(ke("span","wb-led-task")).textContent=U.taskId;for(const fe of U.chips)le.appendChild(ke("span","wb-led-chip")).textContent=fe;if(ce.appendChild(le),ce.title=`${U.taskId}
|
|
2
|
-
${U.team}`,U.dead!==void 0){const fe=U.dead,q=fe.reason==="fire-forget",de=ke("button",`wb-btn wb-led-abandon${q?" is-quiet":""}`);de.type="button",de.textContent=q?"移出":"清账",de.title=q?"可选:把这条已过期的免回执记录移出台账(不是失败,不处理也无妨)":"从台账移出这条死信(abandon)",de.addEventListener("click",ee=>{ee.stopPropagation(),de.disabled=!0,t.abandon(fe.taskId,"workbench dead-letter cleanup").then(te=>{de.disabled=!1,de.textContent=te?"已清":"失败"})}),ce.appendChild(de)}if(t.canOpenTeam(U.team)){ce.classList.add("is-link"),ce.setAttribute("role","button"),ce.tabIndex=0,ce.setAttribute("aria-label",`${Ee.textContent},打开 ${U.team} 的对话`);const fe=()=>{t.openTeam(U.team)};ce.addEventListener("click",fe),ce.addEventListener("keydown",q=>{(q.key==="Enter"||q.key===" ")&&(q.preventDefault(),fe())})}D.appendChild(ce)},M=(D,U,ce,Re)=>{if(U===0)return null;const Ee=ke("div",`wb-led-group is-${ce}`);Ee.dataset.group=D;const le=ke("div","wb-led-group-head");return le.appendChild(ke("span")).textContent=`${D} · ${U}`,le.appendChild(ke("span","wb-led-group-hint")).textContent=Re,Ee.appendChild(le),e.appendChild(Ee),Ee},C=(D,U)=>{const ce=$t(D);return{brief:D.brief,team:D.team,sender:Tn(D),taskId:D.taskId,atText:`${_n(D.startedAt,s)} 前${ce?"收到":"派发"}`,inbound:ce,tone:U,chips:[...D.settleable===!0?["可结算"]:[],...D.receiptExpected===!1?["无回执债"]:[],...ce?["入站"]:[],...D.status!=="pending"?[D.status]:[]]}},S=(D,U,ce)=>({brief:D.brief,team:D.team,sender:Tn(D),taskId:D.taskId,atText:`${_n(D.deadAt,s)} 前${ce}`,inbound:$t(D),tone:U,dead:D,chips:D.reason!==void 0&&D.reason!==""&&D.reason!=="unspecified"&&D.reason!=="fire-forget"?[D.reason]:[]}),E=M("死信",c.deadLetters.length,"danger","需清账");if(E!==null)for(const D of[...c.deadLetters].sort((U,ce)=>ce.deadAt-U.deadAt))V(E,S(D,"danger","死信"));const G=M("陈旧",x.length,"warn","我方派发 ≥1 小时仍无回执,可催办");if(G!==null)for(const D of[...x].sort((U,ce)=>U.startedAt-ce.startedAt))V(G,C(D,"warn"));const y=c.owedOverdue.length,f=M("待本机回执",b.length,y>0?"warn":"quiet",y>0?`对方在等本机回执 · ${y} 条超过 1 小时`:"对方在等本机回执");if(f!==null)for(const D of[...b].sort((U,ce)=>U.startedAt-ce.startedAt))V(f,C(D,Dt(D,s)?"warn":"quiet"));const _=M("等待回执",N.length,"quiet","1 小时内");if(_!==null)for(const D of[...N].sort((U,ce)=>ce.startedAt-U.startedAt))V(_,C(D,"quiet"));const p=M("免回执",l.length,"muted","不等回执,24h 后自动归档");if(p!==null)for(const D of l)V(p,C(D,"muted"));const R=M("已过期(免回执)",c.expired.length,"muted","正常记账,不是失败");if(R!==null)for(const D of[...c.expired].sort((U,ce)=>ce.deadAt-U.deadAt))V(R,S(D,"muted","过期"));n.length+i.length===0&&(e.appendChild(ke("div","wb-led-empty")).textContent="台账为空——没有待回执的任务");const j=o.idempotency,K=(Me=o.reconcile)==null?void 0:Me.state;if(j!==void 0||K!==void 0){const D=ke("details","wb-led-forensics wb-forensics");D.appendChild(ke("summary")).textContent="取证";const U=ke("div","wb-led-forensics-body");j!==void 0&&(U.appendChild(ke("div")).textContent=`幂等 claims ${j.claimsFresh??0} · replays ${j.replays??0} · conflicts ${j.conflicts??0}`),K!==void 0&&(U.appendChild(ke("div")).textContent=`reconcile ${K}`),D.appendChild(U),e.appendChild(D)}const we=u.length+c.deadLetters.length;return{badge:we>0?String(we):"",tone:c.deadLetters.length>0?"danger":Y>0||y>0?"warn":void 0}}const Tt=4e3,Ho=32;function ye(e,t){const o=document.createElement(e);return t!==void 0&&(o.className=t),o}function Bt(e,t,o=""){const s=ye("button",`wb-icon-btn wb-chat-act ${o}`.trim());return s.type="button",s.setAttribute("aria-label",e),s.title=e,s.textContent=t,s}function dn(e,t){const o=Math.max(0,Math.round((t-e)/1e3));if(o<60)return"刚刚";const s=Math.round(o/60);if(s<60)return`${s} 分钟前`;const n=Math.round(s/60);return n<48?`${n} 小时前`:`${Math.round(n/24)} 天前`}function jo(e){return e>=1e6?`${(e/1e6).toFixed(1)} MB`:e>=1e3?`${Math.round(e/1e3)} KB`:`${e} B`}function mn(e){const t=e.kind==="session"||e.kind==="remote"?e.team:void 0;return t!==void 0&&t!==""?t:void 0}function On(e){return e.kind==="remote"?`remote:${e.team}`:`${e.kind}:${e.id}`}function Bo(e){let t=null,o=null,s=!1,n=!1;const i=new Map,r=new Map,c=new Map,l=new Map,u=new Set,b=new Map,m=new Map,x=ye("aside","wb-chat");x.setAttribute("aria-label","对话");const N=ye("div","wb-chat-head"),Y=Bt("返回会话列表","‹","wb-chat-back"),re=ye("span","wb-chat-dot"),V=ye("div","wb-chat-titles"),M=ye("span","wb-chat-title"),C=ye("span","wb-chat-sub");V.append(M,C);const S=Bt("刷新对话","↻","wb-chat-refresh"),E=Bt("会话详情","ⓘ","wb-chat-info-btn");E.setAttribute("aria-expanded","false");const G=Bt("关闭对话","✕","wb-chat-close");N.append(Y,re,V,S,E,G);const y=ye("div","wb-chat-info");y.hidden=!0;const f=ye("div","wb-chat-thread");f.setAttribute("role","log"),f.setAttribute("aria-live","polite"),f.tabIndex=0;const _=ye("div","wb-chat-notice"),p=ye("div","wb-chat-log"),R=ye("div","wb-chat-sent");f.append(_,p,R);const j=ye("div","wb-chat-foot");x.append(N,y,f,j),Y.addEventListener("click",()=>{(t==null?void 0:t.kind)==="peer"&&(t.picked=void 0,Ie())}),S.addEventListener("click",()=>{if(t===null)return;const d=K(t);d!==void 0&&i.delete(d),t.kind==="peer"&&t.picked===void 0&&t.url!==void 0&&c.delete(`peer:${t.url}`),de(!0)}),E.addEventListener("click",()=>{n=!n,y.hidden=!n,E.setAttribute("aria-expanded",String(n))}),G.addEventListener("click",()=>ft()),f.addEventListener("scroll",()=>{const d=t!==null?K(t):void 0;d!==void 0&&r.set(d,f.scrollTop)}),document.addEventListener("keydown",d=>{if(d.key!=="Escape"||!x.classList.contains("is-open"))return;const A=d.target;if(A instanceof HTMLElement){if(!x.contains(A)){const I=A instanceof HTMLTextAreaElement||A instanceof HTMLInputElement||A.isContentEditable,Q=A.closest(".wb-stage-board")!==null;if(I||Q)return}ft()}});function K(d){if(d.kind==="session"||d.kind==="log")return e.sessionLog!==void 0?`local:${d.id}`:void 0;if(d.kind==="remote")return e.remoteSessionLog!==void 0?`remote:${d.team}`:void 0;if(d.picked!==void 0&&d.url!==void 0&&e.remoteSessionLog!==void 0)return`peer:${d.url}:${d.picked}`}function we(d){var A,I,Q;return d.kind==="session"||d.kind==="log"?((A=e.sessionLog)==null?void 0:A.call(e,d.id))??Promise.resolve({ok:!1,error:"sessionLog unavailable"}):d.kind==="remote"?((I=e.remoteSessionLog)==null?void 0:I.call(e,{team:d.team}))??Promise.resolve({ok:!1,error:"remoteSessionLog unavailable"}):((Q=e.remoteSessionLog)==null?void 0:Q.call(e,{peer:d.url,id:d.picked}))??Promise.resolve({ok:!1,error:"remoteSessionLog unavailable"})}function Me(){const d=t;if(d===null)return;const A=d.kind==="log"||d.kind==="remote"||d.kind==="session"&&d.live===!1;re.className=`wb-chat-dot ${d.kind==="peer"?"is-peer":A?"is-cold":"is-live"}`,re.title=d.kind==="peer"?"对端主机":d.kind==="log"?"只读日志":d.kind==="remote"?"远端会话":d.live===!1?"冷会话":"在线",M.textContent=d.kind==="peer"&&d.picked!==void 0?`…${d.picked.slice(-12)}`:d.title,C.textContent=d.kind==="peer"&&d.picked!==void 0?d.title:d.sub,Y.hidden=!(d.kind==="peer"&&d.picked!==void 0)}function D(d,A){const I=ye("div","wb-kv");I.appendChild(ye("span","wb-kv-k")).textContent=d,I.appendChild(ye("span","wb-kv-v")).textContent=A,y.appendChild(I)}function U(){var A,I,Q;y.replaceChildren();const d=t;d!==null&&(d.kind==="session"?(D("会话",d.id),d.team!==void 0&&D("路由",d.team),D("来源","本机会话日志")):d.kind==="log"?(D("会话",d.id),D("来源","本机会话日志(不在网络目录)")):d.kind==="remote"?(D("路由",d.team),((A=d.row)==null?void 0:A.origin)!==void 0&&D("来源",d.row.origin),((I=d.row)==null?void 0:I.via)!==void 0&&D("经",d.row.via),((Q=d.row)==null?void 0:Q.workspace)!==void 0&&D("工作区",d.row.workspace)):(D("对端",d.url??d.sub),d.picked!==void 0&&D("会话",d.picked),D("来源","经本机代理读取对端 /a2a/log")))}function ce(d){return d.kind==="log"?"只读日志 —— 此会话当前不在网络目录(可能已归档或未入网)。":d.kind==="remote"?e.remoteSessionLog!==void 0?"远端会话 —— 经本机代理从对端 /a2a/log 读取最近对话。":"远端节点的对话记录在对端机器上;本页的代理读取面未启用。":d.kind==="peer"?d.url===void 0||e.remoteSessionLog===void 0?`对端主机节点(${d.sub})—— 会话记录存放在对端机器上,本页只读本机会话日志。`:d.picked===void 0?"对端主机 —— 选择一个会话阅读(经本机代理读取对端 /a2a/log)。":"":e.sessionLog===void 0?"本页未接入会话日志读取,只显示从这里发出的消息。":""}function Re(){return f.scrollHeight-f.scrollTop-f.clientHeight<=Ho}function Ee(d){const A=()=>{f.scrollTop=f.scrollHeight};A(),requestAnimationFrame(A)}function le(d,A){const I=ye("div",`wb-chat-empty${A==="error"?" is-error":""}`);return I.textContent=d,I}function He(d,A){const I=d==="user",Q=ye("div",`wb-msg ${I?"wb-msg-user":"wb-msg-assistant"}`),X=ye("span","wb-msg-who");X.textContent=I?"问":"答";const me=ye("div","wb-msg-text");return me.textContent=A,Q.append(X,me),Q}function fe(d){if(p.replaceChildren(),d===void 0){p.appendChild(le("读取中…"));return}if(d.ok!==!0||d.messages===void 0){p.appendChild(le(`无法读取(${d.error??"未知错误"})`,"error"));return}if(d.messages.length===0){p.appendChild(le("暂无对话记录"));return}for(const A of d.messages)p.appendChild(He(A.role,A.text))}function q(d,A){if(p.replaceChildren(),A===void 0){p.appendChild(le("读取中…"));return}if(A.ok!==!0||A.sessions===void 0){p.appendChild(le(`无法读取(${A.error??"未知错误"})`,"error"));return}if(A.sessions.length===0){p.appendChild(le("对端没有可读会话"));return}const I=ye("div","wb-chat-sessions"),Q=e.now();for(const X of A.sessions){const me=ye("button","wb-chat-session");me.type="button",me.appendChild(ye("span","wb-chat-session-id")).textContent=`…${X.id.slice(-12)}`;const ge=[X.mtimeMs!==void 0?dn(X.mtimeMs,Q):"",jo(X.sizeBytes)].filter(Boolean).join(" · ");me.appendChild(ye("span","wb-chat-session-meta")).textContent=ge,me.title=X.id,me.addEventListener("click",()=>{(t==null?void 0:t.kind)!=="peer"||t.url!==d||(t.picked=X.id,Ie())}),I.appendChild(me)}p.appendChild(I)}function de(d=!1){const A=t;if(A===null)return;if(_.textContent=ce(A),_.hidden=_.textContent==="",A.kind==="peer"&&A.picked===void 0){if(A.url===void 0||e.remoteSessionLog===void 0){p.replaceChildren();return}const X=A.url,me=`peer:${X}`;if(!d&&c.has(me)){q(X,c.get(me));return}c.set(me,void 0),q(X,void 0),e.remoteSessionLog({peer:X}).then(ge=>{c.set(me,ge),(t==null?void 0:t.kind)==="peer"&&t.url===X&&t.picked===void 0&&q(X,ge)},ge=>{const ve={ok:!1,error:ge instanceof Error?ge.message:String(ge)};c.set(me,ve),(t==null?void 0:t.kind)==="peer"&&t.url===X&&t.picked===void 0&&q(X,ve)});return}const I=K(A);if(I===void 0){p.replaceChildren(),Je(!0);return}const Q=()=>{const X=r.get(I);X===void 0||d?Ee():(f.scrollTop=X,requestAnimationFrame(()=>{t!==null&&K(t)===I&&(f.scrollTop=X)}))};if(!d&&i.has(I)&&i.get(I)!==void 0){fe(i.get(I)),Je(!0),Q();return}d&&r.delete(I),i.set(I,void 0),fe(void 0),Je(!0),we(A).then(X=>{var me;i.set(I,X),(X==null?void 0:X.ok)===!0&&X.messages!==void 0&&((me=e.onTranscript)==null||me.call(e,A,X.messages)),!(t===null||K(t)!==I)&&(fe(X),Je(),Q())},X=>{const me={ok:!1,error:X instanceof Error?X.message:String(X)};i.set(I,me),t!==null&&K(t)===I&&fe(me)})}function ee(d){return((o==null?void 0:o.tasks)??[]).filter(A=>A.team===d)}function te(d){return((o==null?void 0:o.tasksDead)??[]).filter(A=>A.team===d)}let Ce="";function Be(d){return d.reason==="fire-forget"?{text:"已过期(免回执)",tone:"muted",hint:"免回执消息到 24h TTL 归档,属正常记账"}:{text:"死信",tone:"danger",hint:d.reason!==void 0&&d.reason!=="unspecified"?`${d.reason}:超过 24h TTL 仍未结算,需在台账清账`:"超过 24h TTL 仍未结算,需在台账清账"}}function Ye(d,A){const I=d.direction==="inbound";if(d.receiptExpected===!1)return{text:I?"来信 · 无需回执":"已送达 · 无回执",tone:"muted",hint:"免回执消息:不等回执,24h 后自动归档"};const Q=Dt(d,A),X=I?Q?"待本机回执 · 超 1 小时":"待本机回执":Q?"陈旧":"待回执",me=d.status!=="pending"?` · ${d.status}`:"";return{text:`${X}${me}`,tone:Q?"warn":"wait",hint:`${I?"对方等待本机回执;":""}${I?"收到":"派发"}于 ${dn(d.startedAt,A)}`}}function qe(d,A){const I=`结算于 ${dn(d.resolvedAt,A)}`;if(d.receiptExpected===!1&&d.endedBy==="abandoned")return d.late===!0?{text:"已移出(免回执) · 回执迟到",tone:"warn",hint:`${I};免回执消息本机移出后对方回执才到,结局不改写`}:{text:"已移出(免回执)",tone:"muted",hint:`${I};免回执消息,本机移出台账,不是失败`};if(d.endedBy==="abandoned"||d.endedBy==="cancelled"){const ge=d.endedBy==="cancelled"?"撤回":"放弃";return d.late===!0?{text:`已${ge} · 回执迟到`,tone:"warn",hint:`${I};本机${ge}之后对方回执才到,结局不改写`}:{text:`已${ge}`,tone:"muted",hint:`${I};本机${ge},未等到回执`}}if(d.endedBy==="echo")return{text:"已结算 · 内容回显",tone:"ok",hint:`${I};对方回了内容但未带正式回执,按内容回显结算`};if(d.endedBy===void 0&&d.outcome==="abandoned")return{text:"已放弃(本机或对方)",tone:"muted",hint:`${I};本机放弃或撤回,或对方回执报告放弃`};const Q=d.summary!==void 0&&d.summary!==""?` · ${d.summary}`:"";if(d.outcome==="abandoned")return{text:"已回执 · 对方放弃",tone:"warn",hint:`${I};对方回执报告放弃${Q}`};const X=bn.find(ge=>ge.key===d.outcome),me=(X==null?void 0:X.tone)==="completed"?"ok":(X==null?void 0:X.tone)==="failed"?"danger":(X==null?void 0:X.tone)==="rejected"?"warn":"muted";return d.outcome==="unclassified"?{text:"已回执",tone:"ok",hint:`${I};回执未带结论${Q}`}:{text:`已回执 · ${(X==null?void 0:X.label)??d.outcome}`,tone:me,hint:`${I}${Q}`}}function ut(d,A,I){const Q=te(A).find(ge=>ge.taskId===d);if(Q!==void 0)return Be(Q);const X=ee(A).find(ge=>ge.taskId===d);if(X!==void 0)return Ye(X,I);const me=((o==null?void 0:o.archived)??[]).find(ge=>ge.taskId===d&&ge.team===A);return me!==void 0?qe(me,I):u.has(d)?{text:"已离开台账",tone:"muted",hint:"已结算、放弃或撤回之一;主机未给出这条的结局(旧主机,或已超出最近 64 条归档)"}:{text:"已派发",tone:"muted",hint:"异步送达;回执到达后进台账"}}function kt(d){const A=e.now(),I=l.get(d)??[],Q=new Set(I.map(ne=>ne.taskId).filter(ne=>ne!==void 0)),X=ne=>ne!==void 0&&ne!==""?ne:"(无摘要)",me=ee(d).filter(ne=>!Q.has(ne.taskId)).map(ne=>({at:ne.startedAt,side:ne.direction==="inbound"?"theirs":"mine",text:X(ne.brief),status:Ye(ne,A),taskId:ne.taskId})),ge=te(d).filter(ne=>!Q.has(ne.taskId)).map(ne=>{var Te;const We=ne.direction??b.get(ne.taskId)??(((Te=ne.peer)==null?void 0:Te.startsWith("local:"))===!0?"inbound":void 0);return{at:ne.startedAt,side:We==="inbound"?"theirs":We==="outbound"?"mine":"system",text:X(ne.brief),status:Be(ne),taskId:ne.taskId}}),ve=I.map(ne=>({at:ne.at,side:"mine",text:ne.text,status:ne.state==="sending"?{text:"发送中…",tone:"muted"}:ne.state==="failed"?{text:`失败:${ne.error??"未知原因"}`,tone:"danger"}:ne.taskId!==void 0?ut(ne.taskId,d,A):{text:"已派发",tone:"muted"},taskId:ne.taskId}));return[...me,...ge,...ve].sort((ne,We)=>ne.at-We.at)}function Je(d=!1){const A=t,I=A!==null?mn(A):void 0,Q=I!==void 0?kt(I):[],X=JSON.stringify([I??"",...Q.map(ve=>[ve.taskId??"",ve.side,ve.text,ve.status.text])]);if(!d&&X===Ce)return;Ce=X;const me=Re();if(R.replaceChildren(),Q.length===0)return;const ge=ye("div","wb-chat-divider");ge.textContent="台账往来 · 异步送达,回执进台账",R.appendChild(ge);for(const ve of Q){const ne=ve.side==="mine"?"wb-msg wb-msg-user wb-msg-out":ve.side==="theirs"?"wb-msg wb-msg-assistant wb-msg-in":"wb-msg wb-msg-ledger",We=ye("div",ne);We.appendChild(ye("span","wb-msg-who")).textContent=ve.side==="mine"?"我":ve.side==="theirs"?"对方":"台账记录",We.appendChild(ye("div","wb-msg-text")).textContent=ve.text;const Te=ye("div","wb-msg-meta");ve.taskId!==void 0&&(Te.appendChild(ye("span","wb-msg-task")).textContent=ve.taskId);const Xe=ye("span",`wb-msg-status is-${ve.status.tone}`);Xe.textContent=ve.status.text,ve.status.hint!==void 0&&(Xe.title=ve.status.hint),Te.appendChild(Xe),We.appendChild(Te),R.appendChild(We)}me&&Ee()}function Qe(d){const A=d.text.value.length;d.note.classList.remove("is-error"),d.note.textContent=A>Tt*.9?`${A}/${Tt}`:"Enter 发送 · Shift+Enter 换行",A>Tt&&d.note.classList.add("is-error"),d.submit.disabled=d.text.value.trim()===""||A>Tt}function vt(d){d.style.height="auto",d.style.height=`${Math.min(d.scrollHeight,160)}px`}function St(d){const A=ye("form","wb-dispatch-form wb-chat-composer"),I=document.createElement("textarea");I.className="wb-dispatch-text",I.rows=1,I.placeholder="发一句话任务给这个节点…",I.setAttribute("aria-label","发送消息");const Q=ye("button","wb-dispatch-submit");Q.type="submit",Q.textContent="发送",Q.setAttribute("aria-label","发送");const X=ye("div","wb-dispatch-note");X.setAttribute("aria-live","polite");const me=ye("div","wb-chat-composer-row");me.append(I,Q),A.append(me,X);const ge={team:d,form:A,text:I,note:X,submit:Q};return I.addEventListener("input",()=>{vt(I),Qe(ge)}),I.addEventListener("keydown",ve=>{ve.key!=="Enter"||ve.shiftKey||ve.ctrlKey||ve.altKey||ve.metaKey||ve.isComposing||(ve.preventDefault(),A.requestSubmit())}),A.addEventListener("submit",ve=>{ve.preventDefault();const ne=I.value.trim();if(ne===""||ne.length>Tt||e.dispatchQuick===void 0)return;const We={text:ne,at:e.now(),state:"sending"},Te=l.get(d)??[];Te.push(We),l.set(d,Te),I.value="",vt(I),Qe(ge),I.focus({preventScroll:!0}),Je(),Ee(),e.dispatchQuick(d,ne).then(Xe=>Xe,Xe=>({ok:!1,error:Xe instanceof Error?Xe.message:String(Xe)})).then(Xe=>{Xe.ok===!0?(We.state="sent",We.taskId=Xe.task_id,X.classList.remove("is-error"),X.textContent=`已派发${Xe.task_id!==void 0?` · ${Xe.task_id}`:""} · 回执将入台账`):(We.state="failed",We.error=Xe.error??"未知原因",I.value===""&&(I.value=ne,vt(I)),X.classList.add("is-error"),X.textContent=`失败:${We.error}`,Q.disabled=I.value.trim()===""),t!==null&&mn(t)===d&&Je()})}),Qe(ge),ge}function Se(){const d=t;if(j.replaceChildren(),d===null)return;const A=mn(d);if(A!==void 0&&e.dispatchQuick!==void 0){let Q=m.get(A);Q===void 0&&(Q=St(A),m.set(A,Q)),j.appendChild(Q.form),s&&(s=!1,Q.text.focus({preventScroll:!0}));return}s=!1;const I=ye("div","wb-chat-readonly");I.textContent=d.kind==="log"?"只读日志:此会话不在网络目录,不能从这里派发。":d.kind==="peer"?"对端主机:选择会话阅读;要派发请打开它的远端会话节点。":"此节点没有可派发的路由。",j.appendChild(I)}function Ie(){Me(),U(),de(),Se()}function tt(d){const A=t!==null&&On(t)===On(d);t=d,A||(s=!0),Ie(),x.classList.add("is-open")}function ft(){t=null,x.classList.remove("is-open")}function At(d){o=d;for(const I of(d==null?void 0:d.tasks)??[])u.add(I.taskId),b.set(I.taskId,I.direction==="inbound"?"inbound":"outbound");const A=t;if(A!==null){if(A.kind==="session"&&d!==null){const I=(d.sessions??[]).find(Q=>Q.id===A.id);I!==void 0&&(A.title=lt(I),A.live=I.live)}Me(),Je()}}return{root:x,open:tt,close:ft,isOpen:()=>t!==null,update:At}}function Yo(e,t,o){const s=document.createElement("section"),n=document.createElement("h4");n.textContent="会话席位名(仅人工设定)",s.appendChild(n);const i=document.createElement("p");i.className="wb-hint",i.textContent="稳定展示名,不改变会话标题、路由句柄或准入。留空并保存可清除。",s.appendChild(i);const r=document.createElement("select");r.setAttribute("aria-label","选择命名的本机会话");for(const N of new Set([...e.map(Y=>Y.id),...Object.keys(t)])){const Y=e.find(V=>V.id===N),re=document.createElement("option");re.value=N,re.textContent=(t[N]??(Y==null?void 0:Y.name)??(Y==null?void 0:Y.label)??N)+" · "+N,r.appendChild(re)}const c=document.createElement("input");c.type="text",c.maxLength=64,c.setAttribute("aria-label","人工席位名"),c.placeholder="例如:开发席";const l=document.createElement("button");l.type="submit",l.textContent="保存席位名",l.className="wb-member-submit";const u=document.createElement("form");u.className="wb-member-add",u.append(r,c,l);const b=document.createElement("p");b.className="wb-hint",b.setAttribute("role","status"),b.setAttribute("aria-live","polite");let m=!1;const x=()=>{c.value=t[r.value]??"",l.disabled=m||r.value===""};return r.addEventListener("change",x),x(),u.addEventListener("submit",async N=>{if(N.preventDefault(),m||r.value==="")return;const Y=r.value,re=c.value.trim(),V={...t};re===""?delete V[Y]:V[Y]=re,m=!0,l.disabled=!0,r.disabled=!0,c.disabled=!0;try{const M=await o(V);M.ok?(delete t[Y],re!==""&&(t[Y]=re),b.textContent="席位名已保存;目录将随状态刷新。"):b.textContent=M.error??"保存失败"}catch(M){b.textContent="保存失败:"+String(M)}finally{m=!1,r.disabled=!1,c.disabled=!1,x()}}),s.append(u,b),s}function Wo(e,t){const o=document.createElement("form");o.className="wb-cli-home";const s=document.createElement("button");s.type="button",s.textContent="指定 home",s.className="wb-member-submit";const n=document.createElement("select");n.className="wb-member-pick",n.setAttribute("aria-label","选择 CLI home 主机"),n.hidden=!0;const i=document.createElement("button");i.type="submit",i.textContent="确认 home",i.className="wb-member-submit",i.hidden=!0,i.disabled=!0;const r=document.createElement("div");r.className="wb-hint",r.setAttribute("role","status"),r.setAttribute("aria-live","polite"),r.textContent="home 未确定;点击指定 home 现读已链接主机名片。";let c=!1;return s.addEventListener("click",async()=>{var l;if(!c){c=!0,s.disabled=!0,i.disabled=!0,r.textContent="正在现读主机名片…";try{const u=await e();if(!u.ok)throw Error(u.error??"候选读取失败");if(u.held){s.hidden=!0,n.hidden=!0,i.hidden=!0,n.replaceChildren(),r.textContent="本机持有,无需指定";return}n.replaceChildren(new Option("请选择 home 主机…","",!0,!0));for(const m of u.homes??[])n.appendChild(new Option(m,m));n.hidden=!1,i.hidden=!1,s.textContent="刷新候选";const b=((l=u.homes)==null?void 0:l.length)??0;r.textContent=(u.unreadable?"有 "+u.unreadable+" 台对端名片读不到;":"")+(b>1?"多台已链接主机列出该句柄,请显式选择。":b===1?"找到 1 台已链接主机;仍需你显式确认。":"当前没有已链接且列出该句柄的可选主机。")}catch(u){r.textContent="读取失败:"+String(u),n.hidden=!0,i.hidden=!0}finally{c=!1,s.disabled=!1}}}),n.addEventListener("change",()=>{i.disabled=c||n.value===""}),o.addEventListener("submit",async l=>{if(l.preventDefault(),!(c||n.value==="")){c=!0,s.disabled=!0,n.disabled=!0,i.disabled=!0;try{r.textContent=await t(n.value)?"home 已指定:"+n.value:"指定失败:主机可能已离线或不再列出该句柄,请刷新后重选。"}catch(u){r.textContent="指定失败:"+String(u)}finally{c=!1,s.disabled=!1,n.disabled=!1,i.disabled=n.value===""}}}),o.append(s,n,i,r),o}const co="dsh-a2a.rail.tab";function Xo(){try{return window.localStorage.getItem(co)}catch{return null}}function Ko(e){try{window.localStorage.setItem(co,e)}catch{}}function Uo(e,t={}){var V;const o=document.createElement("aside");o.className="wb-rail";const s=document.createElement("div");s.className="wb-tabs",s.setAttribute("role","tablist"),s.setAttribute("aria-label","工作台侧栏");const n=document.createElement("div");n.className="wb-tabpanels",o.append(s,n);const i=new Map,r=new Map,c=new Map,l=new Set;for(const M of e){const C=document.createElement("button");C.type="button",C.className="wb-tab",C.id=`wb-tab-${M.key}`,C.dataset.sec=M.key,C.setAttribute("role","tab"),C.setAttribute("aria-controls",`wb-panel-${M.key}`);const S=document.createElement("span");S.className="wb-tab-label",S.textContent=M.label;const E=document.createElement("span");E.className="wb-tab-badge",C.append(S,E),C.addEventListener("click",()=>N(M.key)),s.appendChild(C);const G=document.createElement("section");G.className="wb-tabpanel",G.id=`wb-panel-${M.key}`,G.dataset.sec=M.key,G.setAttribute("role","tabpanel"),G.setAttribute("aria-labelledby",C.id),G.tabIndex=-1,n.appendChild(G),i.set(M.key,C),r.set(M.key,G),c.set(M.key,E)}const u=()=>e.map(M=>M.key).filter(M=>!l.has(M)),b=Xo();let m=((V=e.find(M=>M.key===b))==null?void 0:V.key)??e[0].key;s.addEventListener("keydown",M=>{const C=u(),S=C.indexOf(m);let E;M.key==="ArrowRight"?E=C[(S+1)%C.length]:M.key==="ArrowLeft"?E=C[(S-1+C.length)%C.length]:M.key==="Home"?E=C[0]:M.key==="End"&&(E=C[C.length-1]),E!==void 0&&(M.preventDefault(),N(E,{focus:!0}))});function x(){for(const M of e){const C=M.key===m,S=i.get(M.key);S.setAttribute("aria-selected",String(C)),S.tabIndex=C?0:-1,S.classList.toggle("is-active",C),S.hidden=l.has(M.key),r.get(M.key).hidden=!C}}function N(M,C={}){var E;if(l.has(M))return;const S=M!==m;m=M,Ko(M),x(),C.focus===!0&&i.get(M).focus(),S&&((E=t.onChange)==null||E.call(t,M))}function Y(M,C,S){const E=c.get(M);E.textContent=C,E.className=`wb-tab-badge${S!==void 0?` is-${S}`:""}`}function re(M,C){C?l.add(M):l.delete(M),l.has(m)&&(m=u()[0]??e[0].key),x()}return x(),{root:o,panel:M=>r.get(M),select:N,selected:()=>m,setBadge:Y,setHidden:re}}const gn="application/x-dsh-session";function qo(e,t){e.draggable=!0,e.classList.add("is-draggable"),e.title=`${e.title===""?t:e.title} · 可拖入画布队`,e.addEventListener("dragstart",o=>{o.dataTransfer!==null&&(o.dataTransfer.setData(gn,t),o.dataTransfer.effectAllowed="copy")})}function zo(e,t){const o=n=>n.dataTransfer!==null&&[...n.dataTransfer.types].includes(gn),s=n=>{for(const[i,r]of t.frames())r.classList.toggle("drop-target",i===n)};e.addEventListener("dragover",n=>{if(!o(n))return;const i=t.frameAt(n.clientX,n.clientY);s(i),i!==void 0&&(n.preventDefault(),n.dataTransfer.dropEffect="copy")},t.signal),e.addEventListener("dragleave",n=>{o(n)&&(n.relatedTarget===null||!e.contains(n.relatedTarget))&&s(void 0)},t.signal),e.ownerDocument.addEventListener("dragend",()=>s(void 0),t.signal),e.addEventListener("drop",n=>{if(!o(n))return;s(void 0);const i=t.frameAt(n.clientX,n.clientY),r=n.dataTransfer.getData(gn);i===void 0||r===""||(n.preventDefault(),t.drop(i,r))},t.signal)}const Jo=[{key:"all",label:"全部",hint:"不过滤:目录全部条目"},{key:"local",label:"本机",hint:"本机会话节点(现场 + 冷启动)"},{key:"canvas",label:"队",hint:"画布队(人类手工分配的组队)"},{key:"remote",label:"远端",hint:"远端会话队(来自对端卡片)"},{key:"logs",label:"日志",hint:"本机日志:不在网络目录里的会话档案"}];function ot(e,t){const o=document.createElement(e);return t!==void 0&&(o.className=t),o}function Yt(...e){const t=[];for(const o of e)o!==void 0&&(typeof o=="string"?t.push(o):t.push(...o));return t.join(" ").toLowerCase()}function Vo(e,t){const o=Math.max(0,Math.round((t-e)/1e3));if(o<60)return"刚刚";const s=Math.round(o/60);if(s<60)return`${s} 分钟前`;const n=Math.round(s/60);return n<48?`${n} 小时前`:`${Math.round(n/24)} 天前`}function Fn(e){return e>=1e6?`${(e/1e6).toFixed(1)} MB`:e>=1e3?`${Math.round(e/1e3)} KB`:`${e} B`}function Go(e,t){const o=new Date(t);o.setHours(0,0,0,0);const s=o.getTime();return e>=s?"今天":e>=s-864e5?"昨天":"更早"}function Qo(e,t){var S,E,G;e.replaceChildren();const{state:o,search:s,filter:n}=t,i=s!==""||n!=="all",r=(y,f)=>(n==="all"||n===y)&&(s===""||f.includes(s)),c=(y,f,_)=>{const p=ot("div","wb-dir-group"),R=ot("div","wb-dir-head");return R.appendChild(ot("span","wb-dir-head-label")).textContent=`${y} · ${f}`,_!==void 0&&(R.appendChild(ot("span","wb-dir-head-note")).textContent=_),p.appendChild(R),e.appendChild(p),p},l=(y,f,_,p,R,j,K)=>{const we=ot("button","wb-item");we.type="button",we.appendChild(ot("span",`wb-dot ${f}`)).textContent=_;const Me=ot("span","wb-item-text");return Me.appendChild(ot("span","wb-item-label")).textContent=p,R!==""&&(Me.appendChild(ot("span","wb-item-sub")).textContent=R),we.appendChild(Me),K!==void 0&&(we.title=K),we.addEventListener("click",j),y.appendChild(we),we},u=(y,f)=>{if(f===void 0||f.length===0)return;const _=ot("span","wb-item-badge"),p=f.map(R=>R.slice(R.lastIndexOf("/")+1));_.textContent=`▤ ${p.slice(0,2).join(" ")}${p.length>2?` +${p.length-2}`:""}`,_.title=`画布队:${f.join(" · ")}`,y.appendChild(_)},b=(o.sessions??[]).filter(y=>r("local",Yt(lt(y),y.team,y.label,y.id,y.canvasTeams))),m=b.filter(y=>y.live===!0),x=b.filter(y=>y.live!==!0);if(b.length>0){const y=c("本机会话",b.length,x.length>0?`${m.length} 在线 · ${x.length} 冷`:void 0);for(const f of[...m,...x]){const _=f.live===!0,p=f.nodePromptMissing===!0,R=l(y,_?"wb-dot-live":"wb-dot-cold",_?"●":"○",lt(f),_?f.team:`冷 · ${f.team}`,()=>t.openChat({kind:"session",id:f.id,title:lt(f),sub:f.team,team:f.team,live:f.live}),f.id);if(p){R.classList.add("is-node-prompt-missing");const j=ot("span","wb-node-warning");j.textContent="本会话的组装不含节点段",(S=R.querySelector(".wb-item-text"))==null||S.appendChild(j)}u(R,f.canvasTeams),qo(R,f.id)}}const N=(((E=o.canvas)==null?void 0:E.teams)??[]).filter(y=>r("canvas",Yt(y.name,y.team,y.members.map(f=>f.team??f.id))));if(N.length>0){const y=c("画布队",N.length);for(const f of N){const _=f.members.filter(p=>p.remote===!0).length;l(y,"wb-dot-canvas","▤",f.name,`${f.members.length} 成员${_>0?` · ${_} 远端`:""}`,()=>t.selectCanvas(f),f.team)}}const Y=(o.remote??[]).filter(y=>r("remote",Yt(lt(y),y.team,y.origin,y.workspace,y.canvasTeams)));if(Y.length>0){const y=c("远端节点",Y.length);for(const f of Y){const _=l(y,"wb-dot-remote","◇",lt(f),f.origin!==void 0&&f.origin!==""?f.origin:f.team,()=>t.openChat({kind:"remote",team:f.team,title:lt(f),sub:f.team,row:f}),f.team);if(f.unreachable===!0){_.classList.add("is-unreachable");const p=ot("span","wb-unreachable-note");p.textContent="对端未应答(显示的是最后已知状态)",(G=_.querySelector(".wb-item-text"))==null||G.appendChild(p)}u(_,f.canvasTeams)}}const re=new Set((o.sessions??[]).map(y=>y.id)),V=t.logs.filter(y=>!re.has(y.id)&&r("logs",Yt(y.id,t.titles.get(y.id))));if(V.length>0){const y=t.logTotal!==void 0&&t.logTotal>t.logs.length,f=c("本机日志",V.length,y?`显示 ${t.logs.length} / 共 ${t.logTotal}`:void 0);let _="";for(const p of[...V].sort((R,j)=>j.mtimeMs-R.mtimeMs)){const R=Go(p.mtimeMs,t.now);R!==_&&(_=R,f.appendChild(ot("div","wb-dir-day")).textContent=R);const j=t.titles.get(p.id),K=l(f,"wb-dot-log","❐",j??`会话 …${p.id.slice(-12)}`,`${Vo(p.mtimeMs,t.now)} · ${Fn(p.sizeBytes)}`,()=>t.openChat({kind:"log",id:p.id,title:j??`…${p.id.slice(-12)}`,sub:"本机日志"}),`${p.id}
|
|
3
|
-
${new Date(p.mtimeMs).toLocaleString()} · ${Fn(p.sizeBytes)}`);j===void 0&&K.classList.add("is-untitled")}}b.length+N.length+Y.length+V.length===0&&(e.appendChild(ot("div","wb-dir-empty")).textContent=i?"无匹配条目":"目录为空");const M=o.sessions??[];return`${M.filter(y=>y.live===!0).length}/${M.length}`}const lo="dsh-a2a.logtitles",Zo=300,Pn=60;function es(){try{const e=window.localStorage.getItem(lo),t=e===null?null:JSON.parse(e);if(t!==null&&typeof t=="object")return new Map(Object.entries(t).filter(o=>typeof o[1]=="string"))}catch{}return new Map}function ts(e,t,o){const s=o.find(r=>r.role==="user"&&r.text.trim()!=="")??o.find(r=>r.text.trim()!=="");if(s===void 0)return!1;const n=s.text.trim().split(`
|
|
4
|
-
`)[0].trim(),i=n.length>Pn?`${n.slice(0,Pn-1)}…`:n;if(e.get(t)===i)return!1;for(e.delete(t),e.set(t,i);e.size>Zo;)e.delete(e.keys().next().value);try{window.localStorage.setItem(lo,JSON.stringify(Object.fromEntries(e)))}catch{}return!0}function ht(e){return e.name??e.team??e.label??""}function _t(e,t){const o=Math.max(0,Math.round((t-e)/1e3));if(o<90)return`${o}s`;const s=Math.round(o/60);if(s<90)return`${s}m`;const n=Math.round(s/60);return n<48?`${n}h`:`${Math.round(n/24)}d`}function T(e,t){const o=document.createElement(e);return t!==void 0&&(o.className=t),o}function Dn(e,t,o){const s=T("div","wb-kv");s.appendChild(T("span","wb-kv-k")).textContent=t,s.appendChild(T("span","wb-kv-v")).textContent=o,e.appendChild(s)}function ns(e){try{return new URL(e).host}catch{return e}}const os=[{key:"directory",label:"目录"},{key:"hosts",label:"主机"},{key:"ledger",label:"台账"},{key:"activity",label:"活动"},{key:"plan",label:"规划"}];function ss(e){const t=e.board;let o="data",s,n=null,i="",r="all",c=null;const l=new Map;let u=null,b=[],m;const x=es();let N=!1;const Y=T("div","wb");Y.setAttribute("data-testid","wb-root");const re=T("header","wb-header"),V=T("button","wb-icon-btn wb-menu");V.type="button",V.dataset.testid="wb-menu",V.setAttribute("aria-label","打开目录抽屉"),V.textContent="☰",V.addEventListener("click",()=>Y.classList.toggle("is-rail-open")),re.appendChild(V);const M=T("div","wb-title");M.appendChild(T("span","wb-title-main")).textContent="A2A 工作台";const C=T("span","wb-badge");M.appendChild(C),re.appendChild(M);const S=T("button","wb-icon-btn wb-owner-btn");S.type="button",S.dataset.testid="wb-owner-btn",S.setAttribute("aria-label","主人设置"),S.title="主人设置:席位名 / 入网白名单 / 可见性 / 发布",S.textContent="⚙",S.addEventListener("click",()=>{A=!A,Q()}),re.appendChild(S);const E=T("div","wb-header-stats");re.appendChild(E);const G=T("button","wb-icon-btn wb-rail-toggle");G.type="button",G.dataset.testid="wb-rail-toggle",G.setAttribute("aria-label","折叠/展开侧栏"),G.textContent="◧",G.addEventListener("click",()=>{Y.classList.toggle("is-rail-collapsed"),o==="canvas"&&t!==void 0&&t.activate()}),re.appendChild(G);const y=T("div","wb-body"),f=Uo(os),_=f.root,p=T("div","wb-directory"),R=T("div","wb-dir-tools"),j=document.createElement("input");j.className="wb-search",j.type="search",j.placeholder="搜索:名称 / 队 / 会话 / 节点",j.setAttribute("aria-label","统一搜索目录"),j.addEventListener("input",()=>{i=j.value.trim().toLowerCase(),qe()}),R.appendChild(j);const K=T("div","wb-filters");for(const k of Jo){const w=T("button","wb-filter");w.type="button",w.textContent=k.label,w.dataset.filter=k.key,w.title=k.hint,w.addEventListener("click",()=>{r=k.key,qe()}),K.appendChild(w)}R.appendChild(K),f.panel("directory").appendChild(R),f.panel("directory").appendChild(p);const we=T("section","wb-pane"),Me=T("section","wb-pane"),D=T("section","wb-pane"),U=T("section","wb-pane"),ce=[["ledger",we],["activity",Me],["plan",D],["hosts",U]],Re=T("main","wb-stage"),Ee=T("section","wb-stage-board");t!==void 0&&(Ee.appendChild(t.root),Re.appendChild(Ee));const le=T("div","wb-data"),He=T("aside","wb-inspector"),fe=T("div","wb-inspector-head");fe.appendChild(T("span","wb-inspector-title")).textContent="详情";const q=T("button","wb-icon-btn");q.type="button",q.setAttribute("aria-label","关闭详情"),q.textContent="✕",q.addEventListener("click",()=>Ye(void 0)),fe.appendChild(q),He.appendChild(fe);const de=T("div","wb-inspector-body");He.appendChild(de);const ee=Bo({now:e.now,sessionLog:e.sessionLog,remoteSessionLog:e.remoteSessionLog,dispatchQuick:e.dispatchQuick,onTranscript:(k,w)=>{k.kind!=="log"&&k.kind!=="session"||ts(x,k.id,w)&&qe()}});Re.appendChild(le),y.appendChild(_),y.appendChild(Re),y.appendChild(He),y.appendChild(ee.root),Y.appendChild(re),Y.appendChild(y);function te(k){for(const[w,H]of ce){const $=k==="canvas"?f.panel(w):le;f.setHidden(w,k!=="canvas"),H.parentElement!==$&&$.appendChild(H)}}function Ce(){const w=t!==void 0&&t.available()?"canvas":"data";Y.dataset.mode=w,Ee.classList.toggle("is-hidden",w!=="canvas"),le.classList.toggle("is-hidden",w==="canvas"),te(w),w!==o&&(t!==void 0&&(w==="canvas"?t.activate():t.deactivate()),o=w)}function Be(k){for(;k.firstChild!==null;)k.removeChild(k.firstChild);return k}function Ye(k){s=k,((k==null?void 0:k.kind)!=="canvas"||(c==null?void 0:c.name)!==k.row.name)&&(c=null),(k==null?void 0:k.kind)!=="canvas"&&(u=null),me(),Y.classList.remove("is-rail-open")}function qe(){for(let w=0;w<K.children.length;w++){const H=K.children[w];H.classList.toggle("is-active",H.dataset.filter===r)}if(n===null){p.replaceChildren(T("div","wb-muted")),p.firstElementChild.textContent="载入中…",f.setBadge("directory","");return}const k=Qo(p,{state:n,logs:b,logTotal:m,titles:x,search:i,filter:r,now:e.now(),openChat:ne,selectCanvas:w=>Ye({kind:"canvas",row:w})});f.setBadge("directory",k)}function ut(){const k=Be(U);if(n===null){f.setBadge("hosts","");return}const w=e.now(),H=[...n.peers??[]].sort(($,L)=>{const O=se=>se.link==="linked"?0:1;return O($)-O(L)||(L.score??0)-($.score??0)});if(f.setBadge("hosts",H.length>0?`${H.filter($=>$.link==="linked").length}/${H.length}`:""),H.length===0){k.appendChild(T("div","wb-nodelist-empty")).textContent="暂无 tracked peer——配 peers 种子或等 referral 到达";return}for(const $ of H){const L=ns($.url),O=T("div","wb-host-row"),se=T("span","wb-host-lamp"),ae=$.lastContactAt,Z=ae===void 0?void 0:w-ae,xe=$.lastContactOk;Z===void 0?se.classList.add("is-unknown"):xe===!1&&Z<=5*6e4?se.classList.add("is-fail"):Z<=6e4?se.classList.add("is-live"):Z<=5*6e4?se.classList.add("is-warm"):se.classList.add("is-cold"),se.title=ae===void 0?"尚无接触记录":`最近接触 ${_t(ae,w)}${xe===!1?"(失败)":xe===!0?"(成功)":""}`,O.appendChild(se),O.appendChild(T("span","wb-host-name")).textContent=$.name!==void 0&&$.name!==""?$.name:L;const _e=T("span",`wb-host-badge ${$.link==="linked"?"is-linked":"is-stranger"}`);_e.textContent=`${$.link==="linked"?"linked":"stranger"} ${$.verified===!0?"✓":"✗"}`,_e.title=$.link==="linked"?`已建立运营者链接(互种或 canvas 引用);${$.verified===!0?"验签有效":"尚未持有验签通过的卡片"}`:"无运营者关系(验签 ≠ 关系)",O.appendChild(_e),$.version!==void 0&&$.version!==""&&(O.appendChild(T("span","wb-host-ver")).textContent=$.version),O.appendChild(T("span","wb-host-url mono")).textContent=L,O.setAttribute("role","button"),O.tabIndex=0,O.title=`${$.url} · score ${String($.score??0)}`;const J=()=>{ne({kind:"peer",id:`peer-${L}`,title:$.name!==void 0&&$.name!==""?$.name:L,sub:L,url:$.url})};O.addEventListener("click",J),O.addEventListener("keydown",Pe=>{(Pe.key==="Enter"||Pe.key===" ")&&(Pe.preventDefault(),J())}),k.appendChild(O)}}function kt(){if(n===null){we.replaceChildren(),f.setBadge("ledger","");return}const k=n,w=$=>{const L=(k.sessions??[]).find(se=>se.team===$);if(L!==void 0)return{kind:"session",id:L.id,title:ht(L),sub:L.team,team:L.team,live:L.live};const O=(k.remote??[]).find(se=>se.team===$);if(O!==void 0)return{kind:"remote",team:O.team,title:ht(O),sub:O.team,row:O}},H=Ro(we,{state:k,now:e.now(),abandon:($,L)=>e.abandon($,L),canOpenTeam:$=>w($)!==void 0,openTeam:$=>{const L=w($);return L===void 0?!1:(ne(L),!0)}});f.setBadge("ledger",H.badge,H.tone)}function Je(k,w,H){zt(k.appendChild(T("span","wb-row-team")),w,H)}function Qe(){var se;const k=Be(Me);if(n===null)return;const w=e.now(),H=n.inFlight??[];f.setBadge("activity",H.length>0?String(H.length):"",H.length>0?"accent":void 0);const $=T("div","wb-pane-head");if($.textContent=`在途 ${H.length} · 活动 ${((se=n.activity)==null?void 0:se.length)??0}`,k.appendChild($),H.length>0){const ae=T("div","wb-pane-subhead");ae.textContent="在途路由",k.appendChild(ae);for(const Z of H){const xe=T("div","wb-row");xe.appendChild(T("span","wb-row-dir")).textContent="→",Je(xe,n,Z.team),xe.appendChild(T("span","wb-row-meta")).textContent=`${Z.peer} · ${_t(Z.startedAt,w)}`,k.appendChild(xe)}}const L=T("div","wb-pane-subhead");L.textContent="活动环(最新在前)",k.appendChild(L);const O=n.activity??[];if(O.length===0){k.appendChild(T("div","wb-muted")).textContent="暂无活动";return}for(const ae of O){const Z=T("div","wb-row"),xe=T("span","wb-row-dir");xe.textContent=ae.dir==="fwd"?"⇢":ae.dir==="out"?"→":"←",ae.ok!==!0&&xe.classList.add("is-fail"),Z.appendChild(xe),Je(Z,n,ae.team),Z.appendChild(T("span","wb-row-meta")).textContent=`${ae.peer} · ${_t(ae.ts,w)}`,Z.appendChild(T("span","wb-row-badges")).textContent=ae.ok===!0?"":"失败",k.appendChild(Z)}}function vt(k){var se,ae;const w=e.now(),H=[],$=hn(k,w);$.deadLetters.length>0&&H.push({severity:"high",text:`清账 ${$.deadLetters.length} 条死信(目标早已离开或死信化,无回执可期)`});for(const Z of $.stale){const xe=Z.brief===void 0||Z.brief===""?"":`「${Z.brief}」`;H.push({severity:"normal",text:`催办 ${Z.taskId} → ${Fo(k,Z.team)}(等待 ${_t(Z.startedAt,w)} 无回执)${xe}`,brief:`a2a_route 催收回执:task ${Z.taskId}(team ${Z.team})${xe===""?"":`原任务「${Z.brief}」`}已派发 ${_t(Z.startedAt,w)},请回报结果或回执。`})}const L=(k.sessions??[]).filter(Z=>Z.live!==!0).map(Z=>ht(Z));if(L.length>0){const Z=L.slice(0,3).join("、")+(L.length>3?` 等 ${L.length} 个`:"");H.push({severity:"normal",text:`冷会话 ${L.length} 个(${Z}):在 GUI 打开即可唤醒加入面`})}for(const Z of((se=k.reconcile)==null?void 0:se.rows)??[])if(Z.needsRepair===!0){const xe=(k.sessions??[]).find(J=>J.id===Z.id),_e=xe!==void 0?`${ht(xe)}(${Z.id})`:Z.id;H.push({severity:"high",text:`reconcile 需修复:${_e} ${Z.error}`})}const O=((ae=k.idempotency)==null?void 0:ae.conflicts)??0;return O>0&&H.push({severity:"high",text:`幂等冲突 ${O} 例:人工核查 UNIQUE-ization 流量`}),H}function St(){const k=Be(D);if(n===null)return;const w=vt(n);f.setBadge("plan",w.length>0?String(w.length):"",w.some(L=>L.severity==="high")?"danger":void 0);const H=T("div","wb-pane-head");H.textContent=w.length===0?"网络健康——无待办行动":`待办行动 ${w.length}`,k.appendChild(H);for(const L of w){const O=T("div",`wb-action${L.severity==="high"?" wb-action-high":""}`);if(O.appendChild(T("span","wb-action-text")).textContent=L.text,L.brief!==void 0){const se=T("button","wb-btn");se.type="button",se.textContent="复制催办",se.addEventListener("click",()=>e.copy(L.brief??"")),O.appendChild(se)}k.appendChild(O)}const $=T("div","wb-pane-subhead");$.textContent="派单起草(复制后在任一会话粘贴执行)",k.appendChild($),k.appendChild(Se)}const Se=T("div","wb-draft"),Ie=document.createElement("select");Ie.className="wb-select";const tt=document.createElement("textarea");tt.className="wb-textarea",tt.rows=3,tt.placeholder="任务正文:目标、验收、期限…";const ft=T("button","wb-btn wb-btn-primary");ft.type="button",ft.textContent="复制任务书",ft.addEventListener("click",()=>{const k=Ie.value,w=tt.value.trim();k===""||w===""||e.copy(`a2a_route 派单 → ${k}:
|
|
5
|
-
${w}`)}),Se.appendChild(Ie),Se.appendChild(tt),Se.appendChild(ft);function At(){var L;const k=Ie.value;Be(Ie);const w=document.createElement("option");if(w.value="",w.textContent="选择目标队…",Ie.appendChild(w),n===null)return;const H=n,$=new Map;for(const O of H.sessions??[])O.team!==void 0&&O.team!==""&&$.set(O.team,`${ht(O)}(会话队)`);for(const O of((L=H.canvas)==null?void 0:L.teams)??[])$.set(O.team,`${O.name}(canvas 队)`);for(const O of H.remote??[])$.set(O.team,`${ht(O)}(远端)`);for(const[O,se]of $){const ae=document.createElement("option");ae.value=O,ae.textContent=`${se} · ${O}`,Ie.appendChild(ae)}k!==""&&$.has(k)&&(Ie.value=k)}let d,A=!1,I=null;function Q(){var k;me(),A&&((k=e.ownerSettingsRead)==null||k.call(e).then(w=>{if(A){if(w.ok!==!0){I=null,me();return}d=void 0,I={seatNames:w.seatNames??{},teamJoinAllowlist:w.teamJoinAllowlist??[],teamScopeInfo:w.teamScopeInfo!==!1,announce:w.announce===!0,announceRestartPending:w.announceRestartPending===!0},me()}}))}function X(k){const w=T("div","wb-card"),H=T("div","wb-inspector-head");H.appendChild(T("span","wb-inspector-title")).textContent="主人设置";const $=T("button","wb-icon-btn");if($.type="button",$.setAttribute("aria-label","关闭主人设置"),$.textContent="✕",$.addEventListener("click",()=>{A=!1,me()}),H.appendChild($),w.appendChild(H),e.ownerSettingsRead===void 0){const pe=T("div","wb-hint");pe.textContent="此宿主未提供主人设置面(旧版本)——升级后可用。",w.appendChild(pe),k.appendChild(w);return}if(I===null){const pe=T("div","wb-hint");pe.textContent="读取中…",w.appendChild(pe),k.appendChild(w);return}const L=I;d??(d=Yo((n==null?void 0:n.sessions)??[],L.seatNames,async pe=>{var it;const Oe=await((it=e.ownerSettingsWrite)==null?void 0:it.call(e,{seatNames:pe}));return Oe!=null&&Oe.ok?(L.seatNames=pe,{ok:!0}):{ok:!1,error:(Oe==null?void 0:Oe.error)??"保存失败"}})),w.appendChild(d);const O=T("div","wb-side-head");O.textContent="入网白名单(精确团队名)",w.appendChild(O);for(const pe of L.teamJoinAllowlist){const Oe=T("div","wb-member-row");Oe.appendChild(T("span","wb-member-label")).textContent=pe;const it=T("button","wb-member-remove");it.type="button",it.textContent="移除",it.addEventListener("click",()=>{var It;(It=e.ownerSettingsWrite)==null||It.call(e,{teamJoinAllowlist:L.teamJoinAllowlist.filter(cn=>cn!==pe)}).then(()=>Q())}),Oe.appendChild(it),w.appendChild(Oe)}const se=T("div","wb-member-add"),ae=T("input","wb-member-manual");ae.type="text",ae.placeholder="dsh/团队名(精确,无通配)",ae.setAttribute("aria-label","新增白名单团队名");const Z=T("button","wb-member-submit");Z.type="button",Z.textContent="加入";const xe=()=>{var Oe;const pe=ae.value.trim();pe===""||L.teamJoinAllowlist.includes(pe)||(Oe=e.ownerSettingsWrite)==null||Oe.call(e,{teamJoinAllowlist:[...L.teamJoinAllowlist,pe]}).then(()=>Q())};Z.addEventListener("click",xe),ae.addEventListener("keydown",pe=>{pe.key==="Enter"&&xe()}),se.append(ae,Z),w.appendChild(se);const _e=T("div","wb-side-head");_e.textContent="目录可见性(teamScopeInfo)",w.appendChild(_e);const J=T("div","wb-member-row"),Pe=T("button","wb-member-submit");Pe.type="button",Pe.textContent=L.teamScopeInfo?"已开:仅显示已加入团队(点击放开为全舰队可见)":"已关:全舰队可见(点击收窄为已加入团队)",Pe.addEventListener("click",()=>{var pe;(pe=e.ownerSettingsWrite)==null||pe.call(e,{teamScopeInfo:!L.teamScopeInfo}).then(()=>Q())}),J.appendChild(Pe),w.appendChild(J);const Ze=T("div","wb-hint");Ze.textContent="精度说明:teamScopeInfo 只管「目录显示范围」。关上它不会解锁任何通信准入——会话入网(S3)与目标级路由(F5)规则原样生效。",w.appendChild(Ze);const et=T("div","wb-side-head");et.textContent="节点发布(announce)",w.appendChild(et);const pt=T("div","wb-member-row"),Ve=T("button","wb-member-submit");if(Ve.type="button",Ve.textContent=L.announce?"已开:本节点发布签名卡(点击关闭)":"已关:本节点不发布(点击开启——重启宿主后生效)",Ve.addEventListener("click",()=>{var pe;(pe=e.ownerSettingsWrite)==null||pe.call(e,{announce:!L.announce}).then(()=>Q())}),pt.appendChild(Ve),w.appendChild(pt),L.announceRestartPending){const pe=T("div","wb-hint");pe.textContent="有 announce 变更待生效:重启宿主后按新配置发布。",w.appendChild(pe)}k.appendChild(w)}function me(){var $;const k=Be(de);if(A){He.classList.add("is-open"),X(k);return}if(He.classList.toggle("is-open",s!==void 0),s===void 0)return;const w=s,H=T("div","wb-card");if(w.kind==="canvas"){const L=((($=n==null?void 0:n.canvas)==null?void 0:$.teams)??[]).find(J=>J.name===w.row.name)??w.row;Dn(H,"Canvas 队",L.name),Dn(H,"路由队",L.team);const O=T("div","wb-side-head");if(O.textContent=`成员 · ${L.members.length}`,H.appendChild(O),L.members.length===0){const J=T("div","wb-muted");J.textContent="空队——用下方表单添加成员",H.appendChild(J)}for(const J of L.members){const Pe=T("div","wb-member-row"),Ze=J.cliHeld===!0?"本机持有,无需指定":J.remote===!0?J.cliHome===null?"◇ 远端 · home 未确定":"◇ 远端":J.live===!0?"● 现场":J.joined===!0?"○ 冷启":"· 未入网";Pe.appendChild(T("span","wb-member-dot")).textContent=Ze;const et=T("span","wb-member-label"),pt=((n==null?void 0:n.sessions)??[]).find(pe=>pe.id===J.id);et.textContent=J.remote===!0?J.id:pt!==void 0?ht(pt):J.id,et.title=J.cliHeld===!0?"本机持有,无需指定":J.cliHome!==void 0?J.cliHome??"home 未确定":J.team??J.id,Pe.appendChild(et);const Ve=T("button","wb-member-remove");if(Ve.type="button",Ve.textContent="移除",Ve.addEventListener("click",async()=>{Ve.disabled=!0,await e.canvasOp("remove-member",L.name,J.id)||(Ve.disabled=!1)}),Pe.appendChild(Ve),H.appendChild(Pe),J.cliHomeCleared===!0){const pe=T("div","wb-hint");pe.textContent="本机落户已清除旧 home 钉;户口离线后也不会恢复旧钉。",H.appendChild(pe)}if(J.cliHome===null&&J.cliHeld!==!0&&e.cliHomeOptions!==void 0){const pe=JSON.stringify([L.name,J.id]);let Oe=l.get(pe);Oe===void 0&&(Oe=Wo(()=>e.cliHomeOptions(L.name,J.id),it=>e.canvasOp("add-member",L.name,J.id,it)),l.set(pe,Oe)),H.appendChild(Oe)}}if((c==null?void 0:c.name)!==L.name){const J=T("form","wb-member-add"),Pe=document.createElement("select");Pe.className="wb-member-pick",Pe.setAttribute("aria-label","选择成员");const Ze=document.createElement("input");Ze.type="text",Ze.className="wb-member-manual",Ze.placeholder="或输入远端句柄 zone/id8",Ze.setAttribute("aria-label","远端成员句柄");const et=T("button","wb-member-submit");et.type="submit",et.textContent="添加",J.appendChild(Pe),J.appendChild(Ze),J.appendChild(et),J.addEventListener("submit",async pt=>{pt.preventDefault();const Ve=Ze.value.trim(),pe=Ve!==""?Ve:Pe.value;if(pe==="")return;et.disabled=!0;const Oe=await e.canvasOp("add-member",L.name,pe);et.disabled=!1,Oe&&(Ze.value="")}),c={name:L.name,form:J,pick:Pe,manual:Ze}}const se=c.pick,ae=se.value;Be(se),se.appendChild(new Option("本机会话(现场/冷启动)…","",!0,!0));const Z=new Set(L.members.map(J=>J.id));for(const J of(n==null?void 0:n.sessions)??[])Z.has(J.id)||se.appendChild(new Option(`${ht(J)} — 本机`,J.id));let xe=!1;for(const J of(n==null?void 0:n.remote)??[])J.team.includes("/")&&(Z.has(J.team)||(xe||(se.appendChild(new Option("远端会话队(目录卡片)…","",!0,!1)),xe=!0),se.appendChild(new Option(`${ht(J)} — 远端`,J.team))));xe||se.appendChild(new Option("(暂无可拉入的远端会话队——见下方说明)","",!0,!1)),ae!==""&&Array.from(se.options).some(J=>J.value===ae)&&(se.value=ae),H.appendChild(c.form);const _e=T("div","wb-hint");_e.textContent="成员由人类在此手工分配(agent 不可自组队)。远端成员走对端目录路由,不做本机冷唤醒;地址由目录在派发时重解析。远端下拉只列 zone/id8 会话句柄——若为空,说明目录里还没有已链接对端的会话队(未链接的对端只给最小卡);此时可在输入框手输句柄(如 dsh/xxxxxxxx)先把人拉进来,句柄本身即链接手势。",H.appendChild(_e),e.dispatchQuick!==void 0&&H.appendChild(ve(L.team))}k.appendChild(H)}function ge(k){const w=T("form","wb-dispatch-form"),H=document.createElement("textarea");H.className="wb-dispatch-text",H.placeholder="一句话任务…(≤4000 字符,异步送达,回执进台账)",H.setAttribute("aria-label","快派消息");const $=T("button","wb-dispatch-submit");$.type="submit",$.textContent="发送";const L=T("div","wb-dispatch-note");return w.appendChild(H),w.appendChild($),w.appendChild(L),H.addEventListener("keydown",O=>{O.key!=="Enter"||O.shiftKey||O.ctrlKey||O.altKey||O.metaKey||O.isComposing||(O.preventDefault(),$.disabled||w.requestSubmit())}),w.addEventListener("submit",async O=>{var Z;O.preventDefault();const se=H.value.trim();if(se===""||$.disabled)return;$.disabled=!0,L.textContent="派发中…";let ae;try{ae=await(((Z=e.dispatchQuick)==null?void 0:Z.call(e,k,se))??Promise.resolve({ok:!1,error:"dispatch unavailable"}))}catch(xe){ae={ok:!1,error:xe instanceof Error?xe.message:String(xe)}}$.disabled=!1,ae.ok===!0&&(H.value=""),H.focus({preventScroll:!0}),L.textContent=ae.ok===!0?`已派发${ae.task_id!==void 0?` · ${ae.task_id}`:""} · 回执将入台账(待回执)`:`失败:${ae.error??"未知原因"}`}),{form:w,text:H,note:L}}function ve(k){const w=T("div","wb-dispatch"),H=T("div","wb-side-head");return H.textContent="快派",w.appendChild(H),(u==null?void 0:u.team)!==k&&(u={team:k,...ge(k)}),w.appendChild(u.form),w}function ne(k){ee.open(k),Y.classList.remove("is-rail-open")}function We(k){if(n===null)return;const w=(n.sessions??[]).find($=>$.id===k);if(w!==void 0){ne({kind:"session",id:k,title:ht(w),sub:w.team,team:w.team,live:w.live});return}if(k.startsWith("peer-")){const $=k.slice(5),L=(n.peers??[]).find(O=>O.url.includes($));ne({kind:"peer",id:k,title:L!==void 0?L.url:$,sub:$,url:L==null?void 0:L.url});return}b.find($=>$.id===k)!==void 0&&ne({kind:"log",id:k,title:`…${k.slice(-12)}`,sub:"档案"})}function Te(){var Z,xe;C.textContent=(n==null?void 0:n.version)!==void 0?`v${n.version}`:"",C.hidden=(n==null?void 0:n.version)===void 0;const k=Be(E);if(n===null)return;const w=[],H=hn(n,e.now()),$=H.deadLetters.length;$>0&&w.push({text:`死信 ${$}`,tone:"danger",title:"超过 24h TTL 仍未结算的任务(unconsumed),需在台账清账",tab:"ledger",group:"死信"});const L=H.stale.length;L>0&&w.push({text:`陈旧 ${L}`,tone:"warn",title:"我方派发、要回执、已等待 ≥1h 仍未回执(可催办;免回执行不算)",tab:"ledger",group:"陈旧"});const O=H.owedOverdue.length;O>0&&w.push({text:`欠回执 ${O}`,tone:"warn",title:"对方投递给本机、已等待本机回执超过 1 小时",tab:"ledger",group:"待本机回执"});const se=((Z=n.idempotency)==null?void 0:Z.conflicts)??0;se>0&&w.push({text:`幂等冲突 ${se}`,tone:"danger",title:"同一幂等键对应了不同载荷,需人工核查",tab:"ledger",group:"取证"});const ae=(((xe=n.reconcile)==null?void 0:xe.rows)??[]).filter(_e=>_e.needsRepair===!0).length;if(ae>0&&w.push({text:`需修复 ${ae}`,tone:"danger",title:"reconcile 无法自动恢复的会话,见行动计划",tab:"plan"}),w.length===0){k.appendChild(T("span","wb-header-ok")).textContent="● 无异常";return}for(const _e of w){const J=T("button",`wb-alert wb-alert-${_e.tone}`);J.type="button",J.textContent=_e.text,J.title=`${_e.title}(点击查看)`,J.addEventListener("click",()=>Xe(_e.tab,_e.group)),k.appendChild(J)}}function Xe(k,w){var L;const H=ce.find(([O])=>O===k)[1];o==="canvas"&&(Y.classList.add("is-rail-open"),f.select(k,{focus:!1}));const $=w===void 0?H:w==="取证"?H.querySelector("details.wb-led-forensics"):Array.from(H.querySelectorAll(".wb-led-group")).find(O=>O.dataset.group===w)??null;$!==null&&($ instanceof HTMLDetailsElement&&($.open=!0),(L=$.scrollIntoView)==null||L.call($,{block:"start",behavior:"smooth"}))}function Lt(k){var H;const w=new Set((((H=k==null?void 0:k.canvas)==null?void 0:H.teams)??[]).flatMap($=>$.members.filter(L=>L.cliHome===null&&L.cliHeld!==!0).map(L=>JSON.stringify([$.name,L.id]))));for(const $ of l.keys())w.has($)||l.delete($);n=k,e.sessionLogList!==void 0&&!N&&(N=!0,e.sessionLogList().then($=>{b=$.ok&&$.sessions!==void 0?$.sessions:[],m=$.ok?$.count:void 0}).catch(()=>{}).finally(()=>{N=!1,qe()})),Te(),qe(),At(),ut(),kt(),ee.update(k),Qe(),St(),me(),Ce()}function nt(k){if(k==="board"){Ce();return}f.select(k)}return Lt(null),{root:Y,update:Lt,mode:()=>o,selectTab:nt,openNodeChat:We}}const bt=1e6,Cn=.25,kn=3,mo=256,uo=96;function Mt(e){const t=typeof e=="number"?e:Number.NaN;if(Number.isFinite(t))return Math.max(-bt,Math.min(bt,Math.round(t)))}function fo(e){if(e===null||typeof e!="object")return;const t=e,o=Mt(t.x),s=Mt(t.y);return o===void 0||s===void 0?void 0:{x:o,y:s}}function is(e){const t=fo(e);if(t===void 0)return;const o=e,s=Mt(o.w),n=Mt(o.h);if(!(s===void 0||n===void 0||s<=0||n<=0))return{...t,w:Math.min(s,bt),h:Math.min(n,bt)}}const po=e=>e!==""&&!e.includes("/")&&(e.startsWith("roster:")?e.length>7&&e.length<=47:e.length<=40);function ho(e){if(e===null||typeof e!="object")return;const t=e;if(t.version!==1)return;const o=t.viewport;if(o===null||typeof o!="object")return;const s=o,n=Mt(s.x),i=Mt(s.y),r=s.scale,c=typeof r=="number"?r:Number.NaN;if(n===void 0||i===void 0||!Number.isFinite(c))return;const l=Math.max(Cn,Math.min(kn,c)),u={};if(t.nodes!==null&&typeof t.nodes=="object")for(const[m,x]of Object.entries(t.nodes)){if(typeof m!="string"||m===""||m.length>128)continue;const N=fo(x);if(N!==void 0&&(u[m]=N),Object.keys(u).length>=mo)break}const b={};if(t.frames!==null&&typeof t.frames=="object")for(const[m,x]of Object.entries(t.frames)){if(!po(m))continue;const N=is(x);if(N!==void 0&&(b[m]=N),Object.keys(b).length>=uo)break}return{version:1,viewport:{x:n,y:i,scale:l},nodes:u,frames:b}}function rs(e,t,o){const s=r=>Math.max(-bt,Math.min(bt,Math.round(r))),n={};for(const[r,c]of t)if(!(typeof r!="string"||r===""||r.length>128)&&(n[r]={x:s(c.x),y:s(c.y)},Object.keys(n).length>=mo))break;const i={};for(const[r,c]of o){if(!po(r))continue;const l=s(c.w),u=s(c.h);if(!(l<=0||u<=0)&&(i[r]={x:s(c.x),y:s(c.y),w:Math.min(l,bt),h:Math.min(u,bt)},Object.keys(i).length>=uo))break}return{version:1,viewport:{x:s(e.x),y:s(e.y),scale:Math.max(Cn,Math.min(kn,e.scale))},nodes:n,frames:i}}function bo(e){let t=2166136261;for(let o=0;o<e.length;o++)t^=e.charCodeAt(o),t=Math.imul(t,16777619)>>>0;return t>>>0}const Ue=172,De=56,xt=[150,290,430],at=16;function as(e){const t=bo(e),o=Math.floor(t/at)%xt.length,n=t%at/at*Math.PI*2+o*(Math.PI/at),i=xt[o];return{x:Math.round(Math.cos(n)*i),y:Math.round(Math.sin(n)*i*.6)}}function go(e){const t=new Map;for(const o of e)for(const s of o.members)t.has(s.id)||t.set(s.id,o.name);return t}const Rn=64,Hn=24,jn=20,cs=4,Bn=24,Yn=44,ls=24;function ds(e,t,o=Number.POSITIVE_INFINITY){const s=new Set(t),n=go(e),i=e.map(m=>[...new Set(m.members.map(x=>x.id))].filter(x=>s.has(x)&&n.get(x)===m.name));i.push(t.filter(m=>!n.has(m)));const r=new Map;let c=0,l=0,u=0,b=0;for(const m of i){if(m.length===0)continue;const x=Math.min(3,Math.max(m.length>1?2:1,Math.ceil(Math.sqrt(m.length)))),N=Math.ceil(m.length/x),Y=Math.max(260,x*Ue+(x-1)*Hn+Bn*2),re=Math.max(160,N*De+(N-1)*jn+Yn+ls);b>0&&(b%cs===0||c+Y>o)&&(c=0,l+=u+Rn,u=0),m.forEach((V,M)=>{const C=M%x,S=Math.floor(M/x);r.set(V,{x:c+Bn+Ue/2+C*(Ue+Hn),y:l+Yn+De/2+S*(De+jn)})}),c+=Y+Rn,u=Math.max(u,re),b+=1}return r}const Wt=12;function vo(e,t){const o=l=>t.every(u=>Math.abs(u.x-l.x)>=Ue+Wt||Math.abs(u.y-l.y)>=De+Wt),s=as(e);if(o(s))return s;const n=bo(e),i=at*xt.length,r=Math.floor(n/at)%xt.length*at+n%at;for(let l=1;l<i;l++){const u=(r+l)%i,b=Math.floor(u/at),m=u%at/at*Math.PI*2+b*(Math.PI/at),x=xt[b],N={x:Math.round(Math.cos(m)*x),y:Math.round(Math.sin(m)*x*.6)};if(o(N))return N}const c=xt[xt.length-1];for(let l=0;;l++)for(let u=0;u<6;u++){const b={x:Math.round(-c+u*(Ue+Wt)),y:Math.round(c*.6+De*2+l*(De+Wt))};if(o(b))return b}}function mt(e){return{x:e.x-Ue/2,y:e.y-De/2,w:Ue,h:De}}function En(e){if(e.length===0)return{x:0,y:0,w:260,h:160};let t=Number.POSITIVE_INFINITY,o=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY,n=Number.NEGATIVE_INFINITY;for(const b of e)t=Math.min(t,b.x),o=Math.min(o,b.y),s=Math.max(s,b.x+b.w),n=Math.max(n,b.y+b.h);const i=24,r=44,c=24,l=Math.max(260,Math.round(s-t+i*2)),u=Math.max(160,Math.round(n-o+r+c));return{x:Math.round(t-i),y:Math.round(o-r),w:l,h:u}}class Nn{constructor(){Et(this,"revisionCounter",0);Et(this,"nodes",new Map);Et(this,"frames",new Map);Et(this,"selection",new Set);Et(this,"viewport",{x:0,y:0,scale:1})}get revision(){return this.revisionCounter}getNode(t){return this.nodes.get(t)}allNodes(){return[...this.nodes.values()]}nodeIds(){return[...this.nodes.keys()]}getFrame(t){return this.frames.get(t)}allFrames(){return[...this.frames.entries()]}isSelected(t){return this.selection.has(t)}selectedIds(){return[...this.selection]}bump(){this.revisionCounter+=1}dragNodes(t,o,s){let n=!1;for(const i of t){const r=this.nodes.get(i);r!==void 0&&(r.x+=o,r.y+=s,n=!0)}n&&this.bump()}beginFrameDrag(t){const o=this.frames.get(t);if(o!==void 0)return{name:t,rect:{...o}}}applyFrameDrag(t,o,s){const n=this.frames.get(t.name);n!==void 0&&(n.x=t.rect.x+o,n.y=t.rect.y+s,this.bump())}nudge(t,o,s){this.dragNodes(t,o,s)}marqueeSelect(t,o){o||this.selection.clear();for(const s of this.nodes.values()){const n=mt(s);n.x<t.x+t.w&&n.x+n.w>t.x&&n.y<t.y+t.h&&n.y+n.h>t.y&&this.selection.add(s.id)}this.bump()}setSelection(t){this.selection=new Set(t),this.bump()}upsertNode(t){const o=this.nodes.get(t.id);if(o===void 0){this.nodes.set(t.id,t),this.bump();return}o.label=t.label,o.name=t.name,o.description=t.description,o.live=t.live,o.memberships=t.memberships,this.bump()}removeNode(t){this.nodes.delete(t)&&(this.selection.delete(t),this.bump())}setFrame(t,o){this.frames.set(t,o),this.bump()}removeFrame(t){this.frames.delete(t)&&this.bump()}upsertScore(t,o){const s=this.nodes.get(t);s===void 0||s.score===o||(s.score=o,this.bump())}positions(){const t=new Map;for(const[o,s]of this.nodes)t.set(o,{x:s.x,y:s.y});return t}frameRects(){const t=new Map;for(const[o,s]of this.frames)t.set(o,{...s});return t}teamMemberIds(t){const o=[];for(const s of this.nodes.values()){const n=s.memberships.find(i=>i.team===t);n!==void 0&&o.push({id:s.id,index:n.index})}return o.sort((s,n)=>s.index-n.index).map(s=>s.id)}setTeamMembers(t,o){for(const s of this.nodes.values()){const n=s.memberships.filter(r=>r.team!==t),i=o.indexOf(s.id);i>=0&&n.push({team:t,index:i}),s.memberships=n}this.bump()}contentBounds(){let t=Number.POSITIVE_INFINITY,o=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY,n=Number.NEGATIVE_INFINITY;const i=r=>{t=Math.min(t,r.x),o=Math.min(o,r.y),s=Math.max(s,r.x+r.w),n=Math.max(n,r.y+r.h)};for(const r of this.nodes.values())r.remote!==!0&&i(mt(r));for(const r of this.frames.values())i(r);return t===Number.POSITIVE_INFINITY?null:{minX:t,minY:o,maxX:s,maxY:n}}static fromState(t){const o=new Nn,s=ho(t.layout),n=new Map;for(const i of t.teams)for(let r=0;r<i.members.length;r++){const c=i.members[r].id,l=n.get(c)??[];l.push({team:i.name,index:r}),n.set(c,l)}for(const i of t.sessions){if(i.joined!==!0)continue;const r=s==null?void 0:s.nodes[i.id];let c,l;if(r!==void 0&&typeof r.x=="number"&&typeof r.y=="number")c=r.x,l=r.y;else{const u=vo(i.id,[...o.nodes.values()]);c=u.x,l=u.y}o.nodes.set(i.id,{id:i.id,x:c,y:l,label:i.label,team:i.team,name:i.name,description:i.description,live:i.live!==!1,memberships:n.get(i.id)??[]})}for(const i of t.teams){const r=s==null?void 0:s.frames[i.name];if(r!==void 0){o.frames.set(i.name,{x:r.x,y:r.y,w:r.w,h:r.h});continue}const c=[];for(const l of i.members){const u=o.nodes.get(l.id);u!==void 0&&c.push(mt(u))}c.length>0&&o.frames.set(i.name,En(c))}return o.viewport=s!==void 0?{...s.viewport}:{x:0,y:0,scale:1},o}}const ms=24,yo=-13,us=yo+ms;function fs(e,t,o){const s=[],n=new Set;for(const i of e){const r=t.get(i.name);if(r===void 0)continue;const c=r.x+r.w/2,l=r.y+us;for(const u of i.members){const b=o.get(u.id);if(b===void 0)continue;const m=n.has(u.id);n.add(u.id),s.push({x1:c,y1:l,x2:b.x,y2:b.y-De/2,dashed:m,team:i.name,id:u.id})}}return s}function ps(e,t){for(;e.firstChild!==null;)e.firstChild.remove();const o=t.allFrames().map(([s])=>({name:s,members:t.teamMemberIds(s).map(n=>({id:n}))}));for(const s of fs(o,new Map(t.allFrames()),t.positions())){const n=document.createElementNS("http://www.w3.org/2000/svg","line");n.setAttribute("class","e-member"+(s.dashed?" dashed":"")),n.setAttribute("x1",String(s.x1)),n.setAttribute("y1",String(s.y1)),n.setAttribute("x2",String(s.x2)),n.setAttribute("y2",String(s.y2)),e.appendChild(n)}}function hs(e){return`peer-${dt(e).replace(/[^A-Za-z0-9.:\[\]-]/g,"-")}`}function dt(e){try{return new URL(e).host}catch{return e}}function bs(e){const t=new Map;for(const o of e){const s=o.via!==void 0&&o.via!==""?dt(o.via):"",n=t.get(s)??[];n.push(o),t.set(s,n)}return t}const gs=140,vs=200,ys=90,ws=20,Xt=60;function xs(e,t){const o=t!==null?t.maxX+gs:vs,s=t!==null?t.minY:0;return e.map((n,i)=>({url:n.url,score:n.score,x:o,y:s+i*ys}))}function Cs(e,t,o,s){const n=new Map;for(const r of e){if(!t.has(r.team))continue;const c=`${r.team}\0${r.peer}`,l=n.get(c);l===void 0?n.set(c,{team:r.team,peer:r.peer,startedAt:r.startedAt,count:1}):(l.startedAt=Math.min(l.startedAt,r.startedAt),l.count+=1)}const i=[];for(const r of n.values()){const c=t.get(r.team);if(c===void 0)continue;const l=o.find(b=>{try{return new URL(b.url).host===r.peer}catch{return!1}});if(l===void 0)continue;const u=Math.max(0,Math.round((s-r.startedAt)/1e3));i.push({x1:c.x,y1:c.y,x2:l.x,y2:l.y,label:`a2a_route · ${r.peer} · ${u}s`+(r.count>1?` ×${r.count}`:"")})}return i}function ks(e,t){const o=t!==null?{x:t.maxX+ws,y:e.length>0?(e[0].y+e[e.length-1].y)/2:(t.minY+t.maxY)/2}:{x:-80,y:0};return e.map((s,n)=>({x1:o.x,y1:o.y,x2:s.x,y2:s.y,label:n===0?"gns referral":""}))}function Es(e,t){if(e===null&&t.length===0)return null;let o=e!==null?e.minX:Number.POSITIVE_INFINITY,s=e!==null?e.minY:Number.POSITIVE_INFINITY,n=e!==null?e.maxX:Number.NEGATIVE_INFINITY,i=e!==null?e.maxY:Number.NEGATIVE_INFINITY;for(const r of t)o=Math.min(o,r.x-Xt),s=Math.min(s,r.y-Xt),n=Math.max(n,r.x+Xt),i=Math.max(i,r.y+Xt);return{minX:o,minY:s,maxX:n,maxY:i}}const Ns=11;function $s(e,t){let o=[],s=[],n=[];function i(c){for(const b of o)b.remove();o=[];const l=t.allNodes().filter(b=>b.remote===!0).map(b=>({url:b.peerUrl??b.id.slice(5),score:b.score,x:b.x,y:b.y}));s=l;const u=t.contentBounds();if(u!==null){const b=new Map;for(const[m,x]of t.allFrames())b.set(m,{name:m,x:x.x+x.w/2,y:x.y+Ns});for(const m of Cs(n,b,l,c))o.push(...r(m,"e-activity",m.label));for(const m of ks(l,u))o.push(...r(m,"e-federal",m.label))}}function r(c,l,u){const b=document.createElementNS("http://www.w3.org/2000/svg","line");b.setAttribute("class",l),b.setAttribute("x1",String(c.x1)),b.setAttribute("y1",String(c.y1)),b.setAttribute("x2",String(c.x2)),b.setAttribute("y2",String(c.y2)),e.appendChild(b);const m=[b];if(u!==""){const x=document.createElementNS("http://www.w3.org/2000/svg","text");x.setAttribute("class","edge-label mono"),x.setAttribute("x",String((c.x1+c.x2)/2+14)),x.setAttribute("y",String((c.y1+c.y2)/2+18)),x.textContent=u,e.appendChild(x),m.push(x)}return m}return{render:i,flyTo(c){return c(),s},placements:()=>s,setInFlight:c=>{n=c}}}function wo(e,t){const o=new Map,s=new Set;for(const n of e){if(n.joined!==!0)continue;const i=n.team.lastIndexOf("/");if(i<=0||n.team.slice(i+1)!==n.id.replace(/^session-/,"").slice(0,8))continue;const r=n.team;t.has(r)||s.has(r)||(o.has(r)?(o.delete(r),s.add(r)):o.set(r,n.id))}return o}function Ms(e,t,o,s){var r;const n=t.get(e);return n!==void 0?n:e.includes("/")?`member-${e.replace(/[^a-z0-9-]/gi,"-")}`:`member-${((r=o==null?void 0:o.find(c=>c.via===s))==null?void 0:r.team.split("/")[0])??"dsh"}-${e.replace(/^session-/,"").slice(0,8)}`}function Ss(e){const t=new Map;for(const o of e)for(let s=0;s<o.members.length;s++){const n=o.members[s].id,i=t.get(n)??[];i.push({team:o.name,index:s}),t.set(n,i)}return t}function As(e,t,o){const s=wo(t,new Set((o??[]).map(i=>i.team))),n=new Set;for(const i of e)for(const r of i.org)for(const c of r.members){const l=s.get(c);l!==void 0&&n.add(l)}return n}const Wn={x:0,y:0,scale:1};function Zt(e){return Math.max(Cn,Math.min(kn,e))}function Nt(e){const t=Number.isFinite(e.scale)?e.scale:1,o=Number.isFinite(e.x)?e.x:0,s=Number.isFinite(e.y)?e.y:0;return{x:o,y:s,scale:Zt(t)}}function ct(e,t,o){return{x:e.x+t/e.scale,y:e.y+o/e.scale}}function un(e,t,o){return{x:e.x+t/e.scale,y:e.y+o/e.scale,scale:e.scale}}function Xn(e,t,o,s){const n=Zt(e.scale*t);return n===e.scale?e:{x:e.x+o/e.scale-o/n,y:e.y+s/e.scale-s/n,scale:n}}const Ls=680,Is=.8,Ts=.6,Kn=16;function $n(e,t,o,s=Number.POSITIVE_INFINITY){if(e===null||t<=0||o<=0)return Wn;const n=e.maxX-e.minX,i=e.maxY-e.minY;if(!(n>0)||!(i>0))return Wn;const r=.9*Math.min(t/n,o/i),c=Math.min(s,r),l=t<Ls?Is:Ts;if(r<l){const b=Zt(Math.min(s,l));return{x:e.minX-Kn/b,y:e.minY-Kn/b,scale:b}}const u=Zt(c);return{x:(e.minX+e.maxX)/2-t/(2*u),y:(e.minY+e.maxY)/2-o/(2*u),scale:u}}function _s(e){return`translate(${-e.x*e.scale}px, ${-e.y*e.scale}px) scale(${e.scale})`}function Un(e,t){let o=e===null?null:{...e,minY:e.minY+yo};for(const s of t){if(s.remote!==!0)continue;const n=mt(s);o=o===null?{minX:n.x,minY:n.y,maxX:n.x+n.w,maxY:n.y+n.h}:{minX:Math.min(o.minX,n.x),minY:Math.min(o.minY,n.y),maxX:Math.max(o.maxX,n.x+n.w),maxY:Math.max(o.maxY,n.y+n.h)}}return o}function qn(e,t,o,s){const n=s>0&&s<o/2?s:0,i=$n(e,t,o-n,1);return n===0||e===null?i:{...i,y:i.y-n/i.scale}}function zn(...e){const t=Math.max(0,...e.map(o=>o.offsetHeight>0?o.offsetTop+o.offsetHeight:0));return t>0?t+8:0}function Rt(e){return e.type==="join-network"||e.type==="leave-network"?"$network":e.type==="create-team"||e.type==="remove-team"?e.name:e.team}function Os(e,t){if(t.type==="create-team"){const n=t.ids.map(i=>e.getNode(i)).filter(i=>i!==void 0).map(i=>mt(i));return n.length>0&&e.setFrame(t.name,En(n)),e.setTeamMembers(t.name,t.ids),()=>{e.setTeamMembers(t.name,e.teamMemberIds(t.name).filter(i=>!t.ids.includes(i))),e.removeFrame(t.name)}}if(t.type==="add-member"){const n=e.teamMemberIds(t.team),i=t.ids.filter(r=>!n.includes(r));return e.setTeamMembers(t.team,[...n,...i]),()=>{e.setTeamMembers(t.team,e.teamMemberIds(t.team).filter(r=>!i.includes(r)))}}if(t.type==="remove-member"){const n=e.teamMemberIds(t.team);return e.setTeamMembers(t.team,n.filter(i=>!t.ids.includes(i))),()=>{const i=e.teamMemberIds(t.team);e.setTeamMembers(t.team,[...i,...t.ids.filter(r=>!i.includes(r))])}}if(t.type==="remove-team"){const n=e.teamMemberIds(t.name),i=e.getFrame(t.name),r=i!==void 0?{...i}:void 0;return e.setTeamMembers(t.name,[]),e.removeFrame(t.name),()=>{r!==void 0&&e.setFrame(t.name,r),e.setTeamMembers(t.name,n)}}if(t.type==="join-network"||t.type==="leave-network")return()=>{};const o=e.teamMemberIds(t.team);let s=[...o];for(const n of t.ops)n.op==="remove"?s=s.filter(i=>i!==n.id):s.push(n.id);return e.setTeamMembers(t.team,s),()=>{let n=e.teamMemberIds(t.team);for(let i=0;i<o.length;i++){const r=o[i];n[i]!==r&&n.includes(r)&&(n=n.filter(c=>c!==r),n.push(r))}e.setTeamMembers(t.team,n)}}function Jn(e,t,o,s,n){if(o||s(),!(t.type==="remove-team"&&o||t.type==="create-team"&&!o&&t.created===!0)||n===void 0||e.getFrame(Rt(t))!==void 0)return n;const r={...n.frames};return delete r[Rt(t)],{...n,frames:r}}function vn(e,t){const o=[...e],s=[];for(let n=0;n<t.length;n++){const i=t[n];o[n]!==i&&o.includes(i)&&(s.push({op:"remove",id:i}),s.push({op:"add",id:i}),o.splice(o.indexOf(i),1),o.push(i))}return s}function Fs(e,t){return e.teamMemberIds(t).map(o=>{var s;return{id:o,y:((s=e.getNode(o))==null?void 0:s.y)??0}}).sort((o,s)=>o.y-s.y).map(o=>o.id)}function Kt(e,t){let o,s=Number.POSITIVE_INFINITY;for(const[n,i]of e){if(t.x<i.x||t.x>i.x+i.w||t.y<i.y||t.y>i.y+i.h)continue;const r=i.w*i.h;r<s&&(o=n,s=r)}return o}const Vn=[9133302,3900150,1357990,16096779,15485081,8702998];function Ps(e){let t=0;for(let c=0;c<e.length;c++)t=(t*31+e.charCodeAt(c)&268435455)>>>0;const o=Vn[t%Vn.length],s="#"+o.toString(16).padStart(6,"0"),n=o>>16&255,i=o>>8&255,r=o&255;return{line:s,bg:`rgba(${n},${i},${r},0.05)`}}const en="roster:",xo=e=>e.startsWith(en)?e.slice(en.length):void 0,Ft=e=>en+e,tn=e=>{const t=xo(e);return t===void 0?e:`网络队 · roster · ${t}`};function Ds(e,t){return e.flatMap(o=>{if(t===""||!o.team.startsWith(t+"/")||!Array.isArray(o.members))return[];const s=o.team.slice(t.length+1);return s===""||s.length>40||s.includes("/")||s.startsWith(en)||s.includes("*")?[]:[{name:Ft(s),team:o.team,kind:"roster",members:o.members.filter(n=>typeof n=="string"&&n!=="").map(n=>({id:n}))}]})}function Rs(e){const{root:t,netBtn:o,signal:s,model:n}=e,i=y=>e.isRoster(y)?tn(y):y;function r(){return n.selectedIds().map(y=>{var f;return{id:y,y:((f=n.getNode(y))==null?void 0:f.y)??0}}).sort((y,f)=>y.y-f.y).map(y=>y.id)}function c(){if(l!==null)return;const y=r().filter(f=>{const _=n.getNode(f);return _===void 0?!1:_.remote!==!0||_.remoteHandle!==void 0&&_.remoteHandle!==""});if(y.length<2){e.notice("info","框选至少 2 个会话节点");return}u(y)}let l=null;function u(y){const f=document.createElement("div");f.className="p-dialog";const _=document.createElement("div");_.className="p-dialog-panel",_.setAttribute("role","dialog"),_.setAttribute("aria-modal","true"),_.setAttribute("aria-labelledby","p-dialog-title");const p=document.createElement("div");p.id="p-dialog-title",p.className="p-dialog-title",p.textContent=`组建团队(${y.length} 个节点,自上而下即优先级)`;const R={value:"canvas"},j=document.createElement("div");j.className="p-dialog-kind",j.setAttribute("role","radiogroup"),j.setAttribute("aria-label","团队类型");const K=document.createElement("div");K.className="p-dialog-hint";const we={canvas:"canvas 队:画布上的协作组,可以加入远端成员。",roster:"roster 网络队:只收本机已入网的会话;队名会写进属主的精确允许名单。"},Me=["canvas","roster"].map(ee=>{const te=document.createElement("button");return te.type="button",te.dataset.kind=ee,te.setAttribute("role","radio"),te.textContent=ee==="canvas"?"canvas 队":"roster 网络队",te.addEventListener("click",()=>D(ee)),j.appendChild(te),te});function D(ee){R.value=ee;for(const te of Me){const Ce=te.dataset.kind===ee;te.setAttribute("aria-checked",String(Ce)),te.tabIndex=Ce?0:-1}K.textContent=we[ee],ce.textContent=""}j.addEventListener("keydown",ee=>{var Ce;const te=ee;["ArrowLeft","ArrowRight","ArrowUp","ArrowDown"].includes(te.key)&&(te.preventDefault(),D(R.value==="canvas"?"roster":"canvas"),(Ce=Me.find(Be=>Be.dataset.kind===R.value))==null||Ce.focus())});const U=document.createElement("input");U.className="p-dialog-input",U.maxLength=40,U.setAttribute("aria-label","团队名");const ce=document.createElement("div");ce.className="p-dialog-err",ce.setAttribute("aria-live","polite");const Re=document.createElement("div");Re.className="p-dialog-row";const Ee=document.createElement("button");Ee.type="button",Ee.textContent="组建";const le=document.createElement("button");le.type="button",le.textContent="取消",Re.append(Ee,le),D("canvas"),_.append(p,j,K,U,ce,Re),f.appendChild(_),t.appendChild(f);const He=document.activeElement,fe=()=>{f.remove(),l=null,He==null||He.focus()},q=()=>{const ee=U.value.trim();return ee===""||ee.length>40||ee.includes("/")||ee.startsWith("roster:")||R.value==="roster"&&ee.includes("*")||/^\d+$/.test(ee)?"队名需 1..40 字,不含“/”、通配符或保留前缀,不为纯数字":R.value==="roster"&&n.getFrame(ee)!==void 0?"同名 canvas 队已存在,不能创建 roster 队":R.value==="roster"&&n.getFrame(Ft(ee))!==void 0&&!e.isRoster(Ft(ee))?"roster 框名已被 canvas 或镜像队占用":R.value==="canvas"&&n.getFrame(Ft(ee))!==void 0?"同名 roster 队已存在,不能创建 canvas 队":R.value==="roster"&&y.some(te=>{var Ce;return((Ce=n.getNode(te))==null?void 0:Ce.remote)===!0||!e.joined(te)})?"roster 仅接受本机已入网的会话":null},de=()=>{const ee=q();if(ee!==null){ce.textContent=ee,U.focus();return}const te=R.value==="roster"?Ft(U.value.trim()):U.value.trim();if(fe(),n.getFrame(te)!==void 0){e.notice("info",`已加入现有团队「${R.value==="roster"?tn(te):te}」`),e.emit({type:"add-member",team:te,ids:y});return}e.emit({type:"create-team",name:te,ids:y,created:!0,...R.value==="roster"?{roster:!0}:{}})};Ee.addEventListener("click",de),le.addEventListener("click",fe),U.addEventListener("keydown",ee=>{const te=ee;te.key==="Enter"&&(te.preventDefault(),de()),te.key==="Escape"&&(te.preventDefault(),fe())}),f.addEventListener("keydown",ee=>{const te=ee;if(te.key==="Escape"){te.preventDefault(),te.stopPropagation(),fe();return}if(te.key!=="Tab")return;te.preventDefault();const Ce=Array.from(_.querySelectorAll('input, select, button:not([tabindex="-1"])')),Be=Ce.indexOf(document.activeElement),Ye=te.shiftKey?Ce[(Be-1+Ce.length)%Ce.length]:Ce[(Be+1)%Ce.length];Ye==null||Ye.focus()},s),l={wrap:f,restoreFocus:He},U.focus()}let b=null,m="root",x=null,N=null,Y=[];function re(){N==null||N.remove(),N=null}function V(){var _;if(N!==null){re();return}if(Y.length===0)return;const y=document.createElement("div");y.className="p-menu p-netmenu",y.setAttribute("role","menu"),y.setAttribute("aria-label","未入网会话");for(const p of Y)y.appendChild(C(`${p.name!==void 0&&p.name!==""?p.name:p.label} — 入网`,!0,()=>{re(),e.emit({type:"join-network",id:p.id})}));N=y,t.appendChild(y);const f=o.getBoundingClientRect();y.style.left=`${String(Math.min(f.left,window.innerWidth-220))}px`,y.style.top=`${String(Math.max(8,f.top-(Y.length*30+10)))}px`,y.addEventListener("keydown",p=>{p.key==="Escape"&&(p.stopPropagation(),re(),o.focus())}),(_=y.querySelector("button"))==null||_.focus(),document.addEventListener("pointerdown",p=>{if(N===null)return;const R=p.target;R!==null&&(R.closest(".p-netmenu")!==null||R===o||o.contains(R))||re()},s)}function M(){b==null||b.remove(),b=null,m="root",x!==null&&x.isConnected?x.focus():t.focus(),x=null}function C(y,f,_){const p=document.createElement("button");return p.type="button",p.setAttribute("role","menuitem"),p.textContent=y,f?p.addEventListener("click",()=>{M(),_()}):(p.disabled=!0,p.setAttribute("aria-disabled","true")),p}function S(y,f,_,p="root",R){var Me,D,U,ce,Re,Ee,le,He;R!==void 0&&(x=R),x===null&&(x=e.anchorFor(_)),b==null||b.remove(),m=p;const j=document.createElement("div");j.className="p-menu",j.setAttribute("role","menu"),j.setAttribute("aria-label","团队操作");let K=[];if(_.kind==="frame")K=[C(`解散团队「${i(_.name)}」`,!0,()=>e.emit({type:"remove-team",name:_.name}))];else{const fe=_.id;if(p==="root"){const q=C("组成团队…",n.selectedIds().length>=2,()=>u(r()));q.title="先框选或 Shift 加选至少 2 个节点",K.push(q);const de=((Me=n.getNode(fe))==null?void 0:Me.memberships.map(ee=>ee.team))??[];e.teams().length>0&&(K.push(C("加入团队 ▸",!0,()=>S(y,f,_,"join"))),de.length>0&&K.push(C("置顶路由 ▸",!0,()=>S(y,f,_,"promote")))),de.length>0&&K.push(C("离队 ▸",!0,()=>S(y,f,_,"leave"))),((D=n.getNode(fe))==null?void 0:D.remote)!==!0&&K.push(C("退网",!0,()=>e.emit({type:"leave-network",id:fe})))}else{K.push(C("‹ 返回",!0,()=>S(y,f,_,"root")));for(const q of e.teams())if(p==="join"){const de=((U=n.getNode(fe))==null?void 0:U.memberships.some(Ce=>Ce.team===q.name))??!0,ee=!e.isRoster(q.name)||e.joined(fe)&&((ce=n.getNode(fe))==null?void 0:ce.remote)!==!0,te=C(de?`${i(q.name)}(已加入)`:i(q.name),!de&&ee,()=>e.emit({type:"add-member",team:q.name,ids:[fe]}));ee||(te.title="roster 只接受本机已入网会话"),K.push(te)}else if(p==="leave"){const de=((Re=n.getNode(fe))==null?void 0:Re.memberships.some(ee=>ee.team===q.name))??!1;K.push(C(i(q.name),de,()=>e.emit({type:"remove-member",team:q.name,ids:[fe]})))}else{const de=((Ee=n.getNode(fe))==null?void 0:Ee.memberships.some(ee=>ee.team===q.name))??!1;if(e.isRoster(q.name))continue;K.push(C(i(q.name),de,()=>{const ee=n.teamMemberIds(q.name),te=[fe,...ee.filter(Ce=>Ce!==fe)];e.emit({type:"reorder",team:q.name,ops:vn(ee,te)})}))}if(p==="leave"){const q=new Set(e.teams().map(de=>de.name));for(const de of((le=n.getNode(fe))==null?void 0:le.memberships)??[])q.has(de.team)||K.push(C(i(de.team),!0,()=>e.emit({type:"remove-member",team:de.team,ids:[fe]})))}}}j.append(...K),j.style.left=`${Math.min(y,window.innerWidth-200)}px`;const we=K.length*30+8;j.style.top=`${Math.max(8,Math.min(f,window.innerHeight-we-8))}px`,j.addEventListener("keydown",fe=>{var te,Ce,Be,Ye;const q=fe,de=Array.from(j.querySelectorAll("[role=menuitem]")),ee=de.indexOf(document.activeElement);q.key==="ArrowDown"?(q.preventDefault(),(te=de[(ee+1+de.length)%de.length])==null||te.focus()):q.key==="ArrowUp"?(q.preventDefault(),(Ce=de[(ee-1+de.length)%de.length])==null||Ce.focus()):q.key==="Home"?(q.preventDefault(),(Be=de[0])==null||Be.focus()):q.key==="End"?(q.preventDefault(),(Ye=de[de.length-1])==null||Ye.focus()):q.key==="Escape"&&(q.preventDefault(),q.stopPropagation(),m!=="root"?S(y,f,_,"root"):M())}),t.appendChild(j),b=j,(He=K[0])==null||He.focus()}function E(y,f,_){if(l!==null)return;const p=(_==null?void 0:_.closest(".p-node"))??null;if(p!==null){const K=n.getNode(p.dataset.id??"");if((K==null?void 0:K.remote)===!0&&(K.remoteHandle===void 0||K.remoteHandle===""))return}const R=p,j=(_==null?void 0:_.closest(".p-frame-head"))??null;if(R!==null){const K=R.dataset.id??"";n.isSelected(K)||n.setSelection([K]),x=R,S(y,f,{kind:"node",id:K})}else j!==null&&(x=j,S(y,f,{kind:"frame",name:j.dataset.frame??""}))}function G(y){Y=y,o.textContent=`未入网${Y.length>0?`(${String(Y.length)})`:""}`,o.disabled=Y.length===0,o.setAttribute("aria-disabled",String(Y.length===0)),Y.length===0&&re()}return{menuItem:C,isMenuOpen:()=>b!==null,isDialogOpen:()=>l!==null,closeMenu:M,openMenu:S,contextMenuAt:E,openNameDialog:u,startCreateFromSelection:c,toggleNetMenu:V,setUnjoined:G}}function Hs(e,t){const o=t.trim().toLowerCase();return o===""?[]:e.filter(s=>s.name.toLowerCase().includes(o)||s.team.toLowerCase().includes(o)||(s.host??"").toLowerCase().includes(o)).slice(0,8)}function js(e,t){return e.allNodes().map(o=>{const s=o.id.slice(5),n=o.id.startsWith("member-")?o.name!==void 0&&o.name!==""?o.name:o.team:o.remote===!0?s:t(o);return{id:o.id,name:n,team:o.team,...o.remote===!0?{host:s}:{}}})}function Bs(e,t=1200){e!==void 0&&(e.classList.add("pulse"),setTimeout(()=>e.classList.remove("pulse"),t))}function Ys(e){return t=>{const o=e.model.getNode(t);if(o===void 0)return;const s=e.viewSize();e.setVp($n({minX:o.x,minY:o.y,maxX:o.x+Ue,maxY:o.y+De},s.w,s.h,1)),e.applyViewport(),e.markDirty(),Bs(e.cardEl(t))}}function Ws(e,t,o,s){const n=Xs({onPick:s});return e.appendChild(n.root),{...n,refresh:()=>n.setIndex(js(t,o))}}function Xs(e){const t=document.createElement("div");t.className="p-search";const o=document.createElement("input");o.type="search",o.className="p-search-input",o.placeholder="🔍 搜索(Ctrl+K)",o.title="搜索名字 / 句柄 / 宿主(Ctrl+K 聚焦,Esc 清空)",o.setAttribute("aria-label","搜索画板节点:名字、句柄或宿主");const s=document.createElement("div");s.className="p-search-list";let n=[],i=[],r=0;const c=()=>{s.style.display="none",s.textContent=""},l=()=>{if(s.textContent="",i.length===0){c();return}i.forEach((m,x)=>{const N=document.createElement("div");N.className="p-search-hit"+(x===r?" active":""),N.dataset.id=m.id,N.textContent=m.name===m.team?m.name:`${m.name} · ${m.team}`,N.addEventListener("mousedown",Y=>{Y.preventDefault(),e.onPick(m.id),u()}),s.appendChild(N)}),s.style.display="block"},u=()=>{o.value="",i=[],c()},b=()=>{i=Hs(n,o.value),r=0,l()};return o.addEventListener("input",b),o.addEventListener("keydown",m=>{if(m.key==="Escape"){u(),o.blur(),m.stopPropagation();return}if(m.key==="ArrowDown"||m.key==="ArrowUp"){if(i.length===0)return;m.preventDefault(),r=(r+(m.key==="ArrowDown"?1:i.length-1))%i.length,l();return}m.key==="Enter"&&i.length>0&&(m.preventDefault(),e.onPick(i[r].id),u())}),t.append(o,s),{root:t,setIndex(m){n=m,o.value!==""&&b()},focus(){o.focus(),o.select()},clear(){u()}}}const Ut=28,Gn=16,Qn=14,Zn=48,Ks=4,Us=180,qs=90,zs=1600;function Js(e){const t=e.wrapWidth??zs,o=e.frames.map(l=>{const u=Math.max(l.soleIds.length,1),b=Math.min(Ks,Math.max(1,Math.ceil(Math.sqrt(u)))),m=Math.ceil(u/b),x=Math.max(Us,Ut*2+b*Ue+(b-1)*Gn),N=Math.max(qs,Ut*2+m*De+(m-1)*Qn);return{name:l.name,w:x,h:N,rows:m,perRow:b,soleIds:l.soleIds}}),s=[],n=[];let i=0,r=0,c=0;for(const l of o){i>0&&i+l.w>t&&(i=0,r+=c+Zn,c=0);const u={x:i,y:r,w:l.w,h:l.h};s.push({name:l.name,rect:u});const b=u.x+Ut+Ue/2;let m=u.y+Ut+De/2;l.soleIds.forEach((x,N)=>{const Y=N%l.perRow;N>0&&Y===0&&(m+=De+Qn),n.push({id:x,x:b+Y*(Ue+Gn),y:m})}),i+=l.w+Zn,c=Math.max(c,l.h)}return{frames:s,seats:n}}function Vs(e,t){const o=[];for(const[n,i]of e.allFrames()){if(t.has(n))continue;const r=e.teamMemberIds(n).map(c=>e.getNode(c)).filter(c=>c!==void 0).filter(c=>c.memberships.length===1).map(c=>c.id);o.push({name:n,rect:i,soleIds:r})}if(o.length===0)return!1;const s=Js({frames:o});for(const n of s.frames)e.setFrame(n.name,n.rect);for(const n of s.seats){const i=e.getNode(n.id);i!==void 0&&e.dragNodes([n.id],n.x-i.x,n.y-i.y)}return!0}function Gs(e,t){if(e===void 0)return;const o=dt(e);return{text:t?`同步中… · ${o}`:`镜像 · ${o}`,title:t?`已把改动交给属主 ${o},等待它确认`:`这个团队属于 ${o},这里显示的是它的镜像;拖入或移出成员会经中继交给 ${o} 执行`,syncing:t}}const Qs=1e4;function Zs(e=Date.now){const t=(s,n)=>`${s}\0${n}`,o=new Map;return{fork(s,n){return o.set(t(n,s.name),{url:n,name:s.name}),{...s,fleetPeer:n}},settled(s,n){if(s.type!=="remove-team"||s.name===void 0||s.fleetPeer===void 0)return;const i=o.get(t(s.fleetPeer,s.name));i!==void 0&&(n?i.acceptedAt=e():o.delete(t(s.fleetPeer,s.name)))},hides(s,n){return o.has(t(n,s))},sweep(s){var n;for(const[i,r]of o)(!(((n=s.find(l=>l.url===r.url))==null?void 0:n.org.some(l=>l.name===r.name))===!0)||r.acceptedAt!==void 0&&e()-r.acceptedAt>Qs)&&o.delete(i)}}}const Ct=24,ei=200,Jt=(e,t)=>e.x<t.x+t.w&&t.x<e.x+e.w&&e.y<t.y+t.h&&t.y<e.y+e.h;function ti(e,t){const o=t.x+t.w+Ct-e.x,s=t.x-Ct-(e.x+e.w),n=t.y+t.h+Ct-e.y,i=t.y-Ct-(e.y+e.h),r=Math.abs(o)<=Math.abs(s)?o:s,c=Math.abs(n)<=Math.abs(i)?n:i;return Math.abs(r)<=Math.abs(c)?{dx:r,dy:0}:{dx:0,dy:c}}function ni(e,t,o,s){const n=e.beginFrameDrag(t);n!==void 0&&e.applyFrameDrag(n,o,s)}function oi(e,t,o){let s=!1;for(let n=0;n<ei;n++){const i=e.allFrames();let r;for(let M=0;M<i.length&&r===void 0;M++)for(let C=M+1;C<i.length;C++){const[S,E]=i[M],[G,y]=i[C];if(!(t.has(S)&&t.has(G))&&Jt(E,y)){r=[S,E,G,y];break}}if(r===void 0)return s;const[c,l,u,b]=r,m=M=>t.has(M)?2:M===o?1:0,[x,N,Y]=m(c)<m(u)?[c,l,b]:[u,b,l],{dx:re,dy:V}=ti(N,Y);ni(e,x,re,V),s=!0}return s}const gt=28,Vt=16,nn=14;function si(e){const t=[];for(let o=e.y+gt;o+De<=e.y+e.h-gt;o+=De+nn)for(let s=e.x+gt;s+Ue<=e.x+e.w-gt;s+=Ue+Vt)t.push({x:s+Ue/2,y:o+De/2});return t}function ii(e){let t=!1;const o=e.allFrames(),s=new Map(o);for(const n of e.allNodes()){const i=new Set(n.memberships.map(V=>V.team)),r=o.find(([V,M])=>!i.has(V)&&Jt(mt(n),M));if(r===void 0)continue;const c=r[1],l=V=>{const M=mt(V);return o.every(([C,S])=>i.has(C)||!Jt(M,S))&&e.allNodes().every(C=>C.id===n.id||!Jt(M,mt(C)))},b=n.memberships.map(V=>s.get(V.team)).filter(V=>V!==void 0).flatMap(si).find(l),m={x:c.x+c.w+Ct+Ue/2,y:n.y},x={x:n.x,y:c.y+c.h+Ct+De/2},N=Math.max(...o.map(([,V])=>V.x+V.w))+Ct+Ue/2,Y=Array.from({length:2*e.allNodes().length+1},(V,M)=>({x:N,y:c.y+De/2+M*(De+nn)})),re=b??[m,x,...Y].find(l)??Y[Y.length-1];e.dragNodes([n.id],re.x-n.x,re.y-n.y),t=!0}return t}function qt(e,t,o){const s=oi(e,t,o),n=ii(e);return s||n}function ri(e){for(const[t,o]of e.allFrames()){const s=e.teamMemberIds(t).map(u=>e.getNode(u)).filter(u=>u!==void 0).filter(u=>u.memberships.length===1);if(s.length===0)continue;const n=Math.max(1,Math.floor((o.w-2*gt+Vt)/(Ue+Vt))),i=Math.ceil(s.length/n),r=gt*2+i*De+(i-1)*nn;r>o.h&&e.setFrame(t,{...o,h:Math.min(r,o.h+400)});const c=o.x+gt+Ue/2;let l=o.y+gt+De/2;s.forEach((u,b)=>{const m=b%n;b>0&&m===0&&(l+=De+nn);const x=c+m*(Ue+Vt);e.dragNodes([u.id],x-u.x,l-u.y)})}}const ai=30;function ci(e){const t=[],o=()=>({nodes:new Map(e.allNodes().map(i=>[i.id,{x:i.x,y:i.y}])),frames:new Map(e.allFrames().map(([i,r])=>[i,{...r}]))}),s=i=>e.allNodes().some(r=>{const c=i.nodes.get(r.id);return c!==void 0&&(c.x!==r.x||c.y!==r.y)})||e.allFrames().some(([r,c])=>{const l=i.frames.get(r);return l!==void 0&&(l.x!==c.x||l.y!==c.y||l.w!==c.w||l.h!==c.h)}),n=i=>{for(const r of e.allNodes()){const c=i.nodes.get(r.id);c!==void 0&&(c.x!==r.x||c.y!==r.y)&&e.dragNodes([r.id],c.x-r.x,c.y-r.y)}for(const[r,c]of e.allFrames()){const l=i.frames.get(r);l!==void 0&&(l.x!==c.x||l.y!==c.y||l.w!==c.w||l.h!==c.h)&&e.setFrame(r,{...l})}};return{capture:o,commit(i){s(i)&&(t.push(i),t.length>ai&&t.shift())},undo(){const i=t.pop();return i===void 0?!1:(n(i),!0)},revert(i){return s(i)?(n(i),!0):!1},get depth(){return t.length}}}function li(e){const{root:t,trigger:o,signal:s,model:n}=e;let i=null,r="",c=null;function l(){c==null||c.remove(),c=null}function u(){l(),i==null||i.remove(),i=null}function b(){if(i!==null){u();return}const C=document.createElement("div");C.className="p-menu p-nodelist",C.setAttribute("role","dialog"),C.setAttribute("aria-label","节点清单"),i=C,t.appendChild(C);const S=o.getBoundingClientRect();C.style.left=`${String(Math.min(S.left,window.innerWidth-340))}px`,C.style.top=`${String(Math.max(8,S.top-320))}px`,C.addEventListener("keydown",E=>{E.key==="Escape"&&(E.stopPropagation(),u(),o.focus())}),m()}function m(){var _;const C=i;if(C===null)return;l(),C.textContent="";const S=document.createElement("div");S.className="p-nodelist-head";const E=document.createElement("span");E.className="p-nodelist-title",E.textContent="节点";const G=document.createElement("select");G.className="p-nodesel",G.setAttribute("aria-label","选择 host 或对等节点");const y=document.createElement("option");y.value="",y.textContent="本机",G.appendChild(y);for(const[p,R]of e.facts().remoteTeams){if(p==="")continue;const j=document.createElement("option");j.value=p,j.textContent=((_=R[0])==null?void 0:_.origin)!==void 0&&R[0].origin!==""?`${R[0].origin}(${p})`:p,G.appendChild(j)}r!==""&&!e.facts().remoteTeams.has(r)&&(r=""),G.value=r,G.addEventListener("change",()=>{r=G.value,m()}),S.append(E,G);const f=document.createElement("div");f.className="p-nodelist-body",C.append(S,f),r===""?V(f):M(f,e.facts().remoteTeams.get(r)??[])}function x(C,S){const E=document.createElement("span");return E.className="p-nodedot"+(S!==!0?" off":C===!1?" cold":""),E}function N(C,S){const E=document.createElement("button");return E.type="button",E.className="p-listbtn",E.textContent=C,E.addEventListener("click",G=>{G.stopPropagation(),S()}),E}function Y(C,S){const E=document.createElement("div");if(E.className="p-nodelist-group",E.textContent=C,S!==void 0){const G=document.createElement("span");G.className="p-nodelist-note",G.textContent=S,E.appendChild(G)}return E}function re(C,S){var y,f;l();const E=document.createElement("div");E.className="p-menu",E.setAttribute("role","menu"),E.setAttribute("aria-label","加入团队");for(const _ of e.facts().teams){const p=((y=n.getNode(S))==null?void 0:y.memberships.some(R=>R.team===_.name))??!1;E.appendChild(e.menuItem(p?`${_.name}(已加入)`:_.name,!p,()=>{u(),e.emit({type:"add-member",team:_.name,ids:[S]})}))}E.appendChild(e.menuItem("新团队…",!0,()=>{u(),e.openNameDialog([S])})),c=E,t.appendChild(E);const G=C.getBoundingClientRect();E.style.left=`${String(Math.min(G.right+4,window.innerWidth-180))}px`,E.style.top=`${String(Math.max(8,G.top-60))}px`,E.addEventListener("keydown",_=>{_.key==="Escape"&&(_.stopPropagation(),l(),C.focus())}),(f=E.querySelector("button"))==null||f.focus()}function V(C){var f,_;const S=new Set(e.facts().canvasMemberIds);for(const p of e.facts().sessions)p.teams!==void 0&&p.teams.length>0&&S.add(p.id);const E=e.facts().sessions.filter(p=>p.joined===!0&&!S.has(p.id)),G=e.facts().sessions.filter(p=>p.joined!==!0),y=e.facts().sessions.filter(p=>p.joined===!0&&S.has(p.id));C.appendChild(Y(`未组队 (${String(E.length)})`,"无网络能力"));for(const p of E){const R=document.createElement("div");R.className="p-noderow";const j=document.createElement("span");j.className="p-nodename",j.textContent=p.name!==void 0&&p.name!==""?p.name:p.label,j.title=p.team;const K=document.createElement("span");K.className="p-nonet",K.textContent="无网络能力";const we=N("入队▸",()=>re(we,p.id));R.append(x(p.live,!0),j,K,we,N("退网",()=>{u(),e.emit({type:"leave-network",id:p.id})})),C.appendChild(R)}C.appendChild(Y(`未入网 (${String(G.length)})`));for(const p of G){const R=document.createElement("div");R.className="p-noderow";const j=document.createElement("span");j.className="p-nodename",j.textContent=p.name!==void 0&&p.name!==""?p.name:p.label,j.title=p.id,R.append(x(p.live,!1),j,N("入网",()=>{u(),e.emit({type:"join-network",id:p.id})})),C.appendChild(R)}C.appendChild(Y(`已组队 (${String(y.length)})`,"画布展示"));for(const p of y){const R=document.createElement("div");R.className="p-noderow";const j=document.createElement("span");j.className="p-nodename",j.textContent=p.name!==void 0&&p.name!==""?p.name:p.label,j.title=p.team;const K=((f=n.getNode(p.id))==null?void 0:f.memberships.length)??0,we=((_=p.teams)==null?void 0:_.length)??0,Me=document.createElement("span");Me.className="p-teamcount",Me.textContent=`队×${String(Math.max(K,0)+we)}`,R.append(x(p.live,!0),j,Me,N("定位",()=>{e.locate(p.id)})),C.appendChild(R)}if(e.facts().sessions.length===0){const p=document.createElement("div");p.className="p-nodelist-empty",p.textContent="无会话节点",C.appendChild(p)}}function M(C,S){var y;const E=S.filter(f=>f.teams===void 0||f.teams.length===0),G=S.filter(f=>f.teams!==void 0&&f.teams.length>0);C.appendChild(Y(`未组队 (${String(E.length)})`,"无网络能力 · 只读"));for(const f of E){const _=document.createElement("div");_.className="p-noderow";const p=document.createElement("span");p.className="p-nodename",p.textContent=f.name!==void 0&&f.name!==""?f.name:f.team,p.title=f.team;const R=document.createElement("span");R.className="p-nonet",R.textContent="无网络能力",_.append(x(!0,!0),p,R),C.appendChild(_)}C.appendChild(Y(`已组队 (${String(G.length)})`,"只读"));for(const f of G){const _=document.createElement("div");_.className="p-noderow";const p=document.createElement("span");p.className="p-nodename",p.textContent=f.name!==void 0&&f.name!==""?f.name:f.team,p.title=f.team;const R=document.createElement("span");R.className="p-teamcount",R.textContent=`队×${String(((y=f.teams)==null?void 0:y.length)??0)}`,_.append(x(!0,!0),p,R),C.appendChild(_)}if(S.length===0){const f=document.createElement("div");f.className="p-nodelist-empty",f.textContent="该节点未发布会话",C.appendChild(f)}}return document.addEventListener("pointerdown",C=>{if(i===null)return;const S=C.target;if(S===null){u();return}S.closest(".p-nodelist")!==null||S.closest(".p-menu")!==null||S===o||o.contains(S)||u()},s),{toggle:b,close:u,refresh:()=>{i!==null&&m()}}}function di(e){let t=e;const o=t.search(/\|| ```|^```/);return o>=0&&(t=t.slice(0,o)),t.replace(/\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/(^|\s)#{1,6}\s+/g,"$1").replace(/\*\*|__|`/g,"").replace(/\s+/g," ").trim()}function mi(e,t){const o=e.map(i=>i.name!==void 0&&i.name!==""?i.name:i.team),s=o.slice(0,2).join("、"),n=o.length>2?` +${o.length-2}`:"";return(t!==void 0?`score ${t} · `:"")+`${e.length} 远端团队`+(s!==""?`:${s}${n}`:"")}function ui(e,t,o){if(e.id.startsWith("member-"))return{title:e.name!==void 0&&e.name!==""?e.name:e.team,sub:e.team,tip:e.team};if(e.remote===!0){const l=e.id.slice(5),u=t.length===1&&t[0].name!==void 0&&t[0].name!==""?t[0].name:void 0,b=mi(t,o);return u!==void 0?{title:u,sub:`${l} · ${b}`,tip:`${u}
|
|
6
|
-
${l}
|
|
7
|
-
${b}`}:{title:l,sub:b,tip:`${l}
|
|
8
|
-
${b}`}}const s=lt(e),n=e.team+(e.name!==void 0&&e.name!==""?" · "+e.name:""),i=di(e.description??""),r=i!==""?i:n===s?"":e.team,c=(e.memberships.length>1?` · 跨队×${e.memberships.length}`:"")+(e.teams!==void 0&&e.teams.length>0?` · 网络队×${e.teams.length}`:"");return{title:s,sub:r+c,tip:i!==""?`${n}
|
|
9
|
-
${i}`:n}}function fi(e){if((e==null?void 0:e.status)===void 0)return"";const t=e.status==="running"?"工作中":"空闲";return typeof e.queued=="number"&&e.queued>0?`${t} · 排队 ${String(e.queued)}`:t}function pi(e){const t=document.createElement("div");t.className="p-node",t.dataset.id=e,t.tabIndex=0;const o=document.createElement("div");o.className="nm";const s=document.createElement("span");s.className="dot";const n=document.createElement("span");n.className="nm-text",o.append(s,n);const i=document.createElement("div");i.className="sub mono";const r=document.createElement("span");r.className="prio mono";const c=document.createElement("span");c.className="work";const l=document.createElement("div");return l.className="sub-row",l.append(i,c),t.append(o,l,r),t}function hi(e,t,o){if(t.remote===!0){const s=(o==null?void 0:o.link)==="linked"?"lnk-linked":(o==null?void 0:o.link)==="stranger"?"lnk-stranger":"";e.className!==`prio mono ${s}`.trim()&&(e.className=`prio mono ${s}`.trim());const n=o===void 0?"":o.verified===!0?"✓":"✗",i=(t.id.startsWith("member-")?"成员":(o==null?void 0:o.link)??"peer")+n;e.textContent!==i&&(e.textContent=i)}else{e.className!=="prio mono"&&(e.className="prio mono");const s=t.memberships[0]!==void 0?`P${t.memberships[0].index}`:"";e.textContent!==s&&(e.textContent=s)}}const eo="dsh-a2a.board.legend";function bi(){const e=document.createElement("details");e.className="p-legend";const t=document.createElement("summary");t.textContent="图例",t.title="边的含义(点击展开 / 收起)";const o=document.createElement("div");o.className="p-legend-rows";const s=(n,i,r)=>{const c=document.createElement("span"),l=document.createElement("i");n&&(l.className="dashed"),r!==void 0&&(l.style.borderTopColor=r),c.append(l,document.createTextNode(i)),o.appendChild(c)};s(!1,"成员边(星形,框→成员)"),s(!0,"跨队多属(虚线)"),s(!0,"roster 网络队框(双线边框)"),s(!1,"活动边(inFlight 路由,瞬时)","var(--accent)"),s(!0,"联邦线(→peer)","var(--federal)"),e.append(t,o);try{e.open=window.localStorage.getItem(eo)==="open"}catch{}return e.addEventListener("toggle",()=>{try{window.localStorage.setItem(eo,e.open?"open":"closed")}catch{}}),e}const Gt="对端未应答(显示的是最后已知状态)";function to(e){const t=new Set;for(const s of e.remoteTeams??[])s.unreachable===!0&&s.via&&t.add(dt(s.via));for(const s of e.peerOrg??[])s.unreachable===!0&&t.add(dt(s.url));const o=new Set;for(const s of e.remoteTeams??[])s.via&&t.has(dt(s.via))&&o.add(`member-${s.team.replace(/[^a-z0-9-]/gi,"-")}`);return{hosts:t,members:o}}function gi(e,t){e.classList.toggle("is-unreachable",t);const o=e.querySelector(".p-frame-unreachable");if(t&&o===null){const s=document.createElement("span");s.className="p-frame-unreachable",s.textContent=Gt,e.appendChild(s)}else t||o==null||o.remove()}function vi(e){return e<680?"narrow":e<1024?"medium":"wide"}function yi(e){const t=new Nn;let o,s={...t.viewport},n={kind:"none"},i=!1,r=-1,c=!0,l=!1;const u=ci(t);let b,m=!1;const x=()=>vi(globalThis.innerWidth||qe),N=()=>{var a;(a=e.viewportStore)==null||a.set(x(),s),e.onDirty()},Y=e.now??Date.now,re=new AbortController,V=[];let M=null,C=!1;const S={signal:re.signal},E=document.createElement("section");E.id="dsh-plan",E.setAttribute("role","tabpanel"),E.setAttribute("aria-label","A2A 规划画布"),E.tabIndex=0,E.style.display="none";const G=document.createElement("div");G.className="p-grid";const y=document.createElement("div");y.className="p-world";const f=document.createElementNS("http://www.w3.org/2000/svg","svg");f.setAttribute("class","p-edges");const _=document.createElement("div");_.className="p-layer p-frames";let p;const R=a=>{var h,g;p!==void 0&&((h=Ie.get(p))==null||h.classList.remove("selected")),p=a,a!==void 0&&((g=Ie.get(a))==null||g.classList.add("selected"))},j=document.createElement("div");j.className="p-layer p-nodes",j.setAttribute("role","listbox"),j.setAttribute("aria-multiselectable","true"),j.setAttribute("aria-label","会话节点"),y.append(f,_,j);const K=document.createElement("div");K.className="p-marquee";const we=document.createElement("div");we.className="p-toolbar";const Me=document.createElement("span");Me.className="p-zoom mono",Me.textContent="100%";const D=(a,h,g)=>{const F=document.createElement("button");return F.type="button",F.textContent=a,F.title=h,F.addEventListener("click",g,S),F},U=()=>{const a=document.createElement("span");return a.className="p-sep",a.setAttribute("role","separator"),a.setAttribute("aria-orientation","vertical"),a};we.append(D("适配","适配视图(快捷键 0)",()=>it()),D("-","缩小",()=>pe(1/1.2)),Me,D("+","放大",()=>pe(1.2)),U(),D("建队","组成团队(G):先框选至少 2 个节点",()=>O.startCreateFromSelection()),D("整理成员","每队框内仅属一队的成员自动排齐(多队成员不动)",()=>vt()),D("一键重排","全板队框+成员重排:框尺寸随内容自适应、框位行流式平铺(远端队框与多归属成员不动)",()=>St()),D("撤销","撤销上一次布局改动:拖动、缩放、整理、重排、载入时避让(Ctrl+Z;入队离队不撤销)",()=>Oe()));const ce=D("未入网","未入网会话(点击选择入网)",()=>O.toggleNetMenu());ce.className="p-netbtn",ce.setAttribute("aria-haspopup","menu"),we.append(U(),ce);const Re=Ws(we,t,lt,a=>ne(a)),Ee=D("节点","节点清单:本机与对等节点(未组队/未入网在此管理)",()=>Z.toggle());Ee.className="p-nodebtn",Ee.setAttribute("aria-haspopup","dialog"),we.appendChild(Ee);const le=document.createElement("span");le.setAttribute("aria-live","polite"),le.className="p-lamp";const He=document.createElement("i"),fe=document.createElement("span");fe.textContent="布局",le.append(He,fe),le.addEventListener("click",()=>{le.classList.contains("error")&&e.onLampClick()},S),le.addEventListener("keydown",a=>{const h=a;(h.key==="Enter"||h.key===" ")&&le.classList.contains("error")&&(h.preventDefault(),e.onLampClick())},S),we.appendChild(le);const q=document.createElement("div");q.className="p-status";const de=document.createElement("span"),ee=document.createElement("span"),te=document.createElement("span");te.className="mut";const Ce=document.createElement("span");Ce.className="mut",q.append(de,ee,te,Ce),q.tabIndex=0,q.setAttribute("role","button"),q.setAttribute("aria-label","定位在途路由与联邦对端"),q.title="定位在途与联邦(回车)",q.addEventListener("click",()=>ve(),S),q.addEventListener("keydown",a=>{const h=a;(h.key==="Enter"||h.key===" ")&&(h.preventDefault(),ve())},S);const Be=bi(),Ye=document.createElement("div");Ye.className="p-notice-stack",Ye.setAttribute("role","log"),Ye.setAttribute("aria-live","polite"),E.append(G,y,K,we,q,Be,Ye);let qe=0,ut=0;const kt=()=>e.viewSize?e.viewSize():{w:E.clientWidth,h:E.clientHeight},Je=()=>{const a=kt();qe=a.w,ut=a.h};function Qe(){y.style.transform=_s(s);const a=24*s.scale;G.style.backgroundSize=`${a}px ${a}px`,G.style.backgroundPosition=`${-s.x*s.scale}px ${-s.y*s.scale}px`,Me.textContent=`${Math.round(s.scale*100)}%`}function vt(){const a=u.capture();ri(t),qt(t,new Set(nt.keys())),u.commit(a),N(),Se()}function St(){const a=u.capture();Vs(t,new Set(nt.keys()))&&(qt(t,new Set(nt.keys())),u.commit(a),N(),Se())}function Se(){Qe(),t.revision!==r&&(r=t.revision,ft(),At(),ps(f,t)),ge()}const Ie=new Map,tt=new Map;function ft(){var h;const a=new Set;for(const[g,F]of t.allFrames()){a.add(g);let P=Ie.get(g);if(P===void 0){P=document.createElement("div"),P.className="p-frame",P.dataset.name=g;const oe=document.createElement("div");oe.className="p-frame-head",oe.dataset.frame=g,oe.tabIndex=0,oe.setAttribute("role","button"),oe.setAttribute("aria-haspopup","menu"),oe.setAttribute("aria-label",`团队框 ${g}(拖动整组,回车菜单)`);const Fe=document.createElement("span");Fe.className="ttl";const Ge=document.createElement("span");Ge.className="cnt mono";const rt=document.createElement("span");rt.className="route mono",oe.append(Fe,Ge,rt),P.appendChild(oe);for(const yt of["n","s","e","w","ne","nw","se","sw"]){const wt=document.createElement("div");wt.className=`p-frame-handle p-h-${yt}`,wt.dataset.frame=g,wt.dataset.dir=yt,P.appendChild(wt)}_.appendChild(P),Ie.set(g,P)}const ue=Ps(g);P.style.setProperty("--frame-line",ue.line),P.style.setProperty("--frame-bg",ue.bg),P.style.left=`${F.x}px`,P.style.top=`${F.y}px`,P.style.width=`${F.w}px`,P.style.height=`${F.h}px`;const W=P.querySelector(".ttl"),B=P.querySelector(".cnt"),z=P.querySelector(".route"),ie=k.has(g),Ae=ie?tn(g):g;W.textContent!==Ae&&(W.textContent=Ae),P.classList.toggle("is-roster",ie);let Le=0,Ne=0;for(const oe of t.allNodes())oe.memberships.find(Ge=>Ge.team===g)!==void 0&&(Le+=1,oe.memberships.length>1&&(Ne+=1));const Ke=`${Le} 成员`+(Ne>0?` +${Ne} 跨队`:"");B.textContent!==Ke&&(B.textContent=Ke);const v=Gs(nt.get(g),Te.has(g)),be=v!==void 0&&w.hosts.has(dt(nt.get(g))),he=(v==null?void 0:v.text)??((h=Ht.find(oe=>oe.name===g))==null?void 0:h.team)??g;z.textContent!==he&&(z.textContent=he),z.title=`${(v==null?void 0:v.title)??""}${be?` · ${Gt}`:""}`,gi(P,be),P.classList.toggle("is-mirror",v!==void 0),P.classList.toggle("is-syncing",(v==null?void 0:v.syncing)===!0);const je=`团队框 ${g}${v!==void 0?`(${v.text})`:""}${be?`(${Gt})`:""}(拖动整组,回车菜单)`,$e=P.querySelector(".p-frame-head");$e.getAttribute("aria-label")!==je&&$e.setAttribute("aria-label",je)}for(const[g,F]of[...Ie])a.has(g)||(F.remove(),Ie.delete(g))}function At(){const a=new Set;for(const h of t.allNodes()){a.add(h.id);let g=tt.get(h.id);g===void 0&&(g=pi(h.id),j.appendChild(g),tt.set(h.id,g));const F=mt(h);g.style.left=`${F.x}px`,g.style.top=`${F.y}px`,g.classList.toggle("cold",!h.live),g.classList.toggle("remote",h.remote===!0);const P=h.live&&h.remote!==!0?I.get(h.id):void 0;g.classList.toggle("is-working",(P==null?void 0:P.status)==="running");const ue=fi(P),W=g.querySelector(".work");W.textContent!==ue&&(W.textContent=ue),g.classList.toggle("selected",t.isSelected(h.id)),g.setAttribute("aria-selected",String(t.isSelected(h.id)));const B=h.id.slice(5),z=ui(h,h.remote===!0?A.get(B)??[]:[],Q.get(B)),ie=h.remote===!0&&(h.id.startsWith("member-")?w.members.has(h.id):w.hosts.has(B));g.classList.toggle("is-unreachable",ie);const Ae=g.querySelector(".nm-text");Ae.textContent!==z.title&&(Ae.textContent=z.title);const Le=g.querySelector(".sub"),Ne=ie?`未应答 · ${z.sub}`:z.sub;Le.textContent!==Ne&&(Le.textContent=Ne);const Ke=ie?`${z.tip} · ${Gt}`:z.tip;g.title!==Ke&&(g.title=Ke);const v=h.id.startsWith("member-")?me.get(h.remoteHandle??""):B;hi(g.querySelector(".prio"),h,h.remote===!0&&v!==void 0?X.get(v):void 0)}for(const[h,g]of[...tt])a.has(h)||(g.remove(),tt.delete(h));Re.refresh()}const d=$s(f,t);let A=new Map,I=new Map;const Q=new Map,X=new Map;let me=new Map;function ge(){d.render(Y())}function ve(){s=$n(Es(t.contentBounds(),d.placements()),E.clientWidth||qe,E.clientHeight||ut),Qe(),N()}const ne=Ys({model:t,viewSize:kt,setVp:a=>{s=a},applyViewport:Qe,markDirty:N,cardEl:a=>tt.get(a)});function We(a){var F;const h=a.sessions.filter(P=>P.live!==!1).length,g=(P,ue,W)=>{const B=document.createElement("b");B.className=ue,B.textContent=W,P.replaceChildren(B)};g(de,"ok",`● ${h} live`),g(ee,"warn",`● ${a.sessions.length-h} cold`),te.textContent=`${((F=a.inFlight)==null?void 0:F.length)??0} inFlight`,Ce.className="mut",Ce.textContent=`${a.teams.length} 队 · ${a.peerCount} peer`}const Te=new Map,Xe=a=>{Te.set(a,(Te.get(a)??0)+1),r=-1},Lt=a=>{r=-1;const h=(Te.get(a)??0)-1;h<=0?Te.delete(a):Te.set(a,h)};let nt=new Map,k=new Set,w=to({});const H=Zs(e.now);function $(a){const h=a.type==="create-team"&&a.roster===!0||k.has(Rt(a));if(h&&a.type==="remove-team"&&!window.confirm(`解散网络队「${tn(a.name)}」并撤回成员与白名单?`))return;if(h&&a.type==="reorder"){L("error","roster 队不支持置顶路由");return}if(h&&(a.type==="create-team"||a.type==="add-member")&&a.ids.some(W=>{var B;return((B=t.getNode(W))==null?void 0:B.remote)===!0||!se.some(z=>z.id===W&&z.joined===!0)})){L("error","roster 只接受本机已入网会话,远端或未入网成员未写入");return}function g(W){const B=z=>{var Ae;const ie=[];for(const Le of z){if(!Le.startsWith("peer-")&&!Le.startsWith("member-")){ie.push(Le);continue}const Ne=(Ae=t.getNode(Le))==null?void 0:Ae.remoteHandle;Ne!==void 0&&Ne!==""&&ie.push(Ne)}return ie};if(W.type==="add-member"||W.type==="remove-member"||W.type==="create-team"){const z=B(W.ids),ie=W.type!=="create-team"?nt.get(W.team):void 0;return z.length>0||ie!==void 0?{...W,ids:z,...ie!==void 0?{fleetPeer:ie}:{}}:W}return W.type==="remove-team"&&nt.has(W.name)?H.fork(W,nt.get(W.name)):W}if(a.type==="add-member"||a.type==="remove-member"||a.type==="reorder"||a.type==="create-team"){const W=a.type==="reorder"?a.ops.map(B=>B.id):[...a.ids];for(const B of W){if(B===""||B.startsWith("peer-")||B.startsWith("member-")||t.getNode(B)!==void 0)continue;const z=se.find(Le=>Le.id===B);if(z===void 0)continue;const ie=o==null?void 0:o.nodes[B],Ae=ie!==void 0?{x:ie.x,y:ie.y}:Sn(B);t.upsertNode({id:B,x:Ae.x,y:Ae.y,label:z.label,team:z.team,name:z.name,description:z.description,live:z.live!==!1,memberships:[],...z.teams!==void 0&&z.teams.length>0?{teams:z.teams}:{}})}}h&&a.type==="create-team"&&k.add(a.name);const F=Os(t,a),P=Rt(a);Xe(P),Se();const ue=g(h?{...a,roster:!0}:a);e.onCanvasAction(ue).then(W=>{Lt(P),!W&&a.type==="create-team"&&h&&k.delete(P),o=Jn(t,a,W,F,o),N(),H.settled(ue,W),Se()},()=>{Lt(P),a.type==="create-team"&&h&&k.delete(P),o=Jn(t,a,!1,F,o),N(),H.settled(ue,!1),L("error","操作通道异常,已回滚"),Se()})}function L(a,h){var F;for(;Ye.childElementCount>=3;)(F=Ye.firstElementChild)==null||F.remove();const g=document.createElement("div");g.className="p-notice"+(a==="error"?" error":""),g.setAttribute("role",a==="error"?"alert":"status"),g.textContent=h,Ye.appendChild(g),V.push(setTimeout(()=>g.remove(),4e3))}const O=Rs({root:E,netBtn:ce,signal:S,model:t,teams:()=>Ht,joined:a=>se.some(h=>h.id===a&&h.joined===!0),isRoster:a=>k.has(a),anchorFor:a=>(a.kind==="node"?tt.get(a.id):Ie.get(a.name))??null,emit:$,notice:L});let se=[],ae=new Set;const Z=li({root:E,trigger:Ee,signal:S,model:t,facts:()=>({sessions:se,canvasMemberIds:ae,remoteTeams:A,teams:Ht}),menuItem:O.menuItem,emit:$,openNameDialog:O.openNameDialog,locate:xe});zo(E,{signal:S,frames:()=>Ie,frameAt:(a,h)=>{const g=_e({clientX:a,clientY:h});return Kt(new Map(t.allFrames()),ct(s,g.x,g.y))},drop:(a,h)=>{var g;return((g=t.getNode(h))==null?void 0:g.memberships.some(F=>F.team===a))===!0?L("info","该会话已在这个队里"):$({type:"add-member",team:a,ids:[h]})}});function xe(a){var F;const h=t.getNode(a);if(h===void 0)return;Z.close();const g=((F=e.viewSize)==null?void 0:F.call(e))??{w:E.clientWidth>0?E.clientWidth:800,h:E.clientHeight>0?E.clientHeight:600};s=Nt({scale:s.scale,x:h.x-g.w/(2*s.scale),y:h.y-g.h/(2*s.scale)}),Qe(),r=-1,Se()}function _e(a){const h=E.getBoundingClientRect();return{x:a.clientX-h.left,y:a.clientY-h.top}}function J(a,h){var W;const g=_e(h),F=ct(s,g.x,g.y),P=Kt(new Map(t.allFrames()),F),ue=a.ids.filter(B=>{const z=t.getNode(B);return z===void 0?!1:z.remote!==!0?!0:z.remoteHandle!==void 0&&z.remoteHandle!==""});if(P!==void 0){const B=ue.filter(z=>{var ie;return!((ie=t.getNode(z))!=null&&ie.memberships.some(Ae=>Ae.team===P))});if(B.length>0){$({type:"add-member",team:P,ids:B});return}if(a.ids.length===1&&((W=t.getNode(a.clicked))==null?void 0:W.remote)!==!0){const z=t.teamMemberIds(P),ie=Fs(t,P);ie.join("\0")!==z.join("\0")&&$({type:"reorder",team:P,ops:vn(z,ie)})}}if(a.rosterOrigin!==void 0&&P!==a.rosterOrigin){const B=a.ids.filter(z=>t.teamMemberIds(a.rosterOrigin).includes(z));B.length>0&&$({type:"remove-member",team:a.rosterOrigin,ids:B})}}function Pe(a){if(qe===0&&Je(),O.isDialogOpen()){a.preventDefault();return}const h=a.target;if(O.isMenuOpen()){if(h!==null&&h.closest(".p-menu")!==null)return;O.closeMenu(),a.preventDefault();return}if(h!==null&&h.closest("button, input, textarea, select, .p-toolbar, .p-search, .p-lamp, .p-status, .p-legend")!==null)return;b=u.capture();const g=_e(a);if(a.button===2){M={x:g.x,y:g.y,target:a.target,moved:!1},a.preventDefault();try{E.setPointerCapture(a.pointerId??0)}catch{}return}const F=h!==null?h.closest(".p-node"):null,P=h!==null?h.closest(".p-frame-head"):null;if((F!==null||P!==null)&&a.button===1){n={kind:"pan",last:g,moved:!1},a.preventDefault();try{E.setPointerCapture(a.pointerId??0)}catch{}return}const ue=h!==null?h.closest(".p-frame-handle"):null;if(p!==void 0){const W=Ie.get(p),B=h!==null&&W!==void 0&&(W.contains(h)||W===h),z=P!==null&&P.dataset.frame===p;!B&&!z&&R(void 0)}if(ue!==null&&a.button===0){const W=ue.dataset.frame??"";R(W);const B=t.getFrame(W);if(B===void 0)return;n={kind:"frame-resize",name:W,dir:ue.dataset.dir??"se",startRect:{...B},origin:ct(s,g.x,g.y),moved:!1},a.preventDefault();try{E.setPointerCapture(a.pointerId??0)}catch{}return}if(F!==null){if(a.button!==0)return;const W=F.dataset.id??"",B=t.isSelected(W);!B&&!a.shiftKey&&t.setSelection([W]);const z=a.shiftKey||B?t.isSelected(W)?t.selectedIds():[...t.selectedIds(),W]:[W],ie=Kt(new Map(t.allFrames()),ct(s,g.x,g.y));n={kind:"node",clicked:W,ids:z,...ie&&k.has(ie)&&t.teamMemberIds(ie).includes(W)?{rosterOrigin:ie}:{},last:ct(s,g.x,g.y),moved:!1,el:F},F.classList.add("dragging")}else if(P!==null){if(a.button!==0)return;const W=P.dataset.frame??"";R(W);const B=t.beginFrameDrag(W);if(B===void 0)return;n={kind:"frame",name:W,snap:B,origin:ct(s,g.x,g.y),moved:!1}}else if(a.button===1||a.button===0&&i)n={kind:"pan",last:g,moved:!1};else if(a.button===0)n={kind:"marquee",origin:g,last:g,additive:a.shiftKey},K.style.display="block",K.style.left=`${g.x}px`,K.style.top=`${g.y}px`,K.style.width="0px",K.style.height="0px";else return;a.preventDefault();try{E.setPointerCapture(a.pointerId??0)}catch{}}function Ze(a){const h=_e(a);if(M!==null){const g=h.x-M.x,F=h.y-M.y;Math.hypot(g,F)>4&&(M.moved=!0,s=Nt(un(s,-g,-F)),M.x=h.x,M.y=h.y,Qe());return}if(n.kind==="node"){const g=ct(s,h.x,h.y),F=g.x-n.last.x,P=g.y-n.last.y;if(F===0&&P===0)return;n.moved=!0,n.last=g,t.dragNodes(n.ids,F,P);const ue=Kt(new Map(t.allFrames()),g),W=n.ids.filter(z=>{const ie=t.getNode(z);return ie===void 0?!1:ie.remote!==!0||ie.remoteHandle!==void 0&&ie.remoteHandle!==""}),B=ue!==void 0&&W.length>0;for(const[z,ie]of Ie)ie.classList.toggle("drop-target",B&&z===ue);Se()}else if(n.kind==="frame"){const g=ct(s,h.x,h.y),F=g.x-n.origin.x,P=g.y-n.origin.y;if(!n.moved&&F===0&&P===0)return;n.moved=!0,t.applyFrameDrag(n.snap,F,P),Se()}else if(n.kind==="frame-resize"){const g=ct(s,h.x,h.y),F=g.x-n.origin.x,P=g.y-n.origin.y;if(!n.moved&&F===0&&P===0)return;n.moved=!0;const ue=220,W=120,B={...n.startRect};let{x:z,y:ie,w:Ae,h:Le}=B;n.dir.includes("e")&&(Ae=Math.max(ue,B.w+F)),n.dir.includes("s")&&(Le=Math.max(W,B.h+P)),n.dir.includes("w")&&(Ae=Math.max(ue,B.w-F),z=B.x+(B.w-Ae)),n.dir.includes("n")&&(Le=Math.max(W,B.h-P),ie=B.y+(B.h-Le)),t.setFrame(n.name,{x:Math.round(z),y:Math.round(ie),w:Math.round(Ae),h:Math.round(Le)}),Se()}else if(n.kind==="pan")s=un(s,h.x-n.last.x,h.y-n.last.y),n.last=h,n.moved=!0,Qe();else if(n.kind==="marquee"){const g=Math.min(n.origin.x,h.x),F=Math.min(n.origin.y,h.y);K.style.left=`${g}px`,K.style.top=`${F}px`,K.style.width=`${Math.abs(h.x-n.origin.x)}px`,K.style.height=`${Math.abs(h.y-n.origin.y)}px`,n.last=h}}function et(a){var h,g;if(M!==null){const F=M.moved,P=M.target,ue=M.x,W=M.y;M=null,F?(C=!0,N()):P!==null&&O.contextMenuAt(ue,W,P);return}if(n.kind==="node"){const F=n.clicked;if(n.moved)J(n,a),N();else if(a.shiftKey){const P=t.selectedIds();t.setSelection(P.includes(F)?P.filter(ue=>ue!==F):[...P,F])}else t.setSelection([F]),(h=e.onNodePick)==null||h.call(e,F);for(const P of Ie.values())P.classList.remove("drop-target");(g=n.el)==null||g.classList.remove("dragging"),Se()}else if(n.kind==="frame"||n.kind==="frame-resize")n.moved&&(qt(t,new Set(nt.keys()),n.name),N(),Se());else if(n.kind==="pan")n.moved&&N();else if(n.kind==="marquee"){const F=n.last,P=ct(s,Math.min(n.origin.x,F.x),Math.min(n.origin.y,F.y)),ue=ct(s,Math.max(n.origin.x,F.x),Math.max(n.origin.y,F.y));t.marqueeSelect({x:P.x,y:P.y,w:ue.x-P.x,h:ue.y-P.y},n.additive),K.style.display="none",Se()}n={kind:"none"},b!==void 0&&(u.commit(b),b=void 0);try{E.releasePointerCapture(a.pointerId??0)}catch{}}function pt(a){var g;for(const F of Ie.values())F.classList.remove("drop-target");n.kind==="node"&&((g=n.el)==null||g.classList.remove("dragging"));const h=n.kind==="pan"&&n.moved||(M==null?void 0:M.moved)===!0;K.style.display="none",M=null,n={kind:"none"},b!==void 0&&u.revert(b)&&Se(),h&&N(),b=void 0;try{E.releasePointerCapture(a.pointerId??0)}catch{}}function Ve(a){O.isMenuOpen()&&O.closeMenu();const h=_e(a);if(a.shiftKey&&!a.ctrlKey){const g=a.deltaMode===1?16:1;s=Nt(un(s,(a.deltaX??0)*g,(a.deltaY??0)*g))}else{const g=a.deltaMode===1?16:1,F=Math.exp(-((a.deltaY??0)*g)*.0015);s=Xn(s,F,h.x,h.y)}a.preventDefault(),Qe(),N()}function pe(a){Je(),s=Xn(s,a,qe/2,ut/2),Qe(),N()}function Oe(){u.undo()?(N(),Se()):L("info","没有可撤销的布局改动")}function it(){Je(),s=qn(Un(t.contentBounds(),t.allNodes()),qe,ut,zn(we,q)),Qe(),N()}function It(a){var ue,W,B,z,ie,Ae,Le;if(O.isDialogOpen()||((W=(ue=a.target)==null?void 0:ue.closest)==null?void 0:W.call(ue,".p-search"))!==null)return;if((a.ctrlKey||a.metaKey)&&a.key.toLowerCase()==="k"){a.preventDefault(),Re.focus();return}if((a.ctrlKey||a.metaKey)&&!a.shiftKey&&a.key.toLowerCase()==="z"){a.preventDefault(),Oe();return}if(a.ctrlKey||a.metaKey)return;if(O.isMenuOpen()){a.key==="Escape"&&(O.closeMenu(),a.preventDefault());return}if(a.key===" "&&a.target===E){i=!0,a.preventDefault();return}const h=((z=(B=a.target)==null?void 0:B.closest)==null?void 0:z.call(B,".p-frame-head"))??null;if((a.key==="Enter"||a.key===" ")&&h!==null){a.preventDefault();const Ne=h.getBoundingClientRect();O.contextMenuAt(Ne.left+Ne.width/2,Ne.top+Ne.height/2,h);return}if(a.key===" "&&((Ae=(ie=a.target)==null?void 0:ie.classList)!=null&&Ae.contains("p-node"))){const Ke=a.target.dataset.id??"",v=t.selectedIds();t.setSelection(v.includes(Ke)?v.filter(be=>be!==Ke):[...v,Ke]),Se(),a.preventDefault();return}if(a.key==="F10"&&a.shiftKey||a.key==="ContextMenu"){a.preventDefault();const Ne=document.activeElement??null,Ke=((Le=Ne==null?void 0:Ne.getBoundingClientRect)==null?void 0:Le.call(Ne))??{left:0,top:0,width:0,height:0};O.contextMenuAt(Ke.left+Ke.width/2,Ke.top+Ke.height/2,Ne);return}if(a.key==="Delete"||a.key==="Backspace"){a.preventDefault(),cn();return}if(a.altKey&&(a.key==="ArrowUp"||a.key==="ArrowDown")){a.preventDefault(),ko(a.key==="ArrowUp");return}if(a.key==="g"||a.key==="G"){O.startCreateFromSelection();return}if(a.key==="0"){it();return}if(a.key==="="||a.key==="+"){pe(1.2);return}if(a.key==="-"){pe(1/1.2);return}if(a.key==="Escape"){if(O.isMenuOpen()){O.closeMenu(),Se();return}t.setSelection([]),Se();return}const g=a.shiftKey?40:8,P={ArrowLeft:[-g,0],ArrowRight:[g,0],ArrowUp:[0,-g],ArrowDown:[0,g]}[a.key];if(P!==void 0){a.preventDefault();const Ne=t.selectedIds();if(Ne.length>0){const Ke=u.capture();t.nudge(Ne,P[0],P[1]),u.commit(Ke),Se(),N()}}}function cn(){var F,P,ue;const a=document.activeElement,h=((F=a==null?void 0:a.closest)==null?void 0:F.call(a,".p-frame-head"))??null,g=((P=a==null?void 0:a.closest)==null?void 0:P.call(a,".p-node"))??null;if(h!==null){$({type:"remove-team",name:h.dataset.frame??""});return}if(g!==null){const W=g.dataset.id??"",B=((ue=t.getNode(W))==null?void 0:ue.memberships.map(z=>z.team))??[];if(B.length===0){L("info","该节点未加入任何团队");return}if(B.length===1){$({type:"remove-member",team:B[0],ids:[W]});return}O.openMenu(window.innerWidth/2,window.innerHeight/2,{kind:"node",id:W},"leave",g);return}L("info","焦点不在节点或团队框上")}function ko(a){var Ae,Le;const h=document.activeElement,g=((Ae=h==null?void 0:h.closest)==null?void 0:Ae.call(h,".p-node"))??null;if(g===null)return;const F=g.dataset.id??"",P=((Le=t.getNode(F))==null?void 0:Le.memberships)??[];if(P.length!==1)return;const ue=P[0].team,W=t.teamMemberIds(ue),B=W.indexOf(F),z=a?Math.max(0,B-1):Math.min(W.length-1,B+1);if(z===B)return;const ie=[...W];ie.splice(B,1),ie.splice(z,0,F),$({type:"reorder",team:ue,ops:vn(W,ie)})}function Mn(a){a.key===" "&&(i=!1)}E.addEventListener("pointerdown",a=>Pe(a),S),E.addEventListener("pointermove",a=>Ze(a),S),E.addEventListener("pointerup",a=>et(a),S),E.addEventListener("pointercancel",a=>pt(a),S),E.addEventListener("wheel",a=>Ve(a),{...S,passive:!1}),E.addEventListener("keydown",a=>It(a),S),E.addEventListener("keyup",a=>Mn(a),S),E.addEventListener("contextmenu",a=>{var g,F;const h=a;if(((F=(g=h.target)==null?void 0:g.closest)==null?void 0:F.call(g,"input, textarea, .p-search"))==null){if(h.preventDefault(),C){C=!1;return}O.contextMenuAt(h.clientX,h.clientY,h.target)}},S);let Ht=[];function Eo(a){var Ke;Ht=a.teams,k=new Set([...a.teams.filter(v=>v.kind==="roster").map(v=>v.name),...[...k].filter(v=>Te.has(v))]),a.peers,d.setInFlight(a.inFlight??[]),se=a.sessions,O.setUnjoined(a.sessions.filter(v=>v.joined!==!0&&!v.id.startsWith("peer-")));const h=Ss(a.teams);ae=new Set(h.keys());const g=new Set,F=v=>{const be=h.get(v)??[];if(Te.size===0)return be;const he=be.filter($e=>!Te.has($e.team)),je=[];for(const[$e]of Te){const Fe=t.teamMemberIds($e).indexOf(v);Fe>=0&&je.push({team:$e,index:Fe})}return[...he,...je]};let P;if(o===void 0&&!t.allNodes().some(v=>v.remote!==!0)){const v=a.sessions.filter(be=>{var he;return be.joined===!0&&(F(be.id).length>0||(((he=be.teams)==null?void 0:he.length)??0)>0)}).map(be=>be.id);Je(),P=ds(a.teams,v,qe>0?qe:void 0)}const ue=a.peerOrg!==void 0?As(a.peerOrg,a.sessions,a.remoteTeams):new Set;a.peerOrg!==void 0&&(ae=new Set([...ae,...ue]));for(const v of a.sessions){if(v.joined!==!0)continue;const be=F(v.id);if(!(be.length===0&&(v.teams===void 0||v.teams.length===0)&&!ue.has(v.id)))if(g.add(v.id),t.getNode(v.id)!==void 0)t.upsertNode({id:v.id,x:t.getNode(v.id).x,y:t.getNode(v.id).y,label:v.label,team:v.team,name:v.name,description:v.description,live:v.live!==!1,memberships:be,...v.teams!==void 0&&v.teams.length>0?{teams:v.teams}:{}});else{const he=o==null?void 0:o.nodes[v.id];let je,$e;if(he!==void 0)je=he.x,$e=he.y;else{const oe=(P==null?void 0:P.get(v.id))??Sn(v.id);je=oe.x,$e=oe.y}t.upsertNode({id:v.id,x:je,y:$e,label:v.label,team:v.team,name:v.name,description:v.description,live:v.live!==!1,memberships:be,...v.teams!==void 0&&v.teams.length>0?{teams:v.teams}:{}})}}for(const v of t.nodeIds())!g.has(v)&&!v.startsWith("peer-")&&!v.startsWith("member-")&&t.removeNode(v);const W=new Set;A=bs(a.remoteTeams??[]),me=new Map([...A].flatMap(([v,be])=>be.map(he=>[he.team,v]))),I=new Map(a.sessions.map(v=>[v.id,{status:v.status,queued:v.queued}])),w=to(a),Q.clear();for(const v of a.peers??[])Q.set(dt(v.url),v.score),X.set(dt(v.url),{link:v.link,verified:v.verified});if(a.peers!==void 0){const v=t.contentBounds(),be=xs(a.peers,v);a.peers.forEach((he,je)=>{var wt,An,Ln,In;const $e=hs(he.url);W.add($e);const oe=o==null?void 0:o.nodes[$e],Fe=t.getNode($e),Ge=Fe!==void 0?{x:Fe.x,y:Fe.y}:oe!==void 0?{x:oe.x,y:oe.y}:{x:((wt=be[je])==null?void 0:wt.x)??200,y:((An=be[je])==null?void 0:An.y)??0},rt=dt(he.url),yt=(In=(Ln=A.get(rt))==null?void 0:Ln.find(Io=>Io.team.includes("/")))==null?void 0:In.team;t.upsertNode({id:$e,x:Ge.x,y:Ge.y,label:he.url,team:"",name:he.url,peerUrl:he.url,remoteHandle:yt,live:!0,remote:!0,memberships:[]}),t.upsertScore($e,he.score)})}for(const v of t.nodeIds())v.startsWith("peer-")&&!W.has(v)&&t.removeNode(v);const B=new Set;for(const[v,be]of A){const he=t.allNodes().find(oe=>oe.remote===!0&&dt(oe.peerUrl??"")===v&&!oe.id.startsWith("member-")),je=((he==null?void 0:he.x)??400)+190;let $e=(he==null?void 0:he.y)??0;for(const oe of be){if(!oe.team.includes("/"))continue;const Fe=`member-${oe.team.replace(/[^a-z0-9-]/gi,"-")}`;if(B.has(Fe))continue;B.add(Fe);const Ge=o==null?void 0:o.nodes[Fe],rt=t.getNode(Fe),yt=rt!==void 0?{x:rt.x,y:rt.y}:Ge!==void 0?{x:Ge.x,y:Ge.y}:{x:je,y:$e};$e+=92,t.upsertNode({id:Fe,x:yt.x,y:yt.y,label:oe.team,team:oe.team,name:oe.name!==void 0&&oe.name!==""?oe.name:oe.team,remoteHandle:oe.team,live:!0,remote:!0,memberships:[]})}}for(const v of t.nodeIds())v.startsWith("member-")&&!B.has(v)&&t.removeNode(v);const z=new Map;for(const v of t.allNodes())v.remote!==!0||v.remoteHandle===void 0||v.remoteHandle===""||(!z.has(v.remoteHandle)||v.id.startsWith("member-"))&&z.set(v.remoteHandle,v.id);for(const v of a.teams){if(Te.has(v.name))continue;const be=[];for(const $e of v.members){const oe=z.get($e.id)??$e.id;t.getNode(oe)!==void 0&&be.push(oe)}const he=[...t.teamMemberIds(v.name)].sort().join("|"),je=[...be].sort().join("|");he!==je&&t.setTeamMembers(v.name,be)}const ie=new Map,Ae=nt;if(nt=ie,a.peerOrg!==void 0){let v=0;const be=new Set(a.teams.map(he=>he.name));H.sweep(a.peerOrg);for(const he of a.peerOrg){const je=new Set((a.remoteTeams??[]).map(oe=>oe.team)),$e=wo(a.sessions,je);for(const oe of he.org){if(oe.name===""||be.has(oe.name)||H.hides(oe.name,he.url))continue;const Fe=oe.members.map(rt=>Ms(rt,$e,a.remoteTeams,he.url)).filter(rt=>t.getNode(rt)!==void 0),Ge=(Ke=o==null?void 0:o.frames)==null?void 0:Ke[oe.name];t.getFrame(oe.name)===void 0&&t.setFrame(oe.name,Ge!==void 0?{x:Ge.x,y:Ge.y,w:Ge.w,h:Ge.h}:{x:200+v%4*280,y:940+Math.floor(v/4)*160,w:250,h:130}),t.setTeamMembers(oe.name,Fe),ie.set(oe.name,he.url),v+=1}}}for(const[v,be]of Ae)ie.has(v)||t.removeFrame(v);const Le=new Map;for(const v of t.allNodes())v.remote===!0&&v.remoteHandle!==void 0&&v.remoteHandle!==""&&Le.set(v.remoteHandle,v.id);const Ne=go(a.teams);for(const v of a.teams){if(t.getFrame(v.name)!==void 0||Te.has(v.name))continue;const be=o==null?void 0:o.frames[v.name];if(be!==void 0){t.setFrame(v.name,{...be});continue}const he=[],je=[];for(const oe of v.members){const Fe=t.getNode(Le.get(oe.id)??oe.id);Fe!==void 0&&(je.push(mt(Fe)),Ne.get(Fe.id)===v.name&&he.push(mt(Fe)))}const $e=he.length>0?he:je;$e.length>0&&t.setFrame(v.name,En($e))}for(const[v]of t.allFrames())Te.has(v)||!a.teams.some(be=>be.name===v)&&!ie.has(v)&&t.removeFrame(v);if(Z.refresh(),We(a),!l&&n.kind==="none"&&t.nodeIds().length>0){l=!0;const v=u.capture();qt(t,new Set(nt.keys())),u.commit(v)}c&&n.kind==="none"&&t.nodeIds().length>0&&(Je(),qe>0&&ut>0&&(c=!1,s=qn(Un(t.contentBounds(),t.allNodes()),qe,ut,zn(we,q)))),Se()}function Sn(a){return vo(a,t.allNodes().filter(h=>h.remote!==!0))}function No(a){const h=ho(a);if(h===void 0)return;o=h;const g=e.viewportStore;if(g===void 0)c=!1,n.kind==="none"&&(s=Nt({...h.viewport}));else if(!m&&n.kind==="none"){m=!0;const F=g.get(x());F!=null&&Number.isFinite(F.x)&&Number.isFinite(F.y)&&Number.isFinite(F.scale)?(s=Nt({x:F.x,y:F.y,scale:F.scale}),c=!1):x()==="wide"&&(s=Nt({...h.viewport}),c=!1)}r=-1,Se()}function $o(){return rs(s,t.positions(),t.frameRects())}function Mo(a,h){le.classList.remove("pending","saved","error"),a==="pending"&&le.classList.add("pending"),a==="saved"&&le.classList.add("saved"),a==="error"&&le.classList.add("error"),a==="error"?(le.tabIndex=0,le.setAttribute("role","button"),le.setAttribute("aria-label","布局保存失败,按回车重试")):(le.removeAttribute("tabindex"),le.removeAttribute("role"),le.removeAttribute("aria-label"));const g=a==="pending"?"布局待保存…":a==="saved"?`布局已保存 ${h??""}`.trimEnd():a==="error"?"保存失败 · 回车重试":"布局";fe.textContent=g}function So(){E.style.display="block",Je(),Qe(),E.focus()}function Ao(){E.style.display="none"}function Lo(){re.abort();for(const a of V)clearTimeout(a)}return{root:E,reconcile:Eo,activate:So,deactivate:Ao,adoptExternalLayout:No,snapshotDoc:$o,setLamp:Mo,notice:L,destroy:Lo,seam:{pointerDown:Pe,pointerMove:Ze,pointerUp:et,pointerCancel:pt,wheel:Ve,key:It,keyUp:Mn,contextMenu(a){a.preventDefault(),O.contextMenuAt(a.clientX,a.clientY,a.target)}}}}const wi=800;function xi(e){let t,o=!1,s=!1,n=!1,i="idle";function r(b){b!==i&&(i=b,e.onLamp(b))}function c(){t!==void 0&&(t(),t=void 0)}function l(){c(),t=e.schedule(()=>{t=void 0,u(!1)},wi)}async function u(b){if(o){s=!0;return}o=!0,c();const m=e.snapshot();let x;try{x=JSON.stringify(m)}catch{o=!1,r("error"),e.onHttpError("layout document is not JSON-serializable");return}try{const N=await e.send(m,{keepalive:b});if(N===null||typeof N!="object"||N.ok!==!0){r("error");const Y=N!==null&&typeof N=="object"&&typeof N.error=="string"?N.error:"layout save refused";e.onHttpError(`layout save: ${Y}`)}else JSON.stringify(e.snapshot())===x&&(e.onAdopt(N.layout),r("saved"))}catch(N){r("error"),e.onHttpError(`layout save unreachable: ${String((N==null?void 0:N.message)??N).slice(0,80)}`)}if(o=!1,i==="error"){n=!1;return}if(n){n=!1,u(!0);return}s&&(s=!1,r("pending"),l())}return{markDirty(){if(s=!1,r("pending"),o){s=!0;return}l()},retry(){i!=="error"||o||(r("pending"),u(!1))},flush(){if(o){n=!0,s=!0;return}c(),u(!0)},isBusy(){return o},dispose(){c()}}}function no(e){return e!=null&&typeof e.error=="string"?e.error:void 0}function Ci(e){const t=new Map;let o=0;function s(r,c){o+=1;const l=t.get(r)??Promise.resolve(),u=async()=>{try{return await c()}finally{o-=1}},b=l.then(u,u);return t.set(r,b.then(()=>{},()=>{})),b}async function n(r){var re,V,M,C;let c;try{c=await e.send(r)}catch(S){const E=String((S==null?void 0:S.message)??S).slice(0,80);return e.onNotice("error",`画布不可达:${E}`),!1}if(c.status>=400)return e.onNotice("error",no(c.body)??`HTTP ${c.status}`),!1;if(((re=c.body)==null?void 0:re.ok)===!0)return!0;const l=c.body!=null&&typeof c.body=="object"?no(c.body):void 0;if(l!==void 0)return e.onNotice("error",l),!1;const u=String(r.name??""),b=String(r.id??""),m=(V=c.body)==null?void 0:V.members,x=(M=c.body)==null?void 0:M.teams,N=Array.isArray(m)&&m.every(S=>typeof S=="string"),Y=Array.isArray(x)&&x.every(S=>typeof S=="string");return((C=c.body)==null?void 0:C.ok)===!1&&(r.action==="add-member"&&N&&m.includes(b)||r.action==="remove-member"&&N&&!m.includes(b)||r.action==="remove"&&Y&&!x.includes(u))?!0:(e.onNotice("error","画布操作未确认:"+String(r.action)+"(可能队伍/成员已达上限,请重试)"),!1)}async function i(r,c){for(const l of c)if(!await n({...r,id:l}))return!1;return!0}return{createTeam(r,c){return s(r,async()=>{if(!await n({action:"create",name:r}))return!1;for(let l=0;l<c.length;l++)if(!await n({action:"add-member",name:r,id:c[l]}))return!1;return!0})},addMembers(r,c){return s(r,()=>i({action:"add-member",name:r},c))},removeMembers(r,c){return s(r,()=>i({action:"remove-member",name:r},c))},runRosterOps(r,c){return s(r,async()=>{for(const l of c){const u=l.op==="remove"?{action:"remove-member",name:r,id:l.id}:{action:"add-member",name:r,id:l.id};if(!await n(u))return!1}return!0})},removeTeam(r){return s(r,()=>n({action:"remove",name:r}))},hasPending(){return o>0}}}const Co=document.getElementById("app"),ki=(()=>{try{return window.sessionStorage.getItem("dsh_a2a_key")??""}catch{return""}})(),yn=window.__DSH_A2A_KEY__??ki,ze=(e,t={})=>fetch(e,{...t,headers:{...t.headers??{},...yn!==""?{"X-API-Key":yn}:{}}});yn===""&&ze("/__dsh_a2a/owner-settings").then(e=>{if(e.status!==401)return;const t=document.createElement("div");t.className="nexus-keygate",t.style.cssText="position:fixed;inset:0;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:10px;background:#fff;z-index:9999;font:14px/1.5 system-ui,sans-serif;color:#000";const o=document.createElement("div");o.textContent="此面板经远程面打开(密钥不随页面下发)——输入控制密钥";const s=document.createElement("input");s.type="password",s.placeholder="X-API-Key",s.setAttribute("aria-label","控制密钥");const n=document.createElement("button");n.type="button",n.textContent="进入面板";const i=document.createElement("div");i.style.color="#b00";const r=()=>{const c=s.value.trim();c!==""&&fetch("/__dsh_a2a/owner-settings",{headers:{"X-API-Key":c}}).then(l=>{if(l.status===401){i.textContent="密钥不对,再试一次";return}try{window.sessionStorage.setItem("dsh_a2a_key",c)}catch{}window.location.reload()})};n.addEventListener("click",r),s.addEventListener("keydown",c=>{c.key==="Enter"&&r()}),t.append(o,s,n,i),document.body.appendChild(t)});const Pt=document.createElement("div");Pt.className="nexus-fault";Co.appendChild(Pt);const{fault:wn,clear:Ei}=Oo({show(e){Pt.textContent=e,Pt.style.display="block"},hide(){Pt.style.display="none"}},e=>console.error(e));let Qt;const oo="dsh-a2a.viewport.",Ni={get(e){try{const t=window.localStorage.getItem(oo+e);return t===null?void 0:JSON.parse(t)}catch{return}},set(e,t){try{window.localStorage.setItem(oo+e,JSON.stringify({x:t.x,y:t.y,scale:t.scale}))}catch{}}},st=yi({viewportStore:Ni,onDirty:()=>on.markDirty(),onLampClick:()=>on.retry(),onNodePick:e=>{Qt==null||Qt(e)},onCanvasAction:async e=>{const t=await Mi(e);return an(),t}}),on=xi({snapshot:()=>st.snapshotDoc(),send:(e,t)=>ze("/__dsh_a2a/canvas-layout",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"save",layout:e}),cache:"no-store",keepalive:t.keepalive}).then(async o=>await o.json()),schedule:(e,t)=>{const o=setTimeout(e,t);return()=>{clearTimeout(o)}},now:Date.now,onLamp:e=>{xn=e;const t=new Date,o=String(t.getHours()).padStart(2,"0")+":"+String(t.getMinutes()).padStart(2,"0");st.setLamp(e,o)},onAdopt:e=>{st.adoptExternalLayout(e)},onHttpError:e=>wn(e)});window.addEventListener("pagehide",()=>on.flush());const Ot=Ci({send:async e=>{const t=await ze("/__dsh_a2a/canvas",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),cache:"no-store"});return{status:t.status,body:await t.json()}},onNotice:(e,t)=>st.notice(e,t)});async function so(e,t,o,s){const n=await ze("/__dsh_a2a/fleet-canvas-op",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({peer:e,op:t,name:o,...s!==void 0?{id:s}:{}}),cache:"no-store"}).catch(()=>{}),i=n!==void 0?await n.json().catch(()=>{}):void 0;return(i==null?void 0:i.ok)===!0&&t==="remove"&&i.removed===!1&&st.notice("info",`属主那边已没有「${o}」,无需解散`),(i==null?void 0:i.ok)===!0?!0:(st.notice("error",`跨主机团队操作失败:${String((i==null?void 0:i.error)??"对端无响应")}`),!1)}async function $i(e,t){const o=async s=>{const n=await ze("/__dsh_a2a/roster-op",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:t,...s})}).catch(()=>{}),i=n!==void 0?await n.json().catch(()=>{}):void 0;return n!=null&&n.ok&&(i==null?void 0:i.ok)===!0?!0:(st.notice("error",`roster 操作失败:${String((i==null?void 0:i.error)??(n?`HTTP ${n.status}`:"无响应"))}`),!1)};if(e.type==="create-team")return o({op:"create",ids:e.ids});if(e.type==="remove-team")return o({op:"dissolve"});if(e.type==="add-member"||e.type==="remove-member"){for(const s of e.ids)if(!await o({op:e.type,id:s}))return!1;return!0}return st.notice("error","roster 不支持该操作"),!1}function Mi(e){if((e.type==="add-member"||e.type==="remove-member")&&e.fleetPeer!==void 0){const t=e.fleetPeer;return(async()=>{for(const o of e.ids)if(!await so(t,e.type,e.team,o))return!1;return!0})()}if(e.type==="remove-team"&&e.fleetPeer!==void 0)return so(e.fleetPeer,"remove",e.name);if(e.roster===!0){const t=xo(Rt(e));return t!==void 0?$i(e,t):(st.notice("error","无效的 roster 框名"),Promise.resolve(!1))}switch(e.type){case"create-team":return Ot.createTeam(e.name,e.ids,e.created);case"add-member":return Ot.addMembers(e.team,e.ids);case"remove-member":return Ot.removeMembers(e.team,e.ids);case"remove-team":return Ot.removeTeam(e.name);case"reorder":return Ot.runRosterOps(e.team,e.ops);case"join-network":case"leave-network":return Si(e.type==="join-network"?"join":"leave",e.id)}}async function Si(e,t){const o=await ze(`/__dsh_a2a/${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:t}),cache:"no-store"}).catch(()=>{});return o!==void 0&&o.ok}let xn="idle",fn=new Set,io=0,sn=!1,ro,pn=!1;async function Ai(){const e=await ze("/__dsh_a2a/canvas-layout",{cache:"no-store"});if(!e.ok)throw new Error(`/__dsh_a2a/canvas-layout ${e.status}`);return(await e.json()).layout??null}const rn=ss({now:()=>Date.now(),async ownerSettingsRead(){try{return await(await ze("/__dsh_a2a/owner-settings")).json()}catch{return{ok:!1,error:"unreachable"}}},async ownerSettingsWrite(e){try{return await(await ze("/__dsh_a2a/owner-settings",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})).json()}catch{return{ok:!1,error:"unreachable"}}},async abandon(e,t){try{return(await ze("/__dsh_a2a/tasks/abandon",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({task_id:e,reason:t})})).ok}catch{return!1}},copy(e){var t;(t=navigator.clipboard)==null||t.writeText(e).catch(()=>{})},async cliHomeOptions(e,t){try{const o=await ze("/__dsh_a2a/canvas",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({action:"cli-home-options",name:e,id:t})}),s=await o.json();return{...s,ok:o.ok&&s.ok===!0}}catch(o){return{ok:!1,error:String(o)}}},async canvasOp(e,t,o,s){try{const n=await ze("/__dsh_a2a/canvas",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({action:e,name:t,id:o,...s===void 0?{}:{home:s}})}),i=await n.json().catch(()=>({}));return n.ok&&i.ok!==!1?!0:(console.warn(`canvas ${e} ${t}: ${i.error??`HTTP ${n.status}`}`),!1)}catch{return!1}},async dispatchQuick(e,t){try{const o=await ze("/__dsh_a2a/dispatch",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({team:e,message:t})}),s=await o.json().catch(()=>({}));return{ok:o.ok&&s.ok===!0,task_id:s.task_id,reply:s.reply,error:s.error??`HTTP ${o.status}`}}catch(o){return{ok:!1,error:o instanceof Error?o.message:String(o)}}},async sessionLog(e){try{const t=await ze(`/__dsh_a2a/session-log?id=${encodeURIComponent(e)}`),o=await t.json().catch(()=>({}));return{ok:t.ok&&o.ok===!0,messages:o.messages,error:o.error??(t.ok?void 0:`HTTP ${t.status}`)}}catch(t){return{ok:!1,error:t instanceof Error?t.message:String(t)}}},async sessionLogList(){try{const e=await ze("/__dsh_a2a/session-log"),t=await e.json().catch(()=>({}));return{ok:e.ok&&t.ok===!0,sessions:t.sessions,count:typeof t.count=="number"?t.count:void 0,error:t.error??(e.ok?void 0:`HTTP ${e.status}`)}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}},async remoteSessionLog(e){try{const t=new URLSearchParams;e.team!==void 0&&t.set("team",e.team),e.peer!==void 0&&t.set("peer",e.peer),e.id!==void 0&&t.set("id",e.id),e.limit!==void 0&&t.set("limit",String(e.limit));const o=await ze(`/__dsh_a2a/remote-session-log?${t.toString()}`),s=await o.json().catch(()=>({}));return{ok:o.ok&&s.ok===!0,messages:s.messages,sessions:s.sessions,error:s.error??(o.ok?void 0:`HTTP ${o.status}`),via:s.via}}catch(t){return{ok:!1,error:t instanceof Error?t.message:String(t)}}},board:{root:st.root,activate:()=>st.activate(),deactivate:()=>st.deactivate(),available:()=>sn}});Co.appendChild(rn.root);Qt=e=>{rn.openNodeChat(e)};if(new URLSearchParams(window.location.search).get("mode")==="plan"){const e=window.setInterval(()=>{sn&&(rn.selectTab("board"),window.clearInterval(e))},300);window.setTimeout(()=>window.clearInterval(e),3e4)}async function an(){var e,t;try{const o=await ze("/__dsh_a2a/state",{cache:"no-store"});if(!o.ok)throw new Error(`/__dsh_a2a/state ${o.status}`);const s=await o.json();if(Date.now()-io>=15e3){io=Date.now();try{const m=await ze("/__dsh_a2a/nodes",{cache:"no-store"});if(!m.ok)throw new Error(`nodes ${m.status}`);const x=await m.json();fn=new Set((x.bindings??[]).filter(N=>N.mounted!==null&&N.effective!==null&&(N.effective.core===!1||N.effective.mutable===!1)).map(N=>N.session))}catch{fn.clear()}}const n={...s,sessions:(s.sessions??[]).map(m=>({...m,...fn.has(m.id)?{nodePromptMissing:!0}:{}}))};if(Ei(),sn=s.canvas!==void 0,rn.update(n),sn)try{const m=await Ai(),x=JSON.stringify(m??null);x!==ro&&(ro=x,(xn==="idle"||xn==="saved")&&!on.isBusy()&&st.adoptExternalLayout(m)),pn=!0}catch(m){if(!pn){wn(`canvas layout 获取失败:${String(m)}`);return}}else pn=!0;const i=(s.sessions??[]).map(m=>({...m,joined:m.joined===!0})),r=[...((e=s.canvas)==null?void 0:e.teams)??[],...Ds(((t=s.registry)==null?void 0:t.teams)??[],s.zone??"")],c=(s.peers??[]).filter(m=>m!==null&&typeof m=="object"&&typeof m.url=="string"),l=(s.inFlight??[]).filter(m=>m!==null&&typeof m=="object"&&typeof m.team=="string"&&typeof m.peer=="string"&&Number.isFinite(m.startedAt)),u=(s.remote??[]).filter(m=>m!==null&&typeof m=="object"&&typeof m.team=="string"&&typeof m.via=="string").map(m=>({team:m.team,name:m.name,via:m.via,workspace:m.workspace,...m.unreachable===!0?{unreachable:!0}:{},...typeof m.origin=="string"&&m.origin!==""?{origin:m.origin}:{},...Array.isArray(m.teams)&&m.teams.length>0?{teams:m.teams.filter(x=>typeof x=="string"&&x!=="")}:{}})),b=(s.peerOrg??[]).filter(m=>m!==null&&typeof m=="object").filter(m=>typeof m.url=="string"&&Array.isArray(m.org)).map(m=>({url:m.url,...m.unreachable===!0?{unreachable:!0}:{},org:m.org.filter(x=>x!==null&&typeof x=="object").filter(x=>typeof x.team=="string"&&x.team!=="").map(x=>({name:typeof x.name=="string"?x.name:"",team:x.team,members:Array.isArray(x.members)?x.members.filter(N=>typeof N=="string"):[]}))}));st.reconcile({sessions:i,teams:r,peerCount:c.length,peers:c,inFlight:l,remoteTeams:u,peerOrg:b})}catch(o){wn(`state 轮询失败:${String(o)}`)}}an();window.setInterval(()=>{document.hidden||an()},3e3);document.addEventListener("visibilitychange",()=>{document.hidden||an()});
|
|
1
|
+
var To=Object.defineProperty;var _o=(e,t,o)=>t in e?To(e,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):e[t]=o;var Et=(e,t,o)=>_o(e,typeof t!="symbol"?t+"":t,o);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))s(n);new MutationObserver(n=>{for(const i of n)if(i.type==="childList")for(const r of i.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&s(r)}).observe(document,{childList:!0,subtree:!0});function o(n){const i={};return n.integrity&&(i.integrity=n.integrity),n.referrerPolicy&&(i.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?i.credentials="include":n.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function s(n){if(n.ep)return;n.ep=!0;const i=o(n);fetch(n.href,i)}})();const ln=6e4;function Oo(e,t,o=Date.now){let s=-ln;return{fault(n){const i=o();i-s>=ln&&(t(`[nexus] ${n}`),s=i),e.show(n)},clear(){e.hide(),s=-ln}}}function lt(e){return e.name??e.team??e.label??""}function ao(e,t){var i,r;const o=(c,l)=>c!==void 0&&c.trim()!==""?{name:c,remote:l}:void 0,s=(e.sessions??[]).find(c=>c.team===t);if(s!==void 0)return o(lt(s),!1);const n=(e.remote??[]).find(c=>c.team===t);return n!==void 0?o(lt(n),!0):o((r=(((i=e.canvas)==null?void 0:i.teams)??[]).find(c=>c.team===t))==null?void 0:r.name,!1)}function Fo(e,t){const o=ao(e,t);return o===void 0?t:o.remote?`${o.name}(远端)`:o.name}function zt(e,t,o,s=""){const n=ao(t,o);if(e.textContent=`${s}${(n==null?void 0:n.name)??o}`,e.title=o,(n==null?void 0:n.remote)===!0){const i=e.appendChild(document.createElement("span"));i.className="wb-row-remote",i.textContent="远端",i.title="名字由对端自行发布"}}const Po=60*6e4;function $t(e){var t;return e.direction==="inbound"||e.direction===void 0&&((t=e.peer)==null?void 0:t.startsWith("local:"))===!0}function Tn(e){var t;return((t=e.peer)==null?void 0:t.startsWith("local:"))===!0?e.peer.slice(6):void 0}function Dt(e,t){return e.settleable!==void 0?e.settleable===!1:t-e.startedAt>=Po}function hn(e,t){const o=(e.tasks??[]).filter(r=>r.receiptExpected!==!1),s=o.filter(r=>!$t(r)&&Dt(r,t)),n=o.filter(r=>$t(r)&&Dt(r,t)),i=e.tasksDead??[];return{stale:s,owedOverdue:n,deadLetters:i.filter(r=>r.reason!=="fire-forget"),expired:i.filter(r=>r.reason==="fire-forget")}}function ke(e,t){const o=document.createElement(e);return t!==void 0&&(o.className=t),o}function _n(e,t){const o=Math.max(0,Math.round((t-e)/1e3));if(o<90)return`${o}s`;const s=Math.round(o/60);if(s<90)return`${s}m`;const n=Math.round(s/60);return n<48?`${n}h`:`${Math.round(n/24)}d`}function jt(e,t,o,s,n){const i=ke("div",`wb-led-tile${n!==void 0?` is-${n}`:""}`);i.title=s,i.appendChild(ke("span","wb-led-tile-v")).textContent=String(o),i.appendChild(ke("span","wb-led-tile-k")).textContent=t,e.appendChild(i)}const bn=[{key:"completed",label:"完成",tone:"completed"},{key:"sync_completed",label:"同步完成",tone:"completed"},{key:"rejected",label:"拒绝",tone:"rejected"},{key:"failed",label:"失败",tone:"failed"},{key:"expired",label:"过期",tone:"abandoned"},{key:"abandoned",label:"放弃",tone:"abandoned"},{key:"unknown",label:"结论不明",tone:"unclassified"},{key:"unclassified",label:"未分类",tone:"unclassified"}];function Do(e,t,o){const s=ke("div","wb-led-split"),n=ke("div","wb-led-split-bar");n.setAttribute("role","img");const i=ke("div","wb-led-split-legend"),r=new Set(bn.map(u=>u.key)),c=bn.map(u=>[u.tone,u.label,t[u.key]??0]);for(const[u,b]of Object.entries(t))r.has(u)||c.push(["other",u,b]);const l=[];for(const[u,b,m]of c){if(m<=0)continue;const x=ke("span",`wb-led-seg is-${u}`);x.style.width=`${Math.max(2,m/o*100)}%`,n.appendChild(x);const N=ke("span","wb-led-split-item");N.appendChild(ke("i",`wb-led-swatch is-${u}`)),N.appendChild(document.createTextNode(`${b} ${m}`)),i.appendChild(N),l.push(`${b} ${m}`)}n.setAttribute("aria-label",`归档结局:${l.join(",")}`),s.append(n,i),e.appendChild(s)}function Ro(e,t){var Me;e.replaceChildren();const{state:o,now:s}=t,n=o.tasks??[],i=o.tasksDead??[],r=o.archivedCount??0,c=hn(o,s),l=n.filter(D=>D.receiptExpected===!1),u=n.filter(D=>D.receiptExpected!==!1),b=u.filter(D=>$t(D)),m=u.filter(D=>!$t(D)),x=c.stale,N=m.filter(D=>!Dt(D,s)),Y=c.stale.length,re=ke("div","wb-led-tiles");jt(re,"待回执",u.length,`要回执、仍未结算的任务(含陈旧与本机欠对方的入站行)${l.length>0?`;另有免回执 ${l.length} 条不计`:""}`),jt(re,"陈旧",Y,"我方派发、要回执、已等待 ≥1h 仍未回执(可催办);本机欠对方的入站行在「待本机回执」组另计,免回执行不算陈旧",Y>0?"warn":void 0),jt(re,"死信",c.deadLetters.length,"超过 24h TTL 仍未结算(unconsumed);需清账(abandon)才能移出。免回执到期另列,不算死信",c.deadLetters.length>0?"danger":void 0),jt(re,"已归档",r,"已离开台账并留档的任务(结算、拒绝或放弃),用于审计"),e.appendChild(re),r>0&&o.archivedSplit!==void 0&&Do(e,o.archivedSplit,r);const V=(D,U)=>{const ce=ke("div",`wb-led-card is-${U.tone}`),Re=ke("div","wb-led-card-head");Re.appendChild(ke("span",`wb-led-dir${U.inbound?" is-in":""}`)).textContent=U.inbound?"↙":"↗";const Ee=ke("span","wb-led-brief");Ee.textContent=U.brief!==void 0&&U.brief!==""?U.brief:"(无摘要——派发未带 brief)",(U.brief===void 0||U.brief==="")&&Ee.classList.add("is-missing"),Re.appendChild(Ee),ce.appendChild(Re);const le=ke("div","wb-led-meta"),He=le.appendChild(ke("span","wb-led-team"));U.inbound?U.sender!==void 0?zt(He,o,U.sender,"来自 "):He.textContent="来自 对端":zt(He,o,U.team,"发往 "),U.inbound&&zt(le.appendChild(ke("span","wb-led-to")),o,U.team,"至 "),le.appendChild(ke("span")).textContent=U.atText,le.appendChild(ke("span","wb-led-task")).textContent=U.taskId;for(const fe of U.chips)le.appendChild(ke("span","wb-led-chip")).textContent=fe;if(ce.appendChild(le),ce.title=`${U.taskId}
|
|
2
|
+
${U.team}`,U.dead!==void 0){const fe=U.dead,q=fe.reason==="fire-forget",de=ke("button",`wb-btn wb-led-abandon${q?" is-quiet":""}`);de.type="button",de.textContent=q?"移出":"清账",de.title=q?"可选:把这条已过期的免回执记录移出台账(不是失败,不处理也无妨)":"从台账移出这条死信(abandon)",de.addEventListener("click",ee=>{ee.stopPropagation(),de.disabled=!0,t.abandon(fe.taskId,"workbench dead-letter cleanup").then(te=>{de.disabled=!1,de.textContent=te?"已清":"失败"})}),ce.appendChild(de)}if(t.canOpenTeam(U.team)){ce.classList.add("is-link"),ce.setAttribute("role","button"),ce.tabIndex=0,ce.setAttribute("aria-label",`${Ee.textContent},打开 ${U.team} 的对话`);const fe=()=>{t.openTeam(U.team)};ce.addEventListener("click",fe),ce.addEventListener("keydown",q=>{(q.key==="Enter"||q.key===" ")&&(q.preventDefault(),fe())})}D.appendChild(ce)},M=(D,U,ce,Re)=>{if(U===0)return null;const Ee=ke("div",`wb-led-group is-${ce}`);Ee.dataset.group=D;const le=ke("div","wb-led-group-head");return le.appendChild(ke("span")).textContent=`${D} · ${U}`,le.appendChild(ke("span","wb-led-group-hint")).textContent=Re,Ee.appendChild(le),e.appendChild(Ee),Ee},C=(D,U)=>{const ce=$t(D);return{brief:D.brief,team:D.team,sender:Tn(D),taskId:D.taskId,atText:`${_n(D.startedAt,s)} 前${ce?"收到":"派发"}`,inbound:ce,tone:U,chips:[...D.settleable===!0?["可结算"]:[],...D.receiptExpected===!1?["无回执债"]:[],...ce?["入站"]:[],...D.status!=="pending"?[D.status]:[]]}},S=(D,U,ce)=>({brief:D.brief,team:D.team,sender:Tn(D),taskId:D.taskId,atText:`${_n(D.deadAt,s)} 前${ce}`,inbound:$t(D),tone:U,dead:D,chips:D.reason!==void 0&&D.reason!==""&&D.reason!=="unspecified"&&D.reason!=="fire-forget"?[D.reason]:[]}),E=M("死信",c.deadLetters.length,"danger","需清账");if(E!==null)for(const D of[...c.deadLetters].sort((U,ce)=>ce.deadAt-U.deadAt))V(E,S(D,"danger","死信"));const G=M("陈旧",x.length,"warn","我方派发 ≥1 小时仍无回执,可催办");if(G!==null)for(const D of[...x].sort((U,ce)=>U.startedAt-ce.startedAt))V(G,C(D,"warn"));const y=c.owedOverdue.length,f=M("待本机回执",b.length,y>0?"warn":"quiet",y>0?`对方在等本机回执 · ${y} 条超过 1 小时`:"对方在等本机回执");if(f!==null)for(const D of[...b].sort((U,ce)=>U.startedAt-ce.startedAt))V(f,C(D,Dt(D,s)?"warn":"quiet"));const _=M("等待回执",N.length,"quiet","1 小时内");if(_!==null)for(const D of[...N].sort((U,ce)=>ce.startedAt-U.startedAt))V(_,C(D,"quiet"));const p=M("免回执",l.length,"muted","不等回执,24h 后自动归档");if(p!==null)for(const D of l)V(p,C(D,"muted"));const R=M("已过期(免回执)",c.expired.length,"muted","正常记账,不是失败");if(R!==null)for(const D of[...c.expired].sort((U,ce)=>ce.deadAt-U.deadAt))V(R,S(D,"muted","过期"));n.length+i.length===0&&(e.appendChild(ke("div","wb-led-empty")).textContent="台账为空——没有待回执的任务");const j=o.idempotency,K=(Me=o.reconcile)==null?void 0:Me.state;if(j!==void 0||K!==void 0){const D=ke("details","wb-led-forensics wb-forensics");D.appendChild(ke("summary")).textContent="取证";const U=ke("div","wb-led-forensics-body");j!==void 0&&(U.appendChild(ke("div")).textContent=`幂等 claims ${j.claimsFresh??0} · replays ${j.replays??0} · conflicts ${j.conflicts??0}`),K!==void 0&&(U.appendChild(ke("div")).textContent=`reconcile ${K}`),D.appendChild(U),e.appendChild(D)}const we=u.length+c.deadLetters.length;return{badge:we>0?String(we):"",tone:c.deadLetters.length>0?"danger":Y>0||y>0?"warn":void 0}}const Tt=4e3,Ho=32;function ye(e,t){const o=document.createElement(e);return t!==void 0&&(o.className=t),o}function Bt(e,t,o=""){const s=ye("button",`wb-icon-btn wb-chat-act ${o}`.trim());return s.type="button",s.setAttribute("aria-label",e),s.title=e,s.textContent=t,s}function dn(e,t){const o=Math.max(0,Math.round((t-e)/1e3));if(o<60)return"刚刚";const s=Math.round(o/60);if(s<60)return`${s} 分钟前`;const n=Math.round(s/60);return n<48?`${n} 小时前`:`${Math.round(n/24)} 天前`}function jo(e){return e>=1e6?`${(e/1e6).toFixed(1)} MB`:e>=1e3?`${Math.round(e/1e3)} KB`:`${e} B`}function mn(e){const t=e.kind==="session"||e.kind==="remote"?e.team:void 0;return t!==void 0&&t!==""?t:void 0}function On(e){return e.kind==="remote"?`remote:${e.team}`:`${e.kind}:${e.id}`}function Bo(e){let t=null,o=null,s=!1,n=!1;const i=new Map,r=new Map,c=new Map,l=new Map,u=new Set,b=new Map,m=new Map,x=ye("aside","wb-chat");x.setAttribute("aria-label","对话");const N=ye("div","wb-chat-head"),Y=Bt("返回会话列表","‹","wb-chat-back"),re=ye("span","wb-chat-dot"),V=ye("div","wb-chat-titles"),M=ye("span","wb-chat-title"),C=ye("span","wb-chat-sub");V.append(M,C);const S=Bt("刷新对话","↻","wb-chat-refresh"),E=Bt("会话详情","ⓘ","wb-chat-info-btn");E.setAttribute("aria-expanded","false");const G=Bt("关闭对话","✕","wb-chat-close");N.append(Y,re,V,S,E,G);const y=ye("div","wb-chat-info");y.hidden=!0;const f=ye("div","wb-chat-thread");f.setAttribute("role","log"),f.setAttribute("aria-live","polite"),f.tabIndex=0;const _=ye("div","wb-chat-notice"),p=ye("div","wb-chat-log"),R=ye("div","wb-chat-sent");f.append(_,p,R);const j=ye("div","wb-chat-foot");x.append(N,y,f,j),Y.addEventListener("click",()=>{(t==null?void 0:t.kind)==="peer"&&(t.picked=void 0,Ie())}),S.addEventListener("click",()=>{if(t===null)return;const d=K(t);d!==void 0&&i.delete(d),t.kind==="peer"&&t.picked===void 0&&t.url!==void 0&&c.delete(`peer:${t.url}`),de(!0)}),E.addEventListener("click",()=>{n=!n,y.hidden=!n,E.setAttribute("aria-expanded",String(n))}),G.addEventListener("click",()=>ft()),f.addEventListener("scroll",()=>{const d=t!==null?K(t):void 0;d!==void 0&&r.set(d,f.scrollTop)}),document.addEventListener("keydown",d=>{if(d.key!=="Escape"||!x.classList.contains("is-open"))return;const A=d.target;if(A instanceof HTMLElement){if(!x.contains(A)){const I=A instanceof HTMLTextAreaElement||A instanceof HTMLInputElement||A.isContentEditable,Q=A.closest(".wb-stage-board")!==null;if(I||Q)return}ft()}});function K(d){if(d.kind==="session"||d.kind==="log")return e.sessionLog!==void 0?`local:${d.id}`:void 0;if(d.kind==="remote")return e.remoteSessionLog!==void 0?`remote:${d.team}`:void 0;if(d.picked!==void 0&&d.url!==void 0&&e.remoteSessionLog!==void 0)return`peer:${d.url}:${d.picked}`}function we(d){var A,I,Q;return d.kind==="session"||d.kind==="log"?((A=e.sessionLog)==null?void 0:A.call(e,d.id))??Promise.resolve({ok:!1,error:"sessionLog unavailable"}):d.kind==="remote"?((I=e.remoteSessionLog)==null?void 0:I.call(e,{team:d.team}))??Promise.resolve({ok:!1,error:"remoteSessionLog unavailable"}):((Q=e.remoteSessionLog)==null?void 0:Q.call(e,{peer:d.url,id:d.picked}))??Promise.resolve({ok:!1,error:"remoteSessionLog unavailable"})}function Me(){const d=t;if(d===null)return;const A=d.kind==="log"||d.kind==="remote"||d.kind==="session"&&d.live===!1;re.className=`wb-chat-dot ${d.kind==="peer"?"is-peer":A?"is-cold":"is-live"}`,re.title=d.kind==="peer"?"对端主机":d.kind==="log"?"只读日志":d.kind==="remote"?"远端会话":d.live===!1?"冷会话":"在线",M.textContent=d.kind==="peer"&&d.picked!==void 0?`…${d.picked.slice(-12)}`:d.title,C.textContent=d.kind==="peer"&&d.picked!==void 0?d.title:d.sub,Y.hidden=!(d.kind==="peer"&&d.picked!==void 0)}function D(d,A){const I=ye("div","wb-kv");I.appendChild(ye("span","wb-kv-k")).textContent=d,I.appendChild(ye("span","wb-kv-v")).textContent=A,y.appendChild(I)}function U(){var A,I,Q;y.replaceChildren();const d=t;d!==null&&(d.kind==="session"?(D("会话",d.id),d.team!==void 0&&D("路由",d.team),D("来源","本机会话日志")):d.kind==="log"?(D("会话",d.id),D("来源","本机会话日志(不在网络目录)")):d.kind==="remote"?(D("路由",d.team),((A=d.row)==null?void 0:A.origin)!==void 0&&D("来源",d.row.origin),((I=d.row)==null?void 0:I.via)!==void 0&&D("经",d.row.via),((Q=d.row)==null?void 0:Q.workspace)!==void 0&&D("工作区",d.row.workspace)):(D("对端",d.url??d.sub),d.picked!==void 0&&D("会话",d.picked),D("来源","经本机代理读取对端 /a2a/log")))}function ce(d){return d.kind==="log"?"只读日志 —— 此会话当前不在网络目录(可能已归档或未入网)。":d.kind==="remote"?e.remoteSessionLog!==void 0?"远端会话 —— 经本机代理从对端 /a2a/log 读取最近对话。":"远端节点的对话记录在对端机器上;本页的代理读取面未启用。":d.kind==="peer"?d.url===void 0||e.remoteSessionLog===void 0?`对端主机节点(${d.sub})—— 会话记录存放在对端机器上,本页只读本机会话日志。`:d.picked===void 0?"对端主机 —— 选择一个会话阅读(经本机代理读取对端 /a2a/log)。":"":e.sessionLog===void 0?"本页未接入会话日志读取,只显示从这里发出的消息。":""}function Re(){return f.scrollHeight-f.scrollTop-f.clientHeight<=Ho}function Ee(d){const A=()=>{f.scrollTop=f.scrollHeight};A(),requestAnimationFrame(A)}function le(d,A){const I=ye("div",`wb-chat-empty${A==="error"?" is-error":""}`);return I.textContent=d,I}function He(d,A){const I=d==="user",Q=ye("div",`wb-msg ${I?"wb-msg-user":"wb-msg-assistant"}`),X=ye("span","wb-msg-who");X.textContent=I?"问":"答";const me=ye("div","wb-msg-text");return me.textContent=A,Q.append(X,me),Q}function fe(d){if(p.replaceChildren(),d===void 0){p.appendChild(le("读取中…"));return}if(d.ok!==!0||d.messages===void 0){p.appendChild(le(`无法读取(${d.error??"未知错误"})`,"error"));return}if(d.messages.length===0){p.appendChild(le("暂无对话记录"));return}for(const A of d.messages)p.appendChild(He(A.role,A.text))}function q(d,A){if(p.replaceChildren(),A===void 0){p.appendChild(le("读取中…"));return}if(A.ok!==!0||A.sessions===void 0){p.appendChild(le(`无法读取(${A.error??"未知错误"})`,"error"));return}if(A.sessions.length===0){p.appendChild(le("对端没有可读会话"));return}const I=ye("div","wb-chat-sessions"),Q=e.now();for(const X of A.sessions){const me=ye("button","wb-chat-session");me.type="button",me.appendChild(ye("span","wb-chat-session-id")).textContent=`…${X.id.slice(-12)}`;const ge=[X.mtimeMs!==void 0?dn(X.mtimeMs,Q):"",jo(X.sizeBytes)].filter(Boolean).join(" · ");me.appendChild(ye("span","wb-chat-session-meta")).textContent=ge,me.title=X.id,me.addEventListener("click",()=>{(t==null?void 0:t.kind)!=="peer"||t.url!==d||(t.picked=X.id,Ie())}),I.appendChild(me)}p.appendChild(I)}function de(d=!1){const A=t;if(A===null)return;if(_.textContent=ce(A),_.hidden=_.textContent==="",A.kind==="peer"&&A.picked===void 0){if(A.url===void 0||e.remoteSessionLog===void 0){p.replaceChildren();return}const X=A.url,me=`peer:${X}`;if(!d&&c.has(me)){q(X,c.get(me));return}c.set(me,void 0),q(X,void 0),e.remoteSessionLog({peer:X}).then(ge=>{c.set(me,ge),(t==null?void 0:t.kind)==="peer"&&t.url===X&&t.picked===void 0&&q(X,ge)},ge=>{const ve={ok:!1,error:ge instanceof Error?ge.message:String(ge)};c.set(me,ve),(t==null?void 0:t.kind)==="peer"&&t.url===X&&t.picked===void 0&&q(X,ve)});return}const I=K(A);if(I===void 0){p.replaceChildren(),Je(!0);return}const Q=()=>{const X=r.get(I);X===void 0||d?Ee():(f.scrollTop=X,requestAnimationFrame(()=>{t!==null&&K(t)===I&&(f.scrollTop=X)}))};if(!d&&i.has(I)&&i.get(I)!==void 0){fe(i.get(I)),Je(!0),Q();return}d&&r.delete(I),i.set(I,void 0),fe(void 0),Je(!0),we(A).then(X=>{var me;i.set(I,X),(X==null?void 0:X.ok)===!0&&X.messages!==void 0&&((me=e.onTranscript)==null||me.call(e,A,X.messages)),!(t===null||K(t)!==I)&&(fe(X),Je(),Q())},X=>{const me={ok:!1,error:X instanceof Error?X.message:String(X)};i.set(I,me),t!==null&&K(t)===I&&fe(me)})}function ee(d){return((o==null?void 0:o.tasks)??[]).filter(A=>A.team===d)}function te(d){return((o==null?void 0:o.tasksDead)??[]).filter(A=>A.team===d)}let Ce="";function Be(d){return d.reason==="fire-forget"?{text:"已过期(免回执)",tone:"muted",hint:"免回执消息到 24h TTL 归档,属正常记账"}:{text:"死信",tone:"danger",hint:d.reason!==void 0&&d.reason!=="unspecified"?`${d.reason}:超过 24h TTL 仍未结算,需在台账清账`:"超过 24h TTL 仍未结算,需在台账清账"}}function Ye(d,A){const I=d.direction==="inbound";if(d.receiptExpected===!1)return{text:I?"来信 · 无需回执":"已送达 · 无回执",tone:"muted",hint:"免回执消息:不等回执,24h 后自动归档"};const Q=Dt(d,A),X=I?Q?"待本机回执 · 超 1 小时":"待本机回执":Q?"陈旧":"待回执",me=d.status!=="pending"?` · ${d.status}`:"";return{text:`${X}${me}`,tone:Q?"warn":"wait",hint:`${I?"对方等待本机回执;":""}${I?"收到":"派发"}于 ${dn(d.startedAt,A)}`}}function qe(d,A){const I=`结算于 ${dn(d.resolvedAt,A)}`;if(d.receiptExpected===!1&&d.endedBy==="abandoned")return d.late===!0?{text:"已移出(免回执) · 回执迟到",tone:"warn",hint:`${I};免回执消息本机移出后对方回执才到,结局不改写`}:{text:"已移出(免回执)",tone:"muted",hint:`${I};免回执消息,本机移出台账,不是失败`};if(d.endedBy==="abandoned"||d.endedBy==="cancelled"){const ge=d.endedBy==="cancelled"?"撤回":"放弃";return d.late===!0?{text:`已${ge} · 回执迟到`,tone:"warn",hint:`${I};本机${ge}之后对方回执才到,结局不改写`}:{text:`已${ge}`,tone:"muted",hint:`${I};本机${ge},未等到回执`}}if(d.endedBy==="echo")return{text:"已结算 · 内容回显",tone:"ok",hint:`${I};对方回了内容但未带正式回执,按内容回显结算`};if(d.endedBy===void 0&&d.outcome==="abandoned")return{text:"已放弃(本机或对方)",tone:"muted",hint:`${I};本机放弃或撤回,或对方回执报告放弃`};const Q=d.summary!==void 0&&d.summary!==""?` · ${d.summary}`:"";if(d.outcome==="abandoned")return{text:"已回执 · 对方放弃",tone:"warn",hint:`${I};对方回执报告放弃${Q}`};const X=bn.find(ge=>ge.key===d.outcome),me=(X==null?void 0:X.tone)==="completed"?"ok":(X==null?void 0:X.tone)==="failed"?"danger":(X==null?void 0:X.tone)==="rejected"?"warn":"muted";return d.outcome==="unclassified"?{text:"已回执",tone:"ok",hint:`${I};回执未带结论${Q}`}:{text:`已回执 · ${(X==null?void 0:X.label)??d.outcome}`,tone:me,hint:`${I}${Q}`}}function ut(d,A,I){const Q=te(A).find(ge=>ge.taskId===d);if(Q!==void 0)return Be(Q);const X=ee(A).find(ge=>ge.taskId===d);if(X!==void 0)return Ye(X,I);const me=((o==null?void 0:o.archived)??[]).find(ge=>ge.taskId===d&&ge.team===A);return me!==void 0?qe(me,I):u.has(d)?{text:"已离开台账",tone:"muted",hint:"已结算、放弃或撤回之一;主机未给出这条的结局(旧主机,或已超出最近 64 条归档)"}:{text:"已派发",tone:"muted",hint:"异步送达;回执到达后进台账"}}function kt(d){const A=e.now(),I=l.get(d)??[],Q=new Set(I.map(ne=>ne.taskId).filter(ne=>ne!==void 0)),X=ne=>ne!==void 0&&ne!==""?ne:"(无摘要)",me=ee(d).filter(ne=>!Q.has(ne.taskId)).map(ne=>({at:ne.startedAt,side:ne.direction==="inbound"?"theirs":"mine",text:X(ne.brief),status:Ye(ne,A),taskId:ne.taskId})),ge=te(d).filter(ne=>!Q.has(ne.taskId)).map(ne=>{var Te;const We=ne.direction??b.get(ne.taskId)??(((Te=ne.peer)==null?void 0:Te.startsWith("local:"))===!0?"inbound":void 0);return{at:ne.startedAt,side:We==="inbound"?"theirs":We==="outbound"?"mine":"system",text:X(ne.brief),status:Be(ne),taskId:ne.taskId}}),ve=I.map(ne=>({at:ne.at,side:"mine",text:ne.text,status:ne.state==="sending"?{text:"发送中…",tone:"muted"}:ne.state==="failed"?{text:`失败:${ne.error??"未知原因"}`,tone:"danger"}:ne.taskId!==void 0?ut(ne.taskId,d,A):{text:"已派发",tone:"muted"},taskId:ne.taskId}));return[...me,...ge,...ve].sort((ne,We)=>ne.at-We.at)}function Je(d=!1){const A=t,I=A!==null?mn(A):void 0,Q=I!==void 0?kt(I):[],X=JSON.stringify([I??"",...Q.map(ve=>[ve.taskId??"",ve.side,ve.text,ve.status.text])]);if(!d&&X===Ce)return;Ce=X;const me=Re();if(R.replaceChildren(),Q.length===0)return;const ge=ye("div","wb-chat-divider");ge.textContent="台账往来 · 异步送达,回执进台账",R.appendChild(ge);for(const ve of Q){const ne=ve.side==="mine"?"wb-msg wb-msg-user wb-msg-out":ve.side==="theirs"?"wb-msg wb-msg-assistant wb-msg-in":"wb-msg wb-msg-ledger",We=ye("div",ne);We.appendChild(ye("span","wb-msg-who")).textContent=ve.side==="mine"?"我":ve.side==="theirs"?"对方":"台账记录",We.appendChild(ye("div","wb-msg-text")).textContent=ve.text;const Te=ye("div","wb-msg-meta");ve.taskId!==void 0&&(Te.appendChild(ye("span","wb-msg-task")).textContent=ve.taskId);const Xe=ye("span",`wb-msg-status is-${ve.status.tone}`);Xe.textContent=ve.status.text,ve.status.hint!==void 0&&(Xe.title=ve.status.hint),Te.appendChild(Xe),We.appendChild(Te),R.appendChild(We)}me&&Ee()}function Qe(d){const A=d.text.value.length;d.note.classList.remove("is-error"),d.note.textContent=A>Tt*.9?`${A}/${Tt}`:"Enter 发送 · Shift+Enter 换行",A>Tt&&d.note.classList.add("is-error"),d.submit.disabled=d.text.value.trim()===""||A>Tt}function vt(d){d.style.height="auto",d.style.height=`${Math.min(d.scrollHeight,160)}px`}function St(d){const A=ye("form","wb-dispatch-form wb-chat-composer"),I=document.createElement("textarea");I.className="wb-dispatch-text",I.rows=1,I.placeholder="发一句话任务给这个节点…",I.setAttribute("aria-label","发送消息");const Q=ye("button","wb-dispatch-submit");Q.type="submit",Q.textContent="发送",Q.setAttribute("aria-label","发送");const X=ye("div","wb-dispatch-note");X.setAttribute("aria-live","polite");const me=ye("div","wb-chat-composer-row");me.append(I,Q),A.append(me,X);const ge={team:d,form:A,text:I,note:X,submit:Q};return I.addEventListener("input",()=>{vt(I),Qe(ge)}),I.addEventListener("keydown",ve=>{ve.key!=="Enter"||ve.shiftKey||ve.ctrlKey||ve.altKey||ve.metaKey||ve.isComposing||(ve.preventDefault(),A.requestSubmit())}),A.addEventListener("submit",ve=>{ve.preventDefault();const ne=I.value.trim();if(ne===""||ne.length>Tt||e.dispatchQuick===void 0)return;const We={text:ne,at:e.now(),state:"sending"},Te=l.get(d)??[];Te.push(We),l.set(d,Te),I.value="",vt(I),Qe(ge),I.focus({preventScroll:!0}),Je(),Ee(),e.dispatchQuick(d,ne).then(Xe=>Xe,Xe=>({ok:!1,error:Xe instanceof Error?Xe.message:String(Xe)})).then(Xe=>{Xe.ok===!0?(We.state="sent",We.taskId=Xe.task_id,X.classList.remove("is-error"),X.textContent=`已派发${Xe.task_id!==void 0?` · ${Xe.task_id}`:""} · 回执将入台账`):(We.state="failed",We.error=Xe.error??"未知原因",I.value===""&&(I.value=ne,vt(I)),X.classList.add("is-error"),X.textContent=`失败:${We.error}`,Q.disabled=I.value.trim()===""),t!==null&&mn(t)===d&&Je()})}),Qe(ge),ge}function Se(){const d=t;if(j.replaceChildren(),d===null)return;const A=mn(d);if(A!==void 0&&e.dispatchQuick!==void 0){let Q=m.get(A);Q===void 0&&(Q=St(A),m.set(A,Q)),j.appendChild(Q.form),s&&(s=!1,Q.text.focus({preventScroll:!0}));return}s=!1;const I=ye("div","wb-chat-readonly");I.textContent=d.kind==="log"?"只读日志:此会话不在网络目录,不能从这里派发。":d.kind==="peer"?"对端主机:选择会话阅读;要派发请打开它的远端会话节点。":"此节点没有可派发的路由。",j.appendChild(I)}function Ie(){Me(),U(),de(),Se()}function tt(d){const A=t!==null&&On(t)===On(d);t=d,A||(s=!0),Ie(),x.classList.add("is-open")}function ft(){t=null,x.classList.remove("is-open")}function At(d){o=d;for(const I of(d==null?void 0:d.tasks)??[])u.add(I.taskId),b.set(I.taskId,I.direction==="inbound"?"inbound":"outbound");const A=t;if(A!==null){if(A.kind==="session"&&d!==null){const I=(d.sessions??[]).find(Q=>Q.id===A.id);I!==void 0&&(A.title=lt(I),A.live=I.live)}Me(),Je()}}return{root:x,open:tt,close:ft,isOpen:()=>t!==null,update:At}}function Yo(e,t,o){const s=document.createElement("section"),n=document.createElement("h4");n.textContent="会话席位名(仅人工设定)",s.appendChild(n);const i=document.createElement("p");i.className="wb-hint",i.textContent="稳定展示名,不改变会话标题、路由句柄或准入。留空并保存可清除。",s.appendChild(i);const r=document.createElement("select");r.setAttribute("aria-label","选择命名的本机会话");for(const N of new Set([...e.map(Y=>Y.id),...Object.keys(t)])){const Y=e.find(V=>V.id===N),re=document.createElement("option");re.value=N,re.textContent=(t[N]??(Y==null?void 0:Y.name)??(Y==null?void 0:Y.label)??N)+" · "+N,r.appendChild(re)}const c=document.createElement("input");c.type="text",c.maxLength=64,c.setAttribute("aria-label","人工席位名"),c.placeholder="例如:开发席";const l=document.createElement("button");l.type="submit",l.textContent="保存席位名",l.className="wb-member-submit";const u=document.createElement("form");u.className="wb-member-add",u.append(r,c,l);const b=document.createElement("p");b.className="wb-hint",b.setAttribute("role","status"),b.setAttribute("aria-live","polite");let m=!1;const x=()=>{c.value=t[r.value]??"",l.disabled=m||r.value===""};return r.addEventListener("change",x),x(),u.addEventListener("submit",async N=>{if(N.preventDefault(),m||r.value==="")return;const Y=r.value,re=c.value.trim(),V={...t};re===""?delete V[Y]:V[Y]=re,m=!0,l.disabled=!0,r.disabled=!0,c.disabled=!0;try{const M=await o(V);M.ok?(delete t[Y],re!==""&&(t[Y]=re),b.textContent="席位名已保存;目录将随状态刷新。"):b.textContent=M.error??"保存失败"}catch(M){b.textContent="保存失败:"+String(M)}finally{m=!1,r.disabled=!1,c.disabled=!1,x()}}),s.append(u,b),s}function Wo(e,t){const o=document.createElement("form");o.className="wb-cli-home";const s=document.createElement("button");s.type="button",s.textContent="指定 home",s.className="wb-member-submit";const n=document.createElement("select");n.className="wb-member-pick",n.setAttribute("aria-label","选择 CLI home 主机"),n.hidden=!0;const i=document.createElement("button");i.type="submit",i.textContent="确认 home",i.className="wb-member-submit",i.hidden=!0,i.disabled=!0;const r=document.createElement("div");r.className="wb-hint",r.setAttribute("role","status"),r.setAttribute("aria-live","polite"),r.textContent="home 未确定;点击指定 home 现读已链接主机名片。";let c=!1;return s.addEventListener("click",async()=>{var l;if(!c){c=!0,s.disabled=!0,i.disabled=!0,r.textContent="正在现读主机名片…";try{const u=await e();if(!u.ok)throw Error(u.error??"候选读取失败");if(u.held){s.hidden=!0,n.hidden=!0,i.hidden=!0,n.replaceChildren(),r.textContent="本机持有,无需指定";return}n.replaceChildren(new Option("请选择 home 主机…","",!0,!0));for(const m of u.homes??[])n.appendChild(new Option(m,m));n.hidden=!1,i.hidden=!1,s.textContent="刷新候选";const b=((l=u.homes)==null?void 0:l.length)??0;r.textContent=(u.unreadable?"有 "+u.unreadable+" 台对端名片读不到;":"")+(b>1?"多台已链接主机列出该句柄,请显式选择。":b===1?"找到 1 台已链接主机;仍需你显式确认。":"当前没有已链接且列出该句柄的可选主机。")}catch(u){r.textContent="读取失败:"+String(u),n.hidden=!0,i.hidden=!0}finally{c=!1,s.disabled=!1}}}),n.addEventListener("change",()=>{i.disabled=c||n.value===""}),o.addEventListener("submit",async l=>{if(l.preventDefault(),!(c||n.value==="")){c=!0,s.disabled=!0,n.disabled=!0,i.disabled=!0;try{r.textContent=await t(n.value)?"home 已指定:"+n.value:"指定失败:主机可能已离线或不再列出该句柄,请刷新后重选。"}catch(u){r.textContent="指定失败:"+String(u)}finally{c=!1,s.disabled=!1,n.disabled=!1,i.disabled=n.value===""}}}),o.append(s,n,i,r),o}const co="dsh-a2a.rail.tab";function Xo(){try{return window.localStorage.getItem(co)}catch{return null}}function Ko(e){try{window.localStorage.setItem(co,e)}catch{}}function Uo(e,t={}){var V;const o=document.createElement("aside");o.className="wb-rail";const s=document.createElement("div");s.className="wb-tabs",s.setAttribute("role","tablist"),s.setAttribute("aria-label","工作台侧栏");const n=document.createElement("div");n.className="wb-tabpanels",o.append(s,n);const i=new Map,r=new Map,c=new Map,l=new Set;for(const M of e){const C=document.createElement("button");C.type="button",C.className="wb-tab",C.id=`wb-tab-${M.key}`,C.dataset.sec=M.key,C.setAttribute("role","tab"),C.setAttribute("aria-controls",`wb-panel-${M.key}`);const S=document.createElement("span");S.className="wb-tab-label",S.textContent=M.label;const E=document.createElement("span");E.className="wb-tab-badge",C.append(S,E),C.addEventListener("click",()=>N(M.key)),s.appendChild(C);const G=document.createElement("section");G.className="wb-tabpanel",G.id=`wb-panel-${M.key}`,G.dataset.sec=M.key,G.setAttribute("role","tabpanel"),G.setAttribute("aria-labelledby",C.id),G.tabIndex=-1,n.appendChild(G),i.set(M.key,C),r.set(M.key,G),c.set(M.key,E)}const u=()=>e.map(M=>M.key).filter(M=>!l.has(M)),b=Xo();let m=((V=e.find(M=>M.key===b))==null?void 0:V.key)??e[0].key;s.addEventListener("keydown",M=>{const C=u(),S=C.indexOf(m);let E;M.key==="ArrowRight"?E=C[(S+1)%C.length]:M.key==="ArrowLeft"?E=C[(S-1+C.length)%C.length]:M.key==="Home"?E=C[0]:M.key==="End"&&(E=C[C.length-1]),E!==void 0&&(M.preventDefault(),N(E,{focus:!0}))});function x(){for(const M of e){const C=M.key===m,S=i.get(M.key);S.setAttribute("aria-selected",String(C)),S.tabIndex=C?0:-1,S.classList.toggle("is-active",C),S.hidden=l.has(M.key),r.get(M.key).hidden=!C}}function N(M,C={}){var E;if(l.has(M))return;const S=M!==m;m=M,Ko(M),x(),C.focus===!0&&i.get(M).focus(),S&&((E=t.onChange)==null||E.call(t,M))}function Y(M,C,S){const E=c.get(M);E.textContent=C,E.className=`wb-tab-badge${S!==void 0?` is-${S}`:""}`}function re(M,C){C?l.add(M):l.delete(M),l.has(m)&&(m=u()[0]??e[0].key),x()}return x(),{root:o,panel:M=>r.get(M),select:N,selected:()=>m,setBadge:Y,setHidden:re}}const gn="application/x-dsh-session";function qo(e,t){e.draggable=!0,e.classList.add("is-draggable"),e.title=`${e.title===""?t:e.title} · 可拖入画布队`,e.addEventListener("dragstart",o=>{o.dataTransfer!==null&&(o.dataTransfer.setData(gn,t),o.dataTransfer.effectAllowed="copy")})}function zo(e,t){const o=n=>n.dataTransfer!==null&&[...n.dataTransfer.types].includes(gn),s=n=>{for(const[i,r]of t.frames())r.classList.toggle("drop-target",i===n)};e.addEventListener("dragover",n=>{if(!o(n))return;const i=t.frameAt(n.clientX,n.clientY);s(i),i!==void 0&&(n.preventDefault(),n.dataTransfer.dropEffect="copy")},t.signal),e.addEventListener("dragleave",n=>{o(n)&&(n.relatedTarget===null||!e.contains(n.relatedTarget))&&s(void 0)},t.signal),e.ownerDocument.addEventListener("dragend",()=>s(void 0),t.signal),e.addEventListener("drop",n=>{if(!o(n))return;s(void 0);const i=t.frameAt(n.clientX,n.clientY),r=n.dataTransfer.getData(gn);i===void 0||r===""||(n.preventDefault(),t.drop(i,r))},t.signal)}const Jo=[{key:"all",label:"全部",hint:"不过滤:目录全部条目"},{key:"local",label:"本机",hint:"本机会话节点(现场 + 冷启动)"},{key:"canvas",label:"队",hint:"画布队(人类手工分配的组队)"},{key:"remote",label:"远端",hint:"远端会话队(来自对端卡片)"},{key:"logs",label:"日志",hint:"本机日志:不在网络目录里的会话档案"}];function ot(e,t){const o=document.createElement(e);return t!==void 0&&(o.className=t),o}function Yt(...e){const t=[];for(const o of e)o!==void 0&&(typeof o=="string"?t.push(o):t.push(...o));return t.join(" ").toLowerCase()}function Vo(e,t){const o=Math.max(0,Math.round((t-e)/1e3));if(o<60)return"刚刚";const s=Math.round(o/60);if(s<60)return`${s} 分钟前`;const n=Math.round(s/60);return n<48?`${n} 小时前`:`${Math.round(n/24)} 天前`}function Fn(e){return e>=1e6?`${(e/1e6).toFixed(1)} MB`:e>=1e3?`${Math.round(e/1e3)} KB`:`${e} B`}function Go(e,t){const o=new Date(t);o.setHours(0,0,0,0);const s=o.getTime();return e>=s?"今天":e>=s-864e5?"昨天":"更早"}function Qo(e,t){var S,E,G;e.replaceChildren();const{state:o,search:s,filter:n}=t,i=s!==""||n!=="all",r=(y,f)=>(n==="all"||n===y)&&(s===""||f.includes(s)),c=(y,f,_)=>{const p=ot("div","wb-dir-group"),R=ot("div","wb-dir-head");return R.appendChild(ot("span","wb-dir-head-label")).textContent=`${y} · ${f}`,_!==void 0&&(R.appendChild(ot("span","wb-dir-head-note")).textContent=_),p.appendChild(R),e.appendChild(p),p},l=(y,f,_,p,R,j,K)=>{const we=ot("button","wb-item");we.type="button",we.appendChild(ot("span",`wb-dot ${f}`)).textContent=_;const Me=ot("span","wb-item-text");return Me.appendChild(ot("span","wb-item-label")).textContent=p,R!==""&&(Me.appendChild(ot("span","wb-item-sub")).textContent=R),we.appendChild(Me),K!==void 0&&(we.title=K),we.addEventListener("click",j),y.appendChild(we),we},u=(y,f)=>{if(f===void 0||f.length===0)return;const _=ot("span","wb-item-badge"),p=f.map(R=>R.slice(R.lastIndexOf("/")+1));_.textContent=`▤ ${p.slice(0,2).join(" ")}${p.length>2?` +${p.length-2}`:""}`,_.title=`画布队:${f.join(" · ")}`,y.appendChild(_)},b=(o.sessions??[]).filter(y=>r("local",Yt(lt(y),y.team,y.label,y.id,y.canvasTeams))),m=b.filter(y=>y.live===!0),x=b.filter(y=>y.live!==!0);if(b.length>0){const y=c("本机会话",b.length,x.length>0?`${m.length} 在线 · ${x.length} 冷`:void 0);for(const f of[...m,...x]){const _=f.live===!0,p=f.nodePromptMissing===!0,R=l(y,_?"wb-dot-live":"wb-dot-cold",_?"●":"○",lt(f),_?f.team:`冷 · ${f.team}`,()=>t.openChat({kind:"session",id:f.id,title:lt(f),sub:f.team,team:f.team,live:f.live}),f.id);if(p){R.classList.add("is-node-prompt-missing");const j=ot("span","wb-node-warning");j.textContent="本会话的组装不含节点段",(S=R.querySelector(".wb-item-text"))==null||S.appendChild(j)}u(R,f.canvasTeams),qo(R,f.id)}}const N=(((E=o.canvas)==null?void 0:E.teams)??[]).filter(y=>r("canvas",Yt(y.name,y.team,y.members.map(f=>f.team??f.id))));if(N.length>0){const y=c("画布队",N.length);for(const f of N){const _=f.members.filter(p=>p.remote===!0).length;l(y,"wb-dot-canvas","▤",f.name,`${f.members.length} 成员${_>0?` · ${_} 远端`:""}`,()=>t.selectCanvas(f),f.team)}}const Y=(o.remote??[]).filter(y=>r("remote",Yt(lt(y),y.team,y.origin,y.workspace,y.canvasTeams)));if(Y.length>0){const y=c("远端节点",Y.length);for(const f of Y){const _=l(y,"wb-dot-remote","◇",lt(f),f.origin!==void 0&&f.origin!==""?f.origin:f.team,()=>t.openChat({kind:"remote",team:f.team,title:lt(f),sub:f.team,row:f}),f.team);if(f.unreachable===!0){_.classList.add("is-unreachable");const p=ot("span","wb-unreachable-note");p.textContent="对端未应答(显示的是最后已知状态)",(G=_.querySelector(".wb-item-text"))==null||G.appendChild(p)}u(_,f.canvasTeams)}}const re=new Set((o.sessions??[]).map(y=>y.id)),V=t.logs.filter(y=>!re.has(y.id)&&r("logs",Yt(y.id,t.titles.get(y.id))));if(V.length>0){const y=t.logTotal!==void 0&&t.logTotal>t.logs.length,f=c("本机日志",V.length,y?`显示 ${t.logs.length} / 共 ${t.logTotal}`:void 0);let _="";for(const p of[...V].sort((R,j)=>j.mtimeMs-R.mtimeMs)){const R=Go(p.mtimeMs,t.now);R!==_&&(_=R,f.appendChild(ot("div","wb-dir-day")).textContent=R);const j=t.titles.get(p.id),K=l(f,"wb-dot-log","❐",j??`会话 …${p.id.slice(-12)}`,`${Vo(p.mtimeMs,t.now)} · ${Fn(p.sizeBytes)}`,()=>t.openChat({kind:"log",id:p.id,title:j??`…${p.id.slice(-12)}`,sub:"本机日志"}),`${p.id}
|
|
3
|
+
${new Date(p.mtimeMs).toLocaleString()} · ${Fn(p.sizeBytes)}`);j===void 0&&K.classList.add("is-untitled")}}b.length+N.length+Y.length+V.length===0&&(e.appendChild(ot("div","wb-dir-empty")).textContent=i?"无匹配条目":"目录为空");const M=o.sessions??[];return`${M.filter(y=>y.live===!0).length}/${M.length}`}const lo="dsh-a2a.logtitles",Zo=300,Pn=60;function es(){try{const e=window.localStorage.getItem(lo),t=e===null?null:JSON.parse(e);if(t!==null&&typeof t=="object")return new Map(Object.entries(t).filter(o=>typeof o[1]=="string"))}catch{}return new Map}function ts(e,t,o){const s=o.find(r=>r.role==="user"&&r.text.trim()!=="")??o.find(r=>r.text.trim()!=="");if(s===void 0)return!1;const n=s.text.trim().split(`
|
|
4
|
+
`)[0].trim(),i=n.length>Pn?`${n.slice(0,Pn-1)}…`:n;if(e.get(t)===i)return!1;for(e.delete(t),e.set(t,i);e.size>Zo;)e.delete(e.keys().next().value);try{window.localStorage.setItem(lo,JSON.stringify(Object.fromEntries(e)))}catch{}return!0}function ht(e){return e.name??e.team??e.label??""}function _t(e,t){const o=Math.max(0,Math.round((t-e)/1e3));if(o<90)return`${o}s`;const s=Math.round(o/60);if(s<90)return`${s}m`;const n=Math.round(s/60);return n<48?`${n}h`:`${Math.round(n/24)}d`}function T(e,t){const o=document.createElement(e);return t!==void 0&&(o.className=t),o}function Dn(e,t,o){const s=T("div","wb-kv");s.appendChild(T("span","wb-kv-k")).textContent=t,s.appendChild(T("span","wb-kv-v")).textContent=o,e.appendChild(s)}function ns(e){try{return new URL(e).host}catch{return e}}const os=[{key:"directory",label:"目录"},{key:"hosts",label:"主机"},{key:"ledger",label:"台账"},{key:"activity",label:"活动"},{key:"plan",label:"规划"}];function ss(e){const t=e.board;let o="data",s,n=null,i="",r="all",c=null;const l=new Map;let u=null,b=[],m;const x=es();let N=!1;const Y=T("div","wb");Y.setAttribute("data-testid","wb-root");const re=T("header","wb-header"),V=T("button","wb-icon-btn wb-menu");V.type="button",V.dataset.testid="wb-menu",V.setAttribute("aria-label","打开目录抽屉"),V.textContent="☰",V.addEventListener("click",()=>Y.classList.toggle("is-rail-open")),re.appendChild(V);const M=T("div","wb-title");M.appendChild(T("span","wb-title-main")).textContent="A2A 工作台";const C=T("span","wb-badge");M.appendChild(C),re.appendChild(M);const S=T("button","wb-icon-btn wb-owner-btn");S.type="button",S.dataset.testid="wb-owner-btn",S.setAttribute("aria-label","主人设置"),S.title="主人设置:席位名 / 入网白名单 / 可见性 / 发布",S.textContent="⚙",S.addEventListener("click",()=>{A=!A,Q()}),re.appendChild(S);const E=T("div","wb-header-stats");re.appendChild(E);const G=T("button","wb-icon-btn wb-rail-toggle");G.type="button",G.dataset.testid="wb-rail-toggle",G.setAttribute("aria-label","折叠/展开侧栏"),G.textContent="◧",G.addEventListener("click",()=>{Y.classList.toggle("is-rail-collapsed"),o==="canvas"&&t!==void 0&&t.activate()}),re.appendChild(G);const y=T("div","wb-body"),f=Uo(os),_=f.root,p=T("div","wb-directory"),R=T("div","wb-dir-tools"),j=document.createElement("input");j.className="wb-search",j.type="search",j.placeholder="搜索:名称 / 队 / 会话 / 节点",j.setAttribute("aria-label","统一搜索目录"),j.addEventListener("input",()=>{i=j.value.trim().toLowerCase(),qe()}),R.appendChild(j);const K=T("div","wb-filters");for(const k of Jo){const w=T("button","wb-filter");w.type="button",w.textContent=k.label,w.dataset.filter=k.key,w.title=k.hint,w.addEventListener("click",()=>{r=k.key,qe()}),K.appendChild(w)}R.appendChild(K),f.panel("directory").appendChild(R),f.panel("directory").appendChild(p);const we=T("section","wb-pane"),Me=T("section","wb-pane"),D=T("section","wb-pane"),U=T("section","wb-pane"),ce=[["ledger",we],["activity",Me],["plan",D],["hosts",U]],Re=T("main","wb-stage"),Ee=T("section","wb-stage-board");t!==void 0&&(Ee.appendChild(t.root),Re.appendChild(Ee));const le=T("div","wb-data"),He=T("aside","wb-inspector"),fe=T("div","wb-inspector-head");fe.appendChild(T("span","wb-inspector-title")).textContent="详情";const q=T("button","wb-icon-btn");q.type="button",q.setAttribute("aria-label","关闭详情"),q.textContent="✕",q.addEventListener("click",()=>Ye(void 0)),fe.appendChild(q),He.appendChild(fe);const de=T("div","wb-inspector-body");He.appendChild(de);const ee=Bo({now:e.now,sessionLog:e.sessionLog,remoteSessionLog:e.remoteSessionLog,dispatchQuick:e.dispatchQuick,onTranscript:(k,w)=>{k.kind!=="log"&&k.kind!=="session"||ts(x,k.id,w)&&qe()}});Re.appendChild(le),y.appendChild(_),y.appendChild(Re),y.appendChild(He),y.appendChild(ee.root),Y.appendChild(re),Y.appendChild(y);function te(k){for(const[w,H]of ce){const $=k==="canvas"?f.panel(w):le;f.setHidden(w,k!=="canvas"),H.parentElement!==$&&$.appendChild(H)}}function Ce(){const w=t!==void 0&&t.available()?"canvas":"data";Y.dataset.mode=w,Ee.classList.toggle("is-hidden",w!=="canvas"),le.classList.toggle("is-hidden",w==="canvas"),te(w),w!==o&&(t!==void 0&&(w==="canvas"?t.activate():t.deactivate()),o=w)}function Be(k){for(;k.firstChild!==null;)k.removeChild(k.firstChild);return k}function Ye(k){s=k,((k==null?void 0:k.kind)!=="canvas"||(c==null?void 0:c.name)!==k.row.name)&&(c=null),(k==null?void 0:k.kind)!=="canvas"&&(u=null),me(),Y.classList.remove("is-rail-open")}function qe(){for(let w=0;w<K.children.length;w++){const H=K.children[w];H.classList.toggle("is-active",H.dataset.filter===r)}if(n===null){p.replaceChildren(T("div","wb-muted")),p.firstElementChild.textContent="载入中…",f.setBadge("directory","");return}const k=Qo(p,{state:n,logs:b,logTotal:m,titles:x,search:i,filter:r,now:e.now(),openChat:ne,selectCanvas:w=>Ye({kind:"canvas",row:w})});f.setBadge("directory",k)}function ut(){const k=Be(U);if(n===null){f.setBadge("hosts","");return}const w=e.now(),H=[...n.peers??[]].sort(($,L)=>{const O=se=>se.link==="linked"?0:1;return O($)-O(L)||(L.score??0)-($.score??0)});if(f.setBadge("hosts",H.length>0?`${H.filter($=>$.link==="linked").length}/${H.length}`:""),H.length===0){k.appendChild(T("div","wb-nodelist-empty")).textContent="暂无 tracked peer——配 peers 种子或等 referral 到达";return}for(const $ of H){const L=ns($.url),O=T("div","wb-host-row"),se=T("span","wb-host-lamp"),ae=$.lastContactAt,Z=ae===void 0?void 0:w-ae,xe=$.lastContactOk;Z===void 0?se.classList.add("is-unknown"):xe===!1&&Z<=5*6e4?se.classList.add("is-fail"):Z<=6e4?se.classList.add("is-live"):Z<=5*6e4?se.classList.add("is-warm"):se.classList.add("is-cold"),se.title=ae===void 0?"尚无接触记录":`最近接触 ${_t(ae,w)}${xe===!1?"(失败)":xe===!0?"(成功)":""}`,O.appendChild(se),O.appendChild(T("span","wb-host-name")).textContent=$.name!==void 0&&$.name!==""?$.name:L;const _e=T("span",`wb-host-badge ${$.link==="linked"?"is-linked":"is-stranger"}`);_e.textContent=`${$.link==="linked"?"linked":"stranger"} ${$.verified===!0?"✓":"✗"}`,_e.title=$.link==="linked"?`已建立运营者链接(互种或 canvas 引用);${$.verified===!0?"验签有效":"尚未持有验签通过的卡片"}`:"无运营者关系(验签 ≠ 关系)",O.appendChild(_e),$.version!==void 0&&$.version!==""&&(O.appendChild(T("span","wb-host-ver")).textContent=$.version),O.appendChild(T("span","wb-host-url mono")).textContent=L,O.setAttribute("role","button"),O.tabIndex=0,O.title=`${$.url} · score ${String($.score??0)}`;const J=()=>{ne({kind:"peer",id:`peer-${L}`,title:$.name!==void 0&&$.name!==""?$.name:L,sub:L,url:$.url})};O.addEventListener("click",J),O.addEventListener("keydown",Pe=>{(Pe.key==="Enter"||Pe.key===" ")&&(Pe.preventDefault(),J())}),k.appendChild(O)}}function kt(){if(n===null){we.replaceChildren(),f.setBadge("ledger","");return}const k=n,w=$=>{const L=(k.sessions??[]).find(se=>se.team===$);if(L!==void 0)return{kind:"session",id:L.id,title:ht(L),sub:L.team,team:L.team,live:L.live};const O=(k.remote??[]).find(se=>se.team===$);if(O!==void 0)return{kind:"remote",team:O.team,title:ht(O),sub:O.team,row:O}},H=Ro(we,{state:k,now:e.now(),abandon:($,L)=>e.abandon($,L),canOpenTeam:$=>w($)!==void 0,openTeam:$=>{const L=w($);return L===void 0?!1:(ne(L),!0)}});f.setBadge("ledger",H.badge,H.tone)}function Je(k,w,H){zt(k.appendChild(T("span","wb-row-team")),w,H)}function Qe(){var se;const k=Be(Me);if(n===null)return;const w=e.now(),H=n.inFlight??[];f.setBadge("activity",H.length>0?String(H.length):"",H.length>0?"accent":void 0);const $=T("div","wb-pane-head");if($.textContent=`在途 ${H.length} · 活动 ${((se=n.activity)==null?void 0:se.length)??0}`,k.appendChild($),H.length>0){const ae=T("div","wb-pane-subhead");ae.textContent="在途路由",k.appendChild(ae);for(const Z of H){const xe=T("div","wb-row");xe.appendChild(T("span","wb-row-dir")).textContent="→",Je(xe,n,Z.team),xe.appendChild(T("span","wb-row-meta")).textContent=`${Z.peer} · ${_t(Z.startedAt,w)}`,k.appendChild(xe)}}const L=T("div","wb-pane-subhead");L.textContent="活动环(最新在前)",k.appendChild(L);const O=n.activity??[];if(O.length===0){k.appendChild(T("div","wb-muted")).textContent="暂无活动";return}for(const ae of O){const Z=T("div","wb-row"),xe=T("span","wb-row-dir");xe.textContent=ae.dir==="fwd"?"⇢":ae.dir==="out"?"→":"←",ae.ok!==!0&&xe.classList.add("is-fail"),Z.appendChild(xe),Je(Z,n,ae.team),Z.appendChild(T("span","wb-row-meta")).textContent=`${ae.peer} · ${_t(ae.ts,w)}`,Z.appendChild(T("span","wb-row-badges")).textContent=ae.ok===!0?"":"失败",k.appendChild(Z)}}function vt(k){var se,ae;const w=e.now(),H=[],$=hn(k,w);$.deadLetters.length>0&&H.push({severity:"high",text:`清账 ${$.deadLetters.length} 条死信(目标早已离开或死信化,无回执可期)`});for(const Z of $.stale){const xe=Z.brief===void 0||Z.brief===""?"":`「${Z.brief}」`;H.push({severity:"normal",text:`催办 ${Z.taskId} → ${Fo(k,Z.team)}(等待 ${_t(Z.startedAt,w)} 无回执)${xe}`,brief:`a2a_route 催收回执:task ${Z.taskId}(team ${Z.team})${xe===""?"":`原任务「${Z.brief}」`}已派发 ${_t(Z.startedAt,w)},请回报结果或回执。`})}const L=(k.sessions??[]).filter(Z=>Z.live!==!0).map(Z=>ht(Z));if(L.length>0){const Z=L.slice(0,3).join("、")+(L.length>3?` 等 ${L.length} 个`:"");H.push({severity:"normal",text:`冷会话 ${L.length} 个(${Z}):在 GUI 打开即可唤醒加入面`})}for(const Z of((se=k.reconcile)==null?void 0:se.rows)??[])if(Z.needsRepair===!0){const xe=(k.sessions??[]).find(J=>J.id===Z.id),_e=xe!==void 0?`${ht(xe)}(${Z.id})`:Z.id;H.push({severity:"high",text:`reconcile 需修复:${_e} ${Z.error}`})}const O=((ae=k.idempotency)==null?void 0:ae.conflicts)??0;return O>0&&H.push({severity:"high",text:`幂等冲突 ${O} 例:人工核查 UNIQUE-ization 流量`}),H}function St(){const k=Be(D);if(n===null)return;const w=vt(n);f.setBadge("plan",w.length>0?String(w.length):"",w.some(L=>L.severity==="high")?"danger":void 0);const H=T("div","wb-pane-head");H.textContent=w.length===0?"网络健康——无待办行动":`待办行动 ${w.length}`,k.appendChild(H);for(const L of w){const O=T("div",`wb-action${L.severity==="high"?" wb-action-high":""}`);if(O.appendChild(T("span","wb-action-text")).textContent=L.text,L.brief!==void 0){const se=T("button","wb-btn");se.type="button",se.textContent="复制催办",se.addEventListener("click",()=>e.copy(L.brief??"")),O.appendChild(se)}k.appendChild(O)}const $=T("div","wb-pane-subhead");$.textContent="派单起草(复制后在任一会话粘贴执行)",k.appendChild($),k.appendChild(Se)}const Se=T("div","wb-draft"),Ie=document.createElement("select");Ie.className="wb-select";const tt=document.createElement("textarea");tt.className="wb-textarea",tt.rows=3,tt.placeholder="任务正文:目标、验收、期限…";const ft=T("button","wb-btn wb-btn-primary");ft.type="button",ft.textContent="复制任务书",ft.addEventListener("click",()=>{const k=Ie.value,w=tt.value.trim();k===""||w===""||e.copy(`a2a_route 派单 → ${k}:
|
|
5
|
+
${w}`)}),Se.appendChild(Ie),Se.appendChild(tt),Se.appendChild(ft);function At(){var L;const k=Ie.value;Be(Ie);const w=document.createElement("option");if(w.value="",w.textContent="选择目标队…",Ie.appendChild(w),n===null)return;const H=n,$=new Map;for(const O of H.sessions??[])O.team!==void 0&&O.team!==""&&$.set(O.team,`${ht(O)}(会话队)`);for(const O of((L=H.canvas)==null?void 0:L.teams)??[])$.set(O.team,`${O.name}(canvas 队)`);for(const O of H.remote??[])$.set(O.team,`${ht(O)}(远端)`);for(const[O,se]of $){const ae=document.createElement("option");ae.value=O,ae.textContent=`${se} · ${O}`,Ie.appendChild(ae)}k!==""&&$.has(k)&&(Ie.value=k)}let d,A=!1,I=null;function Q(){var k;me(),A&&((k=e.ownerSettingsRead)==null||k.call(e).then(w=>{if(A){if(w.ok!==!0){I=null,me();return}d=void 0,I={seatNames:w.seatNames??{},teamJoinAllowlist:w.teamJoinAllowlist??[],teamScopeInfo:w.teamScopeInfo!==!1,announce:w.announce===!0,announceRestartPending:w.announceRestartPending===!0},me()}}))}function X(k){const w=T("div","wb-card"),H=T("div","wb-inspector-head");H.appendChild(T("span","wb-inspector-title")).textContent="主人设置";const $=T("button","wb-icon-btn");if($.type="button",$.setAttribute("aria-label","关闭主人设置"),$.textContent="✕",$.addEventListener("click",()=>{A=!1,me()}),H.appendChild($),w.appendChild(H),e.ownerSettingsRead===void 0){const pe=T("div","wb-hint");pe.textContent="此宿主未提供主人设置面(旧版本)——升级后可用。",w.appendChild(pe),k.appendChild(w);return}if(I===null){const pe=T("div","wb-hint");pe.textContent="读取中…",w.appendChild(pe),k.appendChild(w);return}const L=I;d??(d=Yo((n==null?void 0:n.sessions)??[],L.seatNames,async pe=>{var it;const Oe=await((it=e.ownerSettingsWrite)==null?void 0:it.call(e,{seatNames:pe}));return Oe!=null&&Oe.ok?(L.seatNames=pe,{ok:!0}):{ok:!1,error:(Oe==null?void 0:Oe.error)??"保存失败"}})),w.appendChild(d);const O=T("div","wb-side-head");O.textContent="入网白名单(精确团队名)",w.appendChild(O);for(const pe of L.teamJoinAllowlist){const Oe=T("div","wb-member-row");Oe.appendChild(T("span","wb-member-label")).textContent=pe;const it=T("button","wb-member-remove");it.type="button",it.textContent="移除",it.addEventListener("click",()=>{var It;(It=e.ownerSettingsWrite)==null||It.call(e,{teamJoinAllowlist:L.teamJoinAllowlist.filter(cn=>cn!==pe)}).then(()=>Q())}),Oe.appendChild(it),w.appendChild(Oe)}const se=T("div","wb-member-add"),ae=T("input","wb-member-manual");ae.type="text",ae.placeholder="dsh/团队名(精确,无通配)",ae.setAttribute("aria-label","新增白名单团队名");const Z=T("button","wb-member-submit");Z.type="button",Z.textContent="加入";const xe=()=>{var Oe;const pe=ae.value.trim();pe===""||L.teamJoinAllowlist.includes(pe)||(Oe=e.ownerSettingsWrite)==null||Oe.call(e,{teamJoinAllowlist:[...L.teamJoinAllowlist,pe]}).then(()=>Q())};Z.addEventListener("click",xe),ae.addEventListener("keydown",pe=>{pe.key==="Enter"&&xe()}),se.append(ae,Z),w.appendChild(se);const _e=T("div","wb-side-head");_e.textContent="目录可见性(teamScopeInfo)",w.appendChild(_e);const J=T("div","wb-member-row"),Pe=T("button","wb-member-submit");Pe.type="button",Pe.textContent=L.teamScopeInfo?"已开:仅显示已加入团队(点击放开为全舰队可见)":"已关:全舰队可见(点击收窄为已加入团队)",Pe.addEventListener("click",()=>{var pe;(pe=e.ownerSettingsWrite)==null||pe.call(e,{teamScopeInfo:!L.teamScopeInfo}).then(()=>Q())}),J.appendChild(Pe),w.appendChild(J);const Ze=T("div","wb-hint");Ze.textContent="精度说明:teamScopeInfo 只管「目录显示范围」。关上它不会解锁任何通信准入——会话入网(S3)与目标级路由(F5)规则原样生效。",w.appendChild(Ze);const et=T("div","wb-side-head");et.textContent="节点发布(announce)",w.appendChild(et);const pt=T("div","wb-member-row"),Ve=T("button","wb-member-submit");if(Ve.type="button",Ve.textContent=L.announce?"已开:本节点发布签名卡(点击关闭)":"已关:本节点不发布(点击开启——重启宿主后生效)",Ve.addEventListener("click",()=>{var pe;(pe=e.ownerSettingsWrite)==null||pe.call(e,{announce:!L.announce}).then(()=>Q())}),pt.appendChild(Ve),w.appendChild(pt),L.announceRestartPending){const pe=T("div","wb-hint");pe.textContent="有 announce 变更待生效:重启宿主后按新配置发布。",w.appendChild(pe)}k.appendChild(w)}function me(){var $;const k=Be(de);if(A){He.classList.add("is-open"),X(k);return}if(He.classList.toggle("is-open",s!==void 0),s===void 0)return;const w=s,H=T("div","wb-card");if(w.kind==="canvas"){const L=((($=n==null?void 0:n.canvas)==null?void 0:$.teams)??[]).find(J=>J.name===w.row.name)??w.row;Dn(H,"Canvas 队",L.name),Dn(H,"路由队",L.team);const O=T("div","wb-side-head");if(O.textContent=`成员 · ${L.members.length}`,H.appendChild(O),L.members.length===0){const J=T("div","wb-muted");J.textContent="空队——用下方表单添加成员",H.appendChild(J)}for(const J of L.members){const Pe=T("div","wb-member-row"),Ze=J.cliHeld===!0?"本机持有,无需指定":J.remote===!0?J.cliHome===null?"◇ 远端 · home 未确定":"◇ 远端":J.live===!0?"● 现场":J.joined===!0?"○ 冷启":"· 未入网";Pe.appendChild(T("span","wb-member-dot")).textContent=Ze;const et=T("span","wb-member-label"),pt=((n==null?void 0:n.sessions)??[]).find(pe=>pe.id===J.id);et.textContent=J.remote===!0?J.id:pt!==void 0?ht(pt):J.id,et.title=J.cliHeld===!0?"本机持有,无需指定":J.cliHome!==void 0?J.cliHome??"home 未确定":J.team??J.id,Pe.appendChild(et);const Ve=T("button","wb-member-remove");if(Ve.type="button",Ve.textContent="移除",Ve.addEventListener("click",async()=>{Ve.disabled=!0,await e.canvasOp("remove-member",L.name,J.id)||(Ve.disabled=!1)}),Pe.appendChild(Ve),H.appendChild(Pe),J.cliHomeCleared===!0){const pe=T("div","wb-hint");pe.textContent="本机落户已清除旧 home 钉;户口离线后也不会恢复旧钉。",H.appendChild(pe)}if(J.cliHome===null&&J.cliHeld!==!0&&e.cliHomeOptions!==void 0){const pe=JSON.stringify([L.name,J.id]);let Oe=l.get(pe);Oe===void 0&&(Oe=Wo(()=>e.cliHomeOptions(L.name,J.id),it=>e.canvasOp("add-member",L.name,J.id,it)),l.set(pe,Oe)),H.appendChild(Oe)}}if((c==null?void 0:c.name)!==L.name){const J=T("form","wb-member-add"),Pe=document.createElement("select");Pe.className="wb-member-pick",Pe.setAttribute("aria-label","选择成员");const Ze=document.createElement("input");Ze.type="text",Ze.className="wb-member-manual",Ze.placeholder="或输入远端句柄 zone/id8",Ze.setAttribute("aria-label","远端成员句柄");const et=T("button","wb-member-submit");et.type="submit",et.textContent="添加",J.appendChild(Pe),J.appendChild(Ze),J.appendChild(et),J.addEventListener("submit",async pt=>{pt.preventDefault();const Ve=Ze.value.trim(),pe=Ve!==""?Ve:Pe.value;if(pe==="")return;et.disabled=!0;const Oe=await e.canvasOp("add-member",L.name,pe);et.disabled=!1,Oe&&(Ze.value="")}),c={name:L.name,form:J,pick:Pe,manual:Ze}}const se=c.pick,ae=se.value;Be(se),se.appendChild(new Option("本机会话(现场/冷启动)…","",!0,!0));const Z=new Set(L.members.map(J=>J.id));for(const J of(n==null?void 0:n.sessions)??[])Z.has(J.id)||se.appendChild(new Option(`${ht(J)} — 本机`,J.id));let xe=!1;for(const J of(n==null?void 0:n.remote)??[])J.team.includes("/")&&(Z.has(J.team)||(xe||(se.appendChild(new Option("远端会话队(目录卡片)…","",!0,!1)),xe=!0),se.appendChild(new Option(`${ht(J)} — 远端`,J.team))));xe||se.appendChild(new Option("(暂无可拉入的远端会话队——见下方说明)","",!0,!1)),ae!==""&&Array.from(se.options).some(J=>J.value===ae)&&(se.value=ae),H.appendChild(c.form);const _e=T("div","wb-hint");_e.textContent="成员由人类在此手工分配(agent 不可自组队)。远端成员走对端目录路由,不做本机冷唤醒;地址由目录在派发时重解析。远端下拉只列 zone/id8 会话句柄——若为空,说明目录里还没有已链接对端的会话队(未链接的对端只给最小卡);此时可在输入框手输句柄(如 dsh/xxxxxxxx)先把人拉进来,句柄本身即链接手势。",H.appendChild(_e),e.dispatchQuick!==void 0&&H.appendChild(ve(L.team))}k.appendChild(H)}function ge(k){const w=T("form","wb-dispatch-form"),H=document.createElement("textarea");H.className="wb-dispatch-text",H.placeholder="一句话任务…(≤4000 字符,异步送达,回执进台账)",H.setAttribute("aria-label","快派消息");const $=T("button","wb-dispatch-submit");$.type="submit",$.textContent="发送";const L=T("div","wb-dispatch-note");return w.appendChild(H),w.appendChild($),w.appendChild(L),H.addEventListener("keydown",O=>{O.key!=="Enter"||O.shiftKey||O.ctrlKey||O.altKey||O.metaKey||O.isComposing||(O.preventDefault(),$.disabled||w.requestSubmit())}),w.addEventListener("submit",async O=>{var Z;O.preventDefault();const se=H.value.trim();if(se===""||$.disabled)return;$.disabled=!0,L.textContent="派发中…";let ae;try{ae=await(((Z=e.dispatchQuick)==null?void 0:Z.call(e,k,se))??Promise.resolve({ok:!1,error:"dispatch unavailable"}))}catch(xe){ae={ok:!1,error:xe instanceof Error?xe.message:String(xe)}}$.disabled=!1,ae.ok===!0&&(H.value=""),H.focus({preventScroll:!0}),L.textContent=ae.ok===!0?`已派发${ae.task_id!==void 0?` · ${ae.task_id}`:""} · 回执将入台账(待回执)`:`失败:${ae.error??"未知原因"}`}),{form:w,text:H,note:L}}function ve(k){const w=T("div","wb-dispatch"),H=T("div","wb-side-head");return H.textContent="快派",w.appendChild(H),(u==null?void 0:u.team)!==k&&(u={team:k,...ge(k)}),w.appendChild(u.form),w}function ne(k){ee.open(k),Y.classList.remove("is-rail-open")}function We(k){if(n===null)return;const w=(n.sessions??[]).find($=>$.id===k);if(w!==void 0){ne({kind:"session",id:k,title:ht(w),sub:w.team,team:w.team,live:w.live});return}if(k.startsWith("peer-")){const $=k.slice(5),L=(n.peers??[]).find(O=>O.url.includes($));ne({kind:"peer",id:k,title:L!==void 0?L.url:$,sub:$,url:L==null?void 0:L.url});return}b.find($=>$.id===k)!==void 0&&ne({kind:"log",id:k,title:`…${k.slice(-12)}`,sub:"档案"})}function Te(){var Z,xe;C.textContent=(n==null?void 0:n.version)!==void 0?`v${n.version}`:"",C.hidden=(n==null?void 0:n.version)===void 0;const k=Be(E);if(n===null)return;const w=[],H=hn(n,e.now()),$=H.deadLetters.length;$>0&&w.push({text:`死信 ${$}`,tone:"danger",title:"超过 24h TTL 仍未结算的任务(unconsumed),需在台账清账",tab:"ledger",group:"死信"});const L=H.stale.length;L>0&&w.push({text:`陈旧 ${L}`,tone:"warn",title:"我方派发、要回执、已等待 ≥1h 仍未回执(可催办;免回执行不算)",tab:"ledger",group:"陈旧"});const O=H.owedOverdue.length;O>0&&w.push({text:`欠回执 ${O}`,tone:"warn",title:"对方投递给本机、已等待本机回执超过 1 小时",tab:"ledger",group:"待本机回执"});const se=((Z=n.idempotency)==null?void 0:Z.conflicts)??0;se>0&&w.push({text:`幂等冲突 ${se}`,tone:"danger",title:"同一幂等键对应了不同载荷,需人工核查",tab:"ledger",group:"取证"});const ae=(((xe=n.reconcile)==null?void 0:xe.rows)??[]).filter(_e=>_e.needsRepair===!0).length;if(ae>0&&w.push({text:`需修复 ${ae}`,tone:"danger",title:"reconcile 无法自动恢复的会话,见行动计划",tab:"plan"}),w.length===0){k.appendChild(T("span","wb-header-ok")).textContent="● 无异常";return}for(const _e of w){const J=T("button",`wb-alert wb-alert-${_e.tone}`);J.type="button",J.textContent=_e.text,J.title=`${_e.title}(点击查看)`,J.addEventListener("click",()=>Xe(_e.tab,_e.group)),k.appendChild(J)}}function Xe(k,w){var L;const H=ce.find(([O])=>O===k)[1];o==="canvas"&&(Y.classList.add("is-rail-open"),f.select(k,{focus:!1}));const $=w===void 0?H:w==="取证"?H.querySelector("details.wb-led-forensics"):Array.from(H.querySelectorAll(".wb-led-group")).find(O=>O.dataset.group===w)??null;$!==null&&($ instanceof HTMLDetailsElement&&($.open=!0),(L=$.scrollIntoView)==null||L.call($,{block:"start",behavior:"smooth"}))}function Lt(k){var H;const w=new Set((((H=k==null?void 0:k.canvas)==null?void 0:H.teams)??[]).flatMap($=>$.members.filter(L=>L.cliHome===null&&L.cliHeld!==!0).map(L=>JSON.stringify([$.name,L.id]))));for(const $ of l.keys())w.has($)||l.delete($);n=k,e.sessionLogList!==void 0&&!N&&(N=!0,e.sessionLogList().then($=>{b=$.ok&&$.sessions!==void 0?$.sessions:[],m=$.ok?$.count:void 0}).catch(()=>{}).finally(()=>{N=!1,qe()})),Te(),qe(),At(),ut(),kt(),ee.update(k),Qe(),St(),me(),Ce()}function nt(k){if(k==="board"){Ce();return}f.select(k)}return Lt(null),{root:Y,update:Lt,mode:()=>o,selectTab:nt,openNodeChat:We}}const bt=1e6,Cn=.25,kn=3,mo=256,uo=96;function Mt(e){const t=typeof e=="number"?e:Number.NaN;if(Number.isFinite(t))return Math.max(-bt,Math.min(bt,Math.round(t)))}function fo(e){if(e===null||typeof e!="object")return;const t=e,o=Mt(t.x),s=Mt(t.y);return o===void 0||s===void 0?void 0:{x:o,y:s}}function is(e){const t=fo(e);if(t===void 0)return;const o=e,s=Mt(o.w),n=Mt(o.h);if(!(s===void 0||n===void 0||s<=0||n<=0))return{...t,w:Math.min(s,bt),h:Math.min(n,bt)}}const po=e=>e!==""&&!e.includes("/")&&(e.startsWith("roster:")?e.length>7&&e.length<=47:e.length<=40);function ho(e){if(e===null||typeof e!="object")return;const t=e;if(t.version!==1)return;const o=t.viewport;if(o===null||typeof o!="object")return;const s=o,n=Mt(s.x),i=Mt(s.y),r=s.scale,c=typeof r=="number"?r:Number.NaN;if(n===void 0||i===void 0||!Number.isFinite(c))return;const l=Math.max(Cn,Math.min(kn,c)),u={};if(t.nodes!==null&&typeof t.nodes=="object")for(const[m,x]of Object.entries(t.nodes)){if(typeof m!="string"||m===""||m.length>128)continue;const N=fo(x);if(N!==void 0&&(u[m]=N),Object.keys(u).length>=mo)break}const b={};if(t.frames!==null&&typeof t.frames=="object")for(const[m,x]of Object.entries(t.frames)){if(!po(m))continue;const N=is(x);if(N!==void 0&&(b[m]=N),Object.keys(b).length>=uo)break}return{version:1,viewport:{x:n,y:i,scale:l},nodes:u,frames:b}}function rs(e,t,o){const s=r=>Math.max(-bt,Math.min(bt,Math.round(r))),n={};for(const[r,c]of t)if(!(typeof r!="string"||r===""||r.length>128)&&(n[r]={x:s(c.x),y:s(c.y)},Object.keys(n).length>=mo))break;const i={};for(const[r,c]of o){if(!po(r))continue;const l=s(c.w),u=s(c.h);if(!(l<=0||u<=0)&&(i[r]={x:s(c.x),y:s(c.y),w:Math.min(l,bt),h:Math.min(u,bt)},Object.keys(i).length>=uo))break}return{version:1,viewport:{x:s(e.x),y:s(e.y),scale:Math.max(Cn,Math.min(kn,e.scale))},nodes:n,frames:i}}function bo(e){let t=2166136261;for(let o=0;o<e.length;o++)t^=e.charCodeAt(o),t=Math.imul(t,16777619)>>>0;return t>>>0}const Ue=172,De=56,xt=[150,290,430],at=16;function as(e){const t=bo(e),o=Math.floor(t/at)%xt.length,n=t%at/at*Math.PI*2+o*(Math.PI/at),i=xt[o];return{x:Math.round(Math.cos(n)*i),y:Math.round(Math.sin(n)*i*.6)}}function go(e){const t=new Map;for(const o of e)for(const s of o.members)t.has(s.id)||t.set(s.id,o.name);return t}const Rn=64,Hn=24,jn=20,cs=4,Bn=24,Yn=44,ls=24;function ds(e,t,o=Number.POSITIVE_INFINITY){const s=new Set(t),n=go(e),i=e.map(m=>[...new Set(m.members.map(x=>x.id))].filter(x=>s.has(x)&&n.get(x)===m.name));i.push(t.filter(m=>!n.has(m)));const r=new Map;let c=0,l=0,u=0,b=0;for(const m of i){if(m.length===0)continue;const x=Math.min(3,Math.max(m.length>1?2:1,Math.ceil(Math.sqrt(m.length)))),N=Math.ceil(m.length/x),Y=Math.max(260,x*Ue+(x-1)*Hn+Bn*2),re=Math.max(160,N*De+(N-1)*jn+Yn+ls);b>0&&(b%cs===0||c+Y>o)&&(c=0,l+=u+Rn,u=0),m.forEach((V,M)=>{const C=M%x,S=Math.floor(M/x);r.set(V,{x:c+Bn+Ue/2+C*(Ue+Hn),y:l+Yn+De/2+S*(De+jn)})}),c+=Y+Rn,u=Math.max(u,re),b+=1}return r}const Wt=12;function vo(e,t){const o=l=>t.every(u=>Math.abs(u.x-l.x)>=Ue+Wt||Math.abs(u.y-l.y)>=De+Wt),s=as(e);if(o(s))return s;const n=bo(e),i=at*xt.length,r=Math.floor(n/at)%xt.length*at+n%at;for(let l=1;l<i;l++){const u=(r+l)%i,b=Math.floor(u/at),m=u%at/at*Math.PI*2+b*(Math.PI/at),x=xt[b],N={x:Math.round(Math.cos(m)*x),y:Math.round(Math.sin(m)*x*.6)};if(o(N))return N}const c=xt[xt.length-1];for(let l=0;;l++)for(let u=0;u<6;u++){const b={x:Math.round(-c+u*(Ue+Wt)),y:Math.round(c*.6+De*2+l*(De+Wt))};if(o(b))return b}}function mt(e){return{x:e.x-Ue/2,y:e.y-De/2,w:Ue,h:De}}function En(e){if(e.length===0)return{x:0,y:0,w:260,h:160};let t=Number.POSITIVE_INFINITY,o=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY,n=Number.NEGATIVE_INFINITY;for(const b of e)t=Math.min(t,b.x),o=Math.min(o,b.y),s=Math.max(s,b.x+b.w),n=Math.max(n,b.y+b.h);const i=24,r=44,c=24,l=Math.max(260,Math.round(s-t+i*2)),u=Math.max(160,Math.round(n-o+r+c));return{x:Math.round(t-i),y:Math.round(o-r),w:l,h:u}}class Nn{constructor(){Et(this,"revisionCounter",0);Et(this,"nodes",new Map);Et(this,"frames",new Map);Et(this,"selection",new Set);Et(this,"viewport",{x:0,y:0,scale:1})}get revision(){return this.revisionCounter}getNode(t){return this.nodes.get(t)}allNodes(){return[...this.nodes.values()]}nodeIds(){return[...this.nodes.keys()]}getFrame(t){return this.frames.get(t)}allFrames(){return[...this.frames.entries()]}isSelected(t){return this.selection.has(t)}selectedIds(){return[...this.selection]}bump(){this.revisionCounter+=1}dragNodes(t,o,s){let n=!1;for(const i of t){const r=this.nodes.get(i);r!==void 0&&(r.x+=o,r.y+=s,n=!0)}n&&this.bump()}beginFrameDrag(t){const o=this.frames.get(t);if(o!==void 0)return{name:t,rect:{...o}}}applyFrameDrag(t,o,s){const n=this.frames.get(t.name);n!==void 0&&(n.x=t.rect.x+o,n.y=t.rect.y+s,this.bump())}nudge(t,o,s){this.dragNodes(t,o,s)}marqueeSelect(t,o){o||this.selection.clear();for(const s of this.nodes.values()){const n=mt(s);n.x<t.x+t.w&&n.x+n.w>t.x&&n.y<t.y+t.h&&n.y+n.h>t.y&&this.selection.add(s.id)}this.bump()}setSelection(t){this.selection=new Set(t),this.bump()}upsertNode(t){const o=this.nodes.get(t.id);if(o===void 0){this.nodes.set(t.id,t),this.bump();return}o.label=t.label,o.name=t.name,o.description=t.description,o.live=t.live,o.memberships=t.memberships,this.bump()}removeNode(t){this.nodes.delete(t)&&(this.selection.delete(t),this.bump())}setFrame(t,o){this.frames.set(t,o),this.bump()}removeFrame(t){this.frames.delete(t)&&this.bump()}upsertScore(t,o){const s=this.nodes.get(t);s===void 0||s.score===o||(s.score=o,this.bump())}positions(){const t=new Map;for(const[o,s]of this.nodes)t.set(o,{x:s.x,y:s.y});return t}frameRects(){const t=new Map;for(const[o,s]of this.frames)t.set(o,{...s});return t}teamMemberIds(t){const o=[];for(const s of this.nodes.values()){const n=s.memberships.find(i=>i.team===t);n!==void 0&&o.push({id:s.id,index:n.index})}return o.sort((s,n)=>s.index-n.index).map(s=>s.id)}setTeamMembers(t,o){for(const s of this.nodes.values()){const n=s.memberships.filter(r=>r.team!==t),i=o.indexOf(s.id);i>=0&&n.push({team:t,index:i}),s.memberships=n}this.bump()}contentBounds(){let t=Number.POSITIVE_INFINITY,o=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY,n=Number.NEGATIVE_INFINITY;const i=r=>{t=Math.min(t,r.x),o=Math.min(o,r.y),s=Math.max(s,r.x+r.w),n=Math.max(n,r.y+r.h)};for(const r of this.nodes.values())r.remote!==!0&&i(mt(r));for(const r of this.frames.values())i(r);return t===Number.POSITIVE_INFINITY?null:{minX:t,minY:o,maxX:s,maxY:n}}static fromState(t){const o=new Nn,s=ho(t.layout),n=new Map;for(const i of t.teams)for(let r=0;r<i.members.length;r++){const c=i.members[r].id,l=n.get(c)??[];l.push({team:i.name,index:r}),n.set(c,l)}for(const i of t.sessions){if(i.joined!==!0)continue;const r=s==null?void 0:s.nodes[i.id];let c,l;if(r!==void 0&&typeof r.x=="number"&&typeof r.y=="number")c=r.x,l=r.y;else{const u=vo(i.id,[...o.nodes.values()]);c=u.x,l=u.y}o.nodes.set(i.id,{id:i.id,x:c,y:l,label:i.label,team:i.team,name:i.name,description:i.description,live:i.live!==!1,memberships:n.get(i.id)??[]})}for(const i of t.teams){const r=s==null?void 0:s.frames[i.name];if(r!==void 0){o.frames.set(i.name,{x:r.x,y:r.y,w:r.w,h:r.h});continue}const c=[];for(const l of i.members){const u=o.nodes.get(l.id);u!==void 0&&c.push(mt(u))}c.length>0&&o.frames.set(i.name,En(c))}return o.viewport=s!==void 0?{...s.viewport}:{x:0,y:0,scale:1},o}}const ms=24,yo=-13,us=yo+ms;function fs(e,t,o){const s=[],n=new Set;for(const i of e){const r=t.get(i.name);if(r===void 0)continue;const c=r.x+r.w/2,l=r.y+us;for(const u of i.members){const b=o.get(u.id);if(b===void 0)continue;const m=n.has(u.id);n.add(u.id),s.push({x1:c,y1:l,x2:b.x,y2:b.y-De/2,dashed:m,team:i.name,id:u.id})}}return s}function ps(e,t){for(;e.firstChild!==null;)e.firstChild.remove();const o=t.allFrames().map(([s])=>({name:s,members:t.teamMemberIds(s).map(n=>({id:n}))}));for(const s of fs(o,new Map(t.allFrames()),t.positions())){const n=document.createElementNS("http://www.w3.org/2000/svg","line");n.setAttribute("class","e-member"+(s.dashed?" dashed":"")),n.setAttribute("x1",String(s.x1)),n.setAttribute("y1",String(s.y1)),n.setAttribute("x2",String(s.x2)),n.setAttribute("y2",String(s.y2)),e.appendChild(n)}}function hs(e){return`peer-${dt(e).replace(/[^A-Za-z0-9.:\[\]-]/g,"-")}`}function dt(e){try{return new URL(e).host}catch{return e}}function bs(e){const t=new Map;for(const o of e){const s=o.via!==void 0&&o.via!==""?dt(o.via):"",n=t.get(s)??[];n.push(o),t.set(s,n)}return t}const gs=140,vs=200,ys=90,ws=20,Xt=60;function xs(e,t){const o=t!==null?t.maxX+gs:vs,s=t!==null?t.minY:0;return e.map((n,i)=>({url:n.url,score:n.score,x:o,y:s+i*ys}))}function Cs(e,t,o,s){const n=new Map;for(const r of e){if(!t.has(r.team))continue;const c=`${r.team}\0${r.peer}`,l=n.get(c);l===void 0?n.set(c,{team:r.team,peer:r.peer,startedAt:r.startedAt,count:1}):(l.startedAt=Math.min(l.startedAt,r.startedAt),l.count+=1)}const i=[];for(const r of n.values()){const c=t.get(r.team);if(c===void 0)continue;const l=o.find(b=>{try{return new URL(b.url).host===r.peer}catch{return!1}});if(l===void 0)continue;const u=Math.max(0,Math.round((s-r.startedAt)/1e3));i.push({x1:c.x,y1:c.y,x2:l.x,y2:l.y,label:`a2a_route · ${r.peer} · ${u}s`+(r.count>1?` ×${r.count}`:"")})}return i}function ks(e,t){const o=t!==null?{x:t.maxX+ws,y:e.length>0?(e[0].y+e[e.length-1].y)/2:(t.minY+t.maxY)/2}:{x:-80,y:0};return e.map((s,n)=>({x1:o.x,y1:o.y,x2:s.x,y2:s.y,label:n===0?"gns referral":""}))}function Es(e,t){if(e===null&&t.length===0)return null;let o=e!==null?e.minX:Number.POSITIVE_INFINITY,s=e!==null?e.minY:Number.POSITIVE_INFINITY,n=e!==null?e.maxX:Number.NEGATIVE_INFINITY,i=e!==null?e.maxY:Number.NEGATIVE_INFINITY;for(const r of t)o=Math.min(o,r.x-Xt),s=Math.min(s,r.y-Xt),n=Math.max(n,r.x+Xt),i=Math.max(i,r.y+Xt);return{minX:o,minY:s,maxX:n,maxY:i}}const Ns=11;function $s(e,t){let o=[],s=[],n=[];function i(c){for(const b of o)b.remove();o=[];const l=t.allNodes().filter(b=>b.remote===!0).map(b=>({url:b.peerUrl??b.id.slice(5),score:b.score,x:b.x,y:b.y}));s=l;const u=t.contentBounds();if(u!==null){const b=new Map;for(const[m,x]of t.allFrames())b.set(m,{name:m,x:x.x+x.w/2,y:x.y+Ns});for(const m of Cs(n,b,l,c))o.push(...r(m,"e-activity",m.label));for(const m of ks(l,u))o.push(...r(m,"e-federal",m.label))}}function r(c,l,u){const b=document.createElementNS("http://www.w3.org/2000/svg","line");b.setAttribute("class",l),b.setAttribute("x1",String(c.x1)),b.setAttribute("y1",String(c.y1)),b.setAttribute("x2",String(c.x2)),b.setAttribute("y2",String(c.y2)),e.appendChild(b);const m=[b];if(u!==""){const x=document.createElementNS("http://www.w3.org/2000/svg","text");x.setAttribute("class","edge-label mono"),x.setAttribute("x",String((c.x1+c.x2)/2+14)),x.setAttribute("y",String((c.y1+c.y2)/2+18)),x.textContent=u,e.appendChild(x),m.push(x)}return m}return{render:i,flyTo(c){return c(),s},placements:()=>s,setInFlight:c=>{n=c}}}function wo(e,t){const o=new Map,s=new Set;for(const n of e){if(n.joined!==!0)continue;const i=n.team.lastIndexOf("/");if(i<=0||n.team.slice(i+1)!==n.id.replace(/^session-/,"").slice(0,8))continue;const r=n.team;t.has(r)||s.has(r)||(o.has(r)?(o.delete(r),s.add(r)):o.set(r,n.id))}return o}function Ms(e,t,o,s){var r;const n=t.get(e);return n!==void 0?n:e.includes("/")?`member-${e.replace(/[^a-z0-9-]/gi,"-")}`:`member-${((r=o==null?void 0:o.find(c=>c.via===s))==null?void 0:r.team.split("/")[0])??"dsh"}-${e.replace(/^session-/,"").slice(0,8)}`}function Ss(e){const t=new Map;for(const o of e)for(let s=0;s<o.members.length;s++){const n=o.members[s].id,i=t.get(n)??[];i.push({team:o.name,index:s}),t.set(n,i)}return t}function As(e,t,o){const s=wo(t,new Set((o??[]).map(i=>i.team))),n=new Set;for(const i of e)for(const r of i.org)for(const c of r.members){const l=s.get(c);l!==void 0&&n.add(l)}return n}const Wn={x:0,y:0,scale:1};function Zt(e){return Math.max(Cn,Math.min(kn,e))}function Nt(e){const t=Number.isFinite(e.scale)?e.scale:1,o=Number.isFinite(e.x)?e.x:0,s=Number.isFinite(e.y)?e.y:0;return{x:o,y:s,scale:Zt(t)}}function ct(e,t,o){return{x:e.x+t/e.scale,y:e.y+o/e.scale}}function un(e,t,o){return{x:e.x+t/e.scale,y:e.y+o/e.scale,scale:e.scale}}function Xn(e,t,o,s){const n=Zt(e.scale*t);return n===e.scale?e:{x:e.x+o/e.scale-o/n,y:e.y+s/e.scale-s/n,scale:n}}const Ls=680,Is=.8,Ts=.6,Kn=16;function $n(e,t,o,s=Number.POSITIVE_INFINITY){if(e===null||t<=0||o<=0)return Wn;const n=e.maxX-e.minX,i=e.maxY-e.minY;if(!(n>0)||!(i>0))return Wn;const r=.9*Math.min(t/n,o/i),c=Math.min(s,r),l=t<Ls?Is:Ts;if(r<l){const b=Zt(Math.min(s,l));return{x:e.minX-Kn/b,y:e.minY-Kn/b,scale:b}}const u=Zt(c);return{x:(e.minX+e.maxX)/2-t/(2*u),y:(e.minY+e.maxY)/2-o/(2*u),scale:u}}function _s(e){return`translate(${-e.x*e.scale}px, ${-e.y*e.scale}px) scale(${e.scale})`}function Un(e,t){let o=e===null?null:{...e,minY:e.minY+yo};for(const s of t){if(s.remote!==!0)continue;const n=mt(s);o=o===null?{minX:n.x,minY:n.y,maxX:n.x+n.w,maxY:n.y+n.h}:{minX:Math.min(o.minX,n.x),minY:Math.min(o.minY,n.y),maxX:Math.max(o.maxX,n.x+n.w),maxY:Math.max(o.maxY,n.y+n.h)}}return o}function qn(e,t,o,s){const n=s>0&&s<o/2?s:0,i=$n(e,t,o-n,1);return n===0||e===null?i:{...i,y:i.y-n/i.scale}}function zn(...e){const t=Math.max(0,...e.map(o=>o.offsetHeight>0?o.offsetTop+o.offsetHeight:0));return t>0?t+8:0}function Rt(e){return e.type==="join-network"||e.type==="leave-network"?"$network":e.type==="create-team"||e.type==="remove-team"?e.name:e.team}function Os(e,t){if(t.type==="create-team"){const n=t.ids.map(i=>e.getNode(i)).filter(i=>i!==void 0).map(i=>mt(i));return n.length>0&&e.setFrame(t.name,En(n)),e.setTeamMembers(t.name,t.ids),()=>{e.setTeamMembers(t.name,e.teamMemberIds(t.name).filter(i=>!t.ids.includes(i))),e.removeFrame(t.name)}}if(t.type==="add-member"){const n=e.teamMemberIds(t.team),i=t.ids.filter(r=>!n.includes(r));return e.setTeamMembers(t.team,[...n,...i]),()=>{e.setTeamMembers(t.team,e.teamMemberIds(t.team).filter(r=>!i.includes(r)))}}if(t.type==="remove-member"){const n=e.teamMemberIds(t.team);return e.setTeamMembers(t.team,n.filter(i=>!t.ids.includes(i))),()=>{const i=e.teamMemberIds(t.team);e.setTeamMembers(t.team,[...i,...t.ids.filter(r=>!i.includes(r))])}}if(t.type==="remove-team"){const n=e.teamMemberIds(t.name),i=e.getFrame(t.name),r=i!==void 0?{...i}:void 0;return e.setTeamMembers(t.name,[]),e.removeFrame(t.name),()=>{r!==void 0&&e.setFrame(t.name,r),e.setTeamMembers(t.name,n)}}if(t.type==="join-network"||t.type==="leave-network")return()=>{};const o=e.teamMemberIds(t.team);let s=[...o];for(const n of t.ops)n.op==="remove"?s=s.filter(i=>i!==n.id):s.push(n.id);return e.setTeamMembers(t.team,s),()=>{let n=e.teamMemberIds(t.team);for(let i=0;i<o.length;i++){const r=o[i];n[i]!==r&&n.includes(r)&&(n=n.filter(c=>c!==r),n.push(r))}e.setTeamMembers(t.team,n)}}function Jn(e,t,o,s,n){if(o||s(),!(t.type==="remove-team"&&o||t.type==="create-team"&&!o&&t.created===!0)||n===void 0||e.getFrame(Rt(t))!==void 0)return n;const r={...n.frames};return delete r[Rt(t)],{...n,frames:r}}function vn(e,t){const o=[...e],s=[];for(let n=0;n<t.length;n++){const i=t[n];o[n]!==i&&o.includes(i)&&(s.push({op:"remove",id:i}),s.push({op:"add",id:i}),o.splice(o.indexOf(i),1),o.push(i))}return s}function Fs(e,t){return e.teamMemberIds(t).map(o=>{var s;return{id:o,y:((s=e.getNode(o))==null?void 0:s.y)??0}}).sort((o,s)=>o.y-s.y).map(o=>o.id)}function Kt(e,t){let o,s=Number.POSITIVE_INFINITY;for(const[n,i]of e){if(t.x<i.x||t.x>i.x+i.w||t.y<i.y||t.y>i.y+i.h)continue;const r=i.w*i.h;r<s&&(o=n,s=r)}return o}const Vn=[9133302,3900150,1357990,16096779,15485081,8702998];function Ps(e){let t=0;for(let c=0;c<e.length;c++)t=(t*31+e.charCodeAt(c)&268435455)>>>0;const o=Vn[t%Vn.length],s="#"+o.toString(16).padStart(6,"0"),n=o>>16&255,i=o>>8&255,r=o&255;return{line:s,bg:`rgba(${n},${i},${r},0.05)`}}const en="roster:",xo=e=>e.startsWith(en)?e.slice(en.length):void 0,Ft=e=>en+e,tn=e=>{const t=xo(e);return t===void 0?e:`网络队 · roster · ${t}`};function Ds(e,t){return e.flatMap(o=>{if(t===""||!o.team.startsWith(t+"/")||!Array.isArray(o.members))return[];const s=o.team.slice(t.length+1);return s===""||s.length>40||s.includes("/")||s.startsWith(en)||s.includes("*")?[]:[{name:Ft(s),team:o.team,kind:"roster",members:o.members.filter(n=>typeof n=="string"&&n!=="").map(n=>({id:n}))}]})}function Rs(e){const{root:t,netBtn:o,signal:s,model:n}=e,i=y=>e.isRoster(y)?tn(y):y;function r(){return n.selectedIds().map(y=>{var f;return{id:y,y:((f=n.getNode(y))==null?void 0:f.y)??0}}).sort((y,f)=>y.y-f.y).map(y=>y.id)}function c(){if(l!==null)return;const y=r().filter(f=>{const _=n.getNode(f);return _===void 0?!1:_.remote!==!0||_.remoteHandle!==void 0&&_.remoteHandle!==""});if(y.length<2){e.notice("info","框选至少 2 个会话节点");return}u(y)}let l=null;function u(y){const f=document.createElement("div");f.className="p-dialog";const _=document.createElement("div");_.className="p-dialog-panel",_.setAttribute("role","dialog"),_.setAttribute("aria-modal","true"),_.setAttribute("aria-labelledby","p-dialog-title");const p=document.createElement("div");p.id="p-dialog-title",p.className="p-dialog-title",p.textContent=`组建团队(${y.length} 个节点,自上而下即优先级)`;const R={value:"canvas"},j=document.createElement("div");j.className="p-dialog-kind",j.setAttribute("role","radiogroup"),j.setAttribute("aria-label","团队类型");const K=document.createElement("div");K.className="p-dialog-hint";const we={canvas:"canvas 队:画布上的协作组,可以加入远端成员。",roster:"roster 网络队:只收本机已入网的会话;队名会写进属主的精确允许名单。"},Me=["canvas","roster"].map(ee=>{const te=document.createElement("button");return te.type="button",te.dataset.kind=ee,te.setAttribute("role","radio"),te.textContent=ee==="canvas"?"canvas 队":"roster 网络队",te.addEventListener("click",()=>D(ee)),j.appendChild(te),te});function D(ee){R.value=ee;for(const te of Me){const Ce=te.dataset.kind===ee;te.setAttribute("aria-checked",String(Ce)),te.tabIndex=Ce?0:-1}K.textContent=we[ee],ce.textContent=""}j.addEventListener("keydown",ee=>{var Ce;const te=ee;["ArrowLeft","ArrowRight","ArrowUp","ArrowDown"].includes(te.key)&&(te.preventDefault(),D(R.value==="canvas"?"roster":"canvas"),(Ce=Me.find(Be=>Be.dataset.kind===R.value))==null||Ce.focus())});const U=document.createElement("input");U.className="p-dialog-input",U.maxLength=40,U.setAttribute("aria-label","团队名");const ce=document.createElement("div");ce.className="p-dialog-err",ce.setAttribute("aria-live","polite");const Re=document.createElement("div");Re.className="p-dialog-row";const Ee=document.createElement("button");Ee.type="button",Ee.textContent="组建";const le=document.createElement("button");le.type="button",le.textContent="取消",Re.append(Ee,le),D("canvas"),_.append(p,j,K,U,ce,Re),f.appendChild(_),t.appendChild(f);const He=document.activeElement,fe=()=>{f.remove(),l=null,He==null||He.focus()},q=()=>{const ee=U.value.trim();return ee===""||ee.length>40||ee.includes("/")||ee.startsWith("roster:")||R.value==="roster"&&ee.includes("*")||/^\d+$/.test(ee)?"队名需 1..40 字,不含“/”、通配符或保留前缀,不为纯数字":R.value==="roster"&&n.getFrame(ee)!==void 0?"同名 canvas 队已存在,不能创建 roster 队":R.value==="roster"&&n.getFrame(Ft(ee))!==void 0&&!e.isRoster(Ft(ee))?"roster 框名已被 canvas 或镜像队占用":R.value==="canvas"&&n.getFrame(Ft(ee))!==void 0?"同名 roster 队已存在,不能创建 canvas 队":R.value==="roster"&&y.some(te=>{var Ce;return((Ce=n.getNode(te))==null?void 0:Ce.remote)===!0||!e.joined(te)})?"roster 仅接受本机已入网的会话":null},de=()=>{const ee=q();if(ee!==null){ce.textContent=ee,U.focus();return}const te=R.value==="roster"?Ft(U.value.trim()):U.value.trim();if(fe(),n.getFrame(te)!==void 0){e.notice("info",`已加入现有团队「${R.value==="roster"?tn(te):te}」`),e.emit({type:"add-member",team:te,ids:y});return}e.emit({type:"create-team",name:te,ids:y,created:!0,...R.value==="roster"?{roster:!0}:{}})};Ee.addEventListener("click",de),le.addEventListener("click",fe),U.addEventListener("keydown",ee=>{const te=ee;te.key==="Enter"&&(te.preventDefault(),de()),te.key==="Escape"&&(te.preventDefault(),fe())}),f.addEventListener("keydown",ee=>{const te=ee;if(te.key==="Escape"){te.preventDefault(),te.stopPropagation(),fe();return}if(te.key!=="Tab")return;te.preventDefault();const Ce=Array.from(_.querySelectorAll('input, select, button:not([tabindex="-1"])')),Be=Ce.indexOf(document.activeElement),Ye=te.shiftKey?Ce[(Be-1+Ce.length)%Ce.length]:Ce[(Be+1)%Ce.length];Ye==null||Ye.focus()},s),l={wrap:f,restoreFocus:He},U.focus()}let b=null,m="root",x=null,N=null,Y=[];function re(){N==null||N.remove(),N=null}function V(){var _;if(N!==null){re();return}if(Y.length===0)return;const y=document.createElement("div");y.className="p-menu p-netmenu",y.setAttribute("role","menu"),y.setAttribute("aria-label","未入网会话");for(const p of Y)y.appendChild(C(`${p.name!==void 0&&p.name!==""?p.name:p.label} — 入网`,!0,()=>{re(),e.emit({type:"join-network",id:p.id})}));N=y,t.appendChild(y);const f=o.getBoundingClientRect();y.style.left=`${String(Math.min(f.left,window.innerWidth-220))}px`,y.style.top=`${String(Math.max(8,f.top-(Y.length*30+10)))}px`,y.addEventListener("keydown",p=>{p.key==="Escape"&&(p.stopPropagation(),re(),o.focus())}),(_=y.querySelector("button"))==null||_.focus(),document.addEventListener("pointerdown",p=>{if(N===null)return;const R=p.target;R!==null&&(R.closest(".p-netmenu")!==null||R===o||o.contains(R))||re()},s)}function M(){b==null||b.remove(),b=null,m="root",x!==null&&x.isConnected?x.focus():t.focus(),x=null}function C(y,f,_){const p=document.createElement("button");return p.type="button",p.setAttribute("role","menuitem"),p.textContent=y,f?p.addEventListener("click",()=>{M(),_()}):(p.disabled=!0,p.setAttribute("aria-disabled","true")),p}function S(y,f,_,p="root",R){var Me,D,U,ce,Re,Ee,le,He;R!==void 0&&(x=R),x===null&&(x=e.anchorFor(_)),b==null||b.remove(),m=p;const j=document.createElement("div");j.className="p-menu",j.setAttribute("role","menu"),j.setAttribute("aria-label","团队操作");let K=[];if(_.kind==="frame")K=[C(`解散团队「${i(_.name)}」`,!0,()=>e.emit({type:"remove-team",name:_.name}))];else{const fe=_.id;if(p==="root"){const q=C("组成团队…",n.selectedIds().length>=2,()=>u(r()));q.title="先框选或 Shift 加选至少 2 个节点",K.push(q);const de=((Me=n.getNode(fe))==null?void 0:Me.memberships.map(ee=>ee.team))??[];e.teams().length>0&&(K.push(C("加入团队 ▸",!0,()=>S(y,f,_,"join"))),de.length>0&&K.push(C("置顶路由 ▸",!0,()=>S(y,f,_,"promote")))),de.length>0&&K.push(C("离队 ▸",!0,()=>S(y,f,_,"leave"))),((D=n.getNode(fe))==null?void 0:D.remote)!==!0&&K.push(C("退网",!0,()=>e.emit({type:"leave-network",id:fe})))}else{K.push(C("‹ 返回",!0,()=>S(y,f,_,"root")));for(const q of e.teams())if(p==="join"){const de=((U=n.getNode(fe))==null?void 0:U.memberships.some(Ce=>Ce.team===q.name))??!0,ee=!e.isRoster(q.name)||e.joined(fe)&&((ce=n.getNode(fe))==null?void 0:ce.remote)!==!0,te=C(de?`${i(q.name)}(已加入)`:i(q.name),!de&&ee,()=>e.emit({type:"add-member",team:q.name,ids:[fe]}));ee||(te.title="roster 只接受本机已入网会话"),K.push(te)}else if(p==="leave"){const de=((Re=n.getNode(fe))==null?void 0:Re.memberships.some(ee=>ee.team===q.name))??!1;K.push(C(i(q.name),de,()=>e.emit({type:"remove-member",team:q.name,ids:[fe]})))}else{const de=((Ee=n.getNode(fe))==null?void 0:Ee.memberships.some(ee=>ee.team===q.name))??!1;if(e.isRoster(q.name))continue;K.push(C(i(q.name),de,()=>{const ee=n.teamMemberIds(q.name),te=[fe,...ee.filter(Ce=>Ce!==fe)];e.emit({type:"reorder",team:q.name,ops:vn(ee,te)})}))}if(p==="leave"){const q=new Set(e.teams().map(de=>de.name));for(const de of((le=n.getNode(fe))==null?void 0:le.memberships)??[])q.has(de.team)||K.push(C(i(de.team),!0,()=>e.emit({type:"remove-member",team:de.team,ids:[fe]})))}}}j.append(...K),j.style.left=`${Math.min(y,window.innerWidth-200)}px`;const we=K.length*30+8;j.style.top=`${Math.max(8,Math.min(f,window.innerHeight-we-8))}px`,j.addEventListener("keydown",fe=>{var te,Ce,Be,Ye;const q=fe,de=Array.from(j.querySelectorAll("[role=menuitem]")),ee=de.indexOf(document.activeElement);q.key==="ArrowDown"?(q.preventDefault(),(te=de[(ee+1+de.length)%de.length])==null||te.focus()):q.key==="ArrowUp"?(q.preventDefault(),(Ce=de[(ee-1+de.length)%de.length])==null||Ce.focus()):q.key==="Home"?(q.preventDefault(),(Be=de[0])==null||Be.focus()):q.key==="End"?(q.preventDefault(),(Ye=de[de.length-1])==null||Ye.focus()):q.key==="Escape"&&(q.preventDefault(),q.stopPropagation(),m!=="root"?S(y,f,_,"root"):M())}),t.appendChild(j),b=j,(He=K[0])==null||He.focus()}function E(y,f,_){if(l!==null)return;const p=(_==null?void 0:_.closest(".p-node"))??null;if(p!==null){const K=n.getNode(p.dataset.id??"");if((K==null?void 0:K.remote)===!0&&(K.remoteHandle===void 0||K.remoteHandle===""))return}const R=p,j=(_==null?void 0:_.closest(".p-frame-head"))??null;if(R!==null){const K=R.dataset.id??"";n.isSelected(K)||n.setSelection([K]),x=R,S(y,f,{kind:"node",id:K})}else j!==null&&(x=j,S(y,f,{kind:"frame",name:j.dataset.frame??""}))}function G(y){Y=y,o.textContent=`未入网${Y.length>0?`(${String(Y.length)})`:""}`,o.disabled=Y.length===0,o.setAttribute("aria-disabled",String(Y.length===0)),Y.length===0&&re()}return{menuItem:C,isMenuOpen:()=>b!==null,isDialogOpen:()=>l!==null,closeMenu:M,openMenu:S,contextMenuAt:E,openNameDialog:u,startCreateFromSelection:c,toggleNetMenu:V,setUnjoined:G}}function Hs(e,t){const o=t.trim().toLowerCase();return o===""?[]:e.filter(s=>s.name.toLowerCase().includes(o)||s.team.toLowerCase().includes(o)||(s.host??"").toLowerCase().includes(o)).slice(0,8)}function js(e,t){return e.allNodes().map(o=>{const s=o.id.slice(5),n=o.id.startsWith("member-")?o.name!==void 0&&o.name!==""?o.name:o.team:o.remote===!0?s:t(o);return{id:o.id,name:n,team:o.team,...o.remote===!0?{host:s}:{}}})}function Bs(e,t=1200){e!==void 0&&(e.classList.add("pulse"),setTimeout(()=>e.classList.remove("pulse"),t))}function Ys(e){return t=>{const o=e.model.getNode(t);if(o===void 0)return;const s=e.viewSize();e.setVp($n({minX:o.x,minY:o.y,maxX:o.x+Ue,maxY:o.y+De},s.w,s.h,1)),e.applyViewport(),e.markDirty(),Bs(e.cardEl(t))}}function Ws(e,t,o,s){const n=Xs({onPick:s});return e.appendChild(n.root),{...n,refresh:()=>n.setIndex(js(t,o))}}function Xs(e){const t=document.createElement("div");t.className="p-search";const o=document.createElement("input");o.type="search",o.className="p-search-input",o.placeholder="🔍 搜索(Ctrl+K)",o.title="搜索名字 / 句柄 / 宿主(Ctrl+K 聚焦,Esc 清空)",o.setAttribute("aria-label","搜索画板节点:名字、句柄或宿主");const s=document.createElement("div");s.className="p-search-list";let n=[],i=[],r=0;const c=()=>{s.style.display="none",s.textContent=""},l=()=>{if(s.textContent="",i.length===0){c();return}i.forEach((m,x)=>{const N=document.createElement("div");N.className="p-search-hit"+(x===r?" active":""),N.dataset.id=m.id,N.textContent=m.name===m.team?m.name:`${m.name} · ${m.team}`,N.addEventListener("mousedown",Y=>{Y.preventDefault(),e.onPick(m.id),u()}),s.appendChild(N)}),s.style.display="block"},u=()=>{o.value="",i=[],c()},b=()=>{i=Hs(n,o.value),r=0,l()};return o.addEventListener("input",b),o.addEventListener("keydown",m=>{if(m.key==="Escape"){u(),o.blur(),m.stopPropagation();return}if(m.key==="ArrowDown"||m.key==="ArrowUp"){if(i.length===0)return;m.preventDefault(),r=(r+(m.key==="ArrowDown"?1:i.length-1))%i.length,l();return}m.key==="Enter"&&i.length>0&&(m.preventDefault(),e.onPick(i[r].id),u())}),t.append(o,s),{root:t,setIndex(m){n=m,o.value!==""&&b()},focus(){o.focus(),o.select()},clear(){u()}}}const Ut=28,Gn=16,Qn=14,Zn=48,Ks=4,Us=180,qs=90,zs=1600;function Js(e){const t=e.wrapWidth??zs,o=e.frames.map(l=>{const u=Math.max(l.soleIds.length,1),b=Math.min(Ks,Math.max(1,Math.ceil(Math.sqrt(u)))),m=Math.ceil(u/b),x=Math.max(Us,Ut*2+b*Ue+(b-1)*Gn),N=Math.max(qs,Ut*2+m*De+(m-1)*Qn);return{name:l.name,w:x,h:N,rows:m,perRow:b,soleIds:l.soleIds}}),s=[],n=[];let i=0,r=0,c=0;for(const l of o){i>0&&i+l.w>t&&(i=0,r+=c+Zn,c=0);const u={x:i,y:r,w:l.w,h:l.h};s.push({name:l.name,rect:u});const b=u.x+Ut+Ue/2;let m=u.y+Ut+De/2;l.soleIds.forEach((x,N)=>{const Y=N%l.perRow;N>0&&Y===0&&(m+=De+Qn),n.push({id:x,x:b+Y*(Ue+Gn),y:m})}),i+=l.w+Zn,c=Math.max(c,l.h)}return{frames:s,seats:n}}function Vs(e,t){const o=[];for(const[n,i]of e.allFrames()){if(t.has(n))continue;const r=e.teamMemberIds(n).map(c=>e.getNode(c)).filter(c=>c!==void 0).filter(c=>c.memberships.length===1).map(c=>c.id);o.push({name:n,rect:i,soleIds:r})}if(o.length===0)return!1;const s=Js({frames:o});for(const n of s.frames)e.setFrame(n.name,n.rect);for(const n of s.seats){const i=e.getNode(n.id);i!==void 0&&e.dragNodes([n.id],n.x-i.x,n.y-i.y)}return!0}function Gs(e,t){if(e===void 0)return;const o=dt(e);return{text:t?`同步中… · ${o}`:`镜像 · ${o}`,title:t?`已把改动交给属主 ${o},等待它确认`:`这个团队属于 ${o},这里显示的是它的镜像;拖入或移出成员会经中继交给 ${o} 执行`,syncing:t}}const Qs=1e4;function Zs(e=Date.now){const t=(s,n)=>`${s}\0${n}`,o=new Map;return{fork(s,n){return o.set(t(n,s.name),{url:n,name:s.name}),{...s,fleetPeer:n}},settled(s,n){if(s.type!=="remove-team"||s.name===void 0||s.fleetPeer===void 0)return;const i=o.get(t(s.fleetPeer,s.name));i!==void 0&&(n?i.acceptedAt=e():o.delete(t(s.fleetPeer,s.name)))},hides(s,n){return o.has(t(n,s))},sweep(s){var n;for(const[i,r]of o)(!(((n=s.find(l=>l.url===r.url))==null?void 0:n.org.some(l=>l.name===r.name))===!0)||r.acceptedAt!==void 0&&e()-r.acceptedAt>Qs)&&o.delete(i)}}}const Ct=24,ei=200,Jt=(e,t)=>e.x<t.x+t.w&&t.x<e.x+e.w&&e.y<t.y+t.h&&t.y<e.y+e.h;function ti(e,t){const o=t.x+t.w+Ct-e.x,s=t.x-Ct-(e.x+e.w),n=t.y+t.h+Ct-e.y,i=t.y-Ct-(e.y+e.h),r=Math.abs(o)<=Math.abs(s)?o:s,c=Math.abs(n)<=Math.abs(i)?n:i;return Math.abs(r)<=Math.abs(c)?{dx:r,dy:0}:{dx:0,dy:c}}function ni(e,t,o,s){const n=e.beginFrameDrag(t);n!==void 0&&e.applyFrameDrag(n,o,s)}function oi(e,t,o){let s=!1;for(let n=0;n<ei;n++){const i=e.allFrames();let r;for(let M=0;M<i.length&&r===void 0;M++)for(let C=M+1;C<i.length;C++){const[S,E]=i[M],[G,y]=i[C];if(!(t.has(S)&&t.has(G))&&Jt(E,y)){r=[S,E,G,y];break}}if(r===void 0)return s;const[c,l,u,b]=r,m=M=>t.has(M)?2:M===o?1:0,[x,N,Y]=m(c)<m(u)?[c,l,b]:[u,b,l],{dx:re,dy:V}=ti(N,Y);ni(e,x,re,V),s=!0}return s}const gt=28,Vt=16,nn=14;function si(e){const t=[];for(let o=e.y+gt;o+De<=e.y+e.h-gt;o+=De+nn)for(let s=e.x+gt;s+Ue<=e.x+e.w-gt;s+=Ue+Vt)t.push({x:s+Ue/2,y:o+De/2});return t}function ii(e){let t=!1;const o=e.allFrames(),s=new Map(o);for(const n of e.allNodes()){const i=new Set(n.memberships.map(V=>V.team)),r=o.find(([V,M])=>!i.has(V)&&Jt(mt(n),M));if(r===void 0)continue;const c=r[1],l=V=>{const M=mt(V);return o.every(([C,S])=>i.has(C)||!Jt(M,S))&&e.allNodes().every(C=>C.id===n.id||!Jt(M,mt(C)))},b=n.memberships.map(V=>s.get(V.team)).filter(V=>V!==void 0).flatMap(si).find(l),m={x:c.x+c.w+Ct+Ue/2,y:n.y},x={x:n.x,y:c.y+c.h+Ct+De/2},N=Math.max(...o.map(([,V])=>V.x+V.w))+Ct+Ue/2,Y=Array.from({length:2*e.allNodes().length+1},(V,M)=>({x:N,y:c.y+De/2+M*(De+nn)})),re=b??[m,x,...Y].find(l)??Y[Y.length-1];e.dragNodes([n.id],re.x-n.x,re.y-n.y),t=!0}return t}function qt(e,t,o){const s=oi(e,t,o),n=ii(e);return s||n}function ri(e){for(const[t,o]of e.allFrames()){const s=e.teamMemberIds(t).map(u=>e.getNode(u)).filter(u=>u!==void 0).filter(u=>u.memberships.length===1);if(s.length===0)continue;const n=Math.max(1,Math.floor((o.w-2*gt+Vt)/(Ue+Vt))),i=Math.ceil(s.length/n),r=gt*2+i*De+(i-1)*nn;r>o.h&&e.setFrame(t,{...o,h:Math.min(r,o.h+400)});const c=o.x+gt+Ue/2;let l=o.y+gt+De/2;s.forEach((u,b)=>{const m=b%n;b>0&&m===0&&(l+=De+nn);const x=c+m*(Ue+Vt);e.dragNodes([u.id],x-u.x,l-u.y)})}}const ai=30;function ci(e){const t=[],o=()=>({nodes:new Map(e.allNodes().map(i=>[i.id,{x:i.x,y:i.y}])),frames:new Map(e.allFrames().map(([i,r])=>[i,{...r}]))}),s=i=>e.allNodes().some(r=>{const c=i.nodes.get(r.id);return c!==void 0&&(c.x!==r.x||c.y!==r.y)})||e.allFrames().some(([r,c])=>{const l=i.frames.get(r);return l!==void 0&&(l.x!==c.x||l.y!==c.y||l.w!==c.w||l.h!==c.h)}),n=i=>{for(const r of e.allNodes()){const c=i.nodes.get(r.id);c!==void 0&&(c.x!==r.x||c.y!==r.y)&&e.dragNodes([r.id],c.x-r.x,c.y-r.y)}for(const[r,c]of e.allFrames()){const l=i.frames.get(r);l!==void 0&&(l.x!==c.x||l.y!==c.y||l.w!==c.w||l.h!==c.h)&&e.setFrame(r,{...l})}};return{capture:o,commit(i){s(i)&&(t.push(i),t.length>ai&&t.shift())},undo(){const i=t.pop();return i===void 0?!1:(n(i),!0)},revert(i){return s(i)?(n(i),!0):!1},get depth(){return t.length}}}function li(e){const{root:t,trigger:o,signal:s,model:n}=e;let i=null,r="",c=null;function l(){c==null||c.remove(),c=null}function u(){l(),i==null||i.remove(),i=null}function b(){if(i!==null){u();return}const C=document.createElement("div");C.className="p-menu p-nodelist",C.setAttribute("role","dialog"),C.setAttribute("aria-label","节点清单"),i=C,t.appendChild(C);const S=o.getBoundingClientRect();C.style.left=`${String(Math.min(S.left,window.innerWidth-340))}px`,C.style.top=`${String(Math.max(8,S.top-320))}px`,C.addEventListener("keydown",E=>{E.key==="Escape"&&(E.stopPropagation(),u(),o.focus())}),m()}function m(){var _;const C=i;if(C===null)return;l(),C.textContent="";const S=document.createElement("div");S.className="p-nodelist-head";const E=document.createElement("span");E.className="p-nodelist-title",E.textContent="节点";const G=document.createElement("select");G.className="p-nodesel",G.setAttribute("aria-label","选择 host 或对等节点");const y=document.createElement("option");y.value="",y.textContent="本机",G.appendChild(y);for(const[p,R]of e.facts().remoteTeams){if(p==="")continue;const j=document.createElement("option");j.value=p,j.textContent=((_=R[0])==null?void 0:_.origin)!==void 0&&R[0].origin!==""?`${R[0].origin}(${p})`:p,G.appendChild(j)}r!==""&&!e.facts().remoteTeams.has(r)&&(r=""),G.value=r,G.addEventListener("change",()=>{r=G.value,m()}),S.append(E,G);const f=document.createElement("div");f.className="p-nodelist-body",C.append(S,f),r===""?V(f):M(f,e.facts().remoteTeams.get(r)??[])}function x(C,S){const E=document.createElement("span");return E.className="p-nodedot"+(S!==!0?" off":C===!1?" cold":""),E}function N(C,S){const E=document.createElement("button");return E.type="button",E.className="p-listbtn",E.textContent=C,E.addEventListener("click",G=>{G.stopPropagation(),S()}),E}function Y(C,S){const E=document.createElement("div");if(E.className="p-nodelist-group",E.textContent=C,S!==void 0){const G=document.createElement("span");G.className="p-nodelist-note",G.textContent=S,E.appendChild(G)}return E}function re(C,S){var y,f;l();const E=document.createElement("div");E.className="p-menu",E.setAttribute("role","menu"),E.setAttribute("aria-label","加入团队");for(const _ of e.facts().teams){const p=((y=n.getNode(S))==null?void 0:y.memberships.some(R=>R.team===_.name))??!1;E.appendChild(e.menuItem(p?`${_.name}(已加入)`:_.name,!p,()=>{u(),e.emit({type:"add-member",team:_.name,ids:[S]})}))}E.appendChild(e.menuItem("新团队…",!0,()=>{u(),e.openNameDialog([S])})),c=E,t.appendChild(E);const G=C.getBoundingClientRect();E.style.left=`${String(Math.min(G.right+4,window.innerWidth-180))}px`,E.style.top=`${String(Math.max(8,G.top-60))}px`,E.addEventListener("keydown",_=>{_.key==="Escape"&&(_.stopPropagation(),l(),C.focus())}),(f=E.querySelector("button"))==null||f.focus()}function V(C){var f,_;const S=new Set(e.facts().canvasMemberIds);for(const p of e.facts().sessions)p.teams!==void 0&&p.teams.length>0&&S.add(p.id);const E=e.facts().sessions.filter(p=>p.joined===!0&&!S.has(p.id)),G=e.facts().sessions.filter(p=>p.joined!==!0),y=e.facts().sessions.filter(p=>p.joined===!0&&S.has(p.id));C.appendChild(Y(`未组队 (${String(E.length)})`,"无网络能力"));for(const p of E){const R=document.createElement("div");R.className="p-noderow";const j=document.createElement("span");j.className="p-nodename",j.textContent=p.name!==void 0&&p.name!==""?p.name:p.label,j.title=p.team;const K=document.createElement("span");K.className="p-nonet",K.textContent="无网络能力";const we=N("入队▸",()=>re(we,p.id));R.append(x(p.live,!0),j,K,we,N("退网",()=>{u(),e.emit({type:"leave-network",id:p.id})})),C.appendChild(R)}C.appendChild(Y(`未入网 (${String(G.length)})`));for(const p of G){const R=document.createElement("div");R.className="p-noderow";const j=document.createElement("span");j.className="p-nodename",j.textContent=p.name!==void 0&&p.name!==""?p.name:p.label,j.title=p.id,R.append(x(p.live,!1),j,N("入网",()=>{u(),e.emit({type:"join-network",id:p.id})})),C.appendChild(R)}C.appendChild(Y(`已组队 (${String(y.length)})`,"画布展示"));for(const p of y){const R=document.createElement("div");R.className="p-noderow";const j=document.createElement("span");j.className="p-nodename",j.textContent=p.name!==void 0&&p.name!==""?p.name:p.label,j.title=p.team;const K=((f=n.getNode(p.id))==null?void 0:f.memberships.length)??0,we=((_=p.teams)==null?void 0:_.length)??0,Me=document.createElement("span");Me.className="p-teamcount",Me.textContent=`队×${String(Math.max(K,0)+we)}`,R.append(x(p.live,!0),j,Me,N("定位",()=>{e.locate(p.id)})),C.appendChild(R)}if(e.facts().sessions.length===0){const p=document.createElement("div");p.className="p-nodelist-empty",p.textContent="无会话节点",C.appendChild(p)}}function M(C,S){var y;const E=S.filter(f=>f.teams===void 0||f.teams.length===0),G=S.filter(f=>f.teams!==void 0&&f.teams.length>0);C.appendChild(Y(`未组队 (${String(E.length)})`,"无网络能力 · 只读"));for(const f of E){const _=document.createElement("div");_.className="p-noderow";const p=document.createElement("span");p.className="p-nodename",p.textContent=f.name!==void 0&&f.name!==""?f.name:f.team,p.title=f.team;const R=document.createElement("span");R.className="p-nonet",R.textContent="无网络能力",_.append(x(!0,!0),p,R),C.appendChild(_)}C.appendChild(Y(`已组队 (${String(G.length)})`,"只读"));for(const f of G){const _=document.createElement("div");_.className="p-noderow";const p=document.createElement("span");p.className="p-nodename",p.textContent=f.name!==void 0&&f.name!==""?f.name:f.team,p.title=f.team;const R=document.createElement("span");R.className="p-teamcount",R.textContent=`队×${String(((y=f.teams)==null?void 0:y.length)??0)}`,_.append(x(!0,!0),p,R),C.appendChild(_)}if(S.length===0){const f=document.createElement("div");f.className="p-nodelist-empty",f.textContent="该节点未发布会话",C.appendChild(f)}}return document.addEventListener("pointerdown",C=>{if(i===null)return;const S=C.target;if(S===null){u();return}S.closest(".p-nodelist")!==null||S.closest(".p-menu")!==null||S===o||o.contains(S)||u()},s),{toggle:b,close:u,refresh:()=>{i!==null&&m()}}}function di(e){let t=e;const o=t.search(/\|| ```|^```/);return o>=0&&(t=t.slice(0,o)),t.replace(/\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/(^|\s)#{1,6}\s+/g,"$1").replace(/\*\*|__|`/g,"").replace(/\s+/g," ").trim()}function mi(e,t){const o=e.map(i=>i.name!==void 0&&i.name!==""?i.name:i.team),s=o.slice(0,2).join("、"),n=o.length>2?` +${o.length-2}`:"";return(t!==void 0?`score ${t} · `:"")+`${e.length} 远端团队`+(s!==""?`:${s}${n}`:"")}function ui(e,t,o){if(e.id.startsWith("member-"))return{title:e.name!==void 0&&e.name!==""?e.name:e.team,sub:e.team,tip:e.team};if(e.remote===!0){const l=e.id.slice(5),u=t.length===1&&t[0].name!==void 0&&t[0].name!==""?t[0].name:void 0,b=mi(t,o);return u!==void 0?{title:u,sub:`${l} · ${b}`,tip:`${u}
|
|
6
|
+
${l}
|
|
7
|
+
${b}`}:{title:l,sub:b,tip:`${l}
|
|
8
|
+
${b}`}}const s=lt(e),n=e.team+(e.name!==void 0&&e.name!==""?" · "+e.name:""),i=di(e.description??""),r=i!==""?i:n===s?"":e.team,c=(e.memberships.length>1?` · 跨队×${e.memberships.length}`:"")+(e.teams!==void 0&&e.teams.length>0?` · 网络队×${e.teams.length}`:"");return{title:s,sub:r+c,tip:i!==""?`${n}
|
|
9
|
+
${i}`:n}}function fi(e){if((e==null?void 0:e.status)===void 0)return"";const t=e.status==="running"?"工作中":"空闲";return typeof e.queued=="number"&&e.queued>0?`${t} · 排队 ${String(e.queued)}`:t}function pi(e){const t=document.createElement("div");t.className="p-node",t.dataset.id=e,t.tabIndex=0;const o=document.createElement("div");o.className="nm";const s=document.createElement("span");s.className="dot";const n=document.createElement("span");n.className="nm-text",o.append(s,n);const i=document.createElement("div");i.className="sub mono";const r=document.createElement("span");r.className="prio mono";const c=document.createElement("span");c.className="work";const l=document.createElement("div");return l.className="sub-row",l.append(i,c),t.append(o,l,r),t}function hi(e,t,o){if(t.remote===!0){const s=(o==null?void 0:o.link)==="linked"?"lnk-linked":(o==null?void 0:o.link)==="stranger"?"lnk-stranger":"";e.className!==`prio mono ${s}`.trim()&&(e.className=`prio mono ${s}`.trim());const n=o===void 0?"":o.verified===!0?"✓":"✗",i=(t.id.startsWith("member-")?"成员":(o==null?void 0:o.link)??"peer")+n;e.textContent!==i&&(e.textContent=i)}else{e.className!=="prio mono"&&(e.className="prio mono");const s=t.memberships[0]!==void 0?`P${t.memberships[0].index}`:"";e.textContent!==s&&(e.textContent=s)}}const eo="dsh-a2a.board.legend";function bi(){const e=document.createElement("details");e.className="p-legend";const t=document.createElement("summary");t.textContent="图例",t.title="边的含义(点击展开 / 收起)";const o=document.createElement("div");o.className="p-legend-rows";const s=(n,i,r)=>{const c=document.createElement("span"),l=document.createElement("i");n&&(l.className="dashed"),r!==void 0&&(l.style.borderTopColor=r),c.append(l,document.createTextNode(i)),o.appendChild(c)};s(!1,"成员边(星形,框→成员)"),s(!0,"跨队多属(虚线)"),s(!0,"roster 网络队框(双线边框)"),s(!1,"活动边(inFlight 路由,瞬时)","var(--accent)"),s(!0,"联邦线(→peer)","var(--federal)"),e.append(t,o);try{e.open=window.localStorage.getItem(eo)==="open"}catch{}return e.addEventListener("toggle",()=>{try{window.localStorage.setItem(eo,e.open?"open":"closed")}catch{}}),e}const Gt="对端未应答(显示的是最后已知状态)";function to(e){const t=new Set;for(const s of e.remoteTeams??[])s.unreachable===!0&&s.via&&t.add(dt(s.via));for(const s of e.peerOrg??[])s.unreachable===!0&&t.add(dt(s.url));const o=new Set;for(const s of e.remoteTeams??[])s.via&&t.has(dt(s.via))&&o.add(`member-${s.team.replace(/[^a-z0-9-]/gi,"-")}`);return{hosts:t,members:o}}function gi(e,t){e.classList.toggle("is-unreachable",t);const o=e.querySelector(".p-frame-unreachable");if(t&&o===null){const s=document.createElement("span");s.className="p-frame-unreachable",s.textContent=Gt,e.appendChild(s)}else t||o==null||o.remove()}function vi(e){return e<680?"narrow":e<1024?"medium":"wide"}function yi(e){const t=new Nn;let o,s={...t.viewport},n={kind:"none"},i=!1,r=-1,c=!0,l=!1;const u=ci(t);let b,m=!1;const x=()=>vi(globalThis.innerWidth||qe),N=()=>{var a;(a=e.viewportStore)==null||a.set(x(),s),e.onDirty()},Y=e.now??Date.now,re=new AbortController,V=[];let M=null,C=!1;const S={signal:re.signal},E=document.createElement("section");E.id="dsh-plan",E.setAttribute("role","tabpanel"),E.setAttribute("aria-label","A2A 规划画布"),E.tabIndex=0,E.style.display="none";const G=document.createElement("div");G.className="p-grid";const y=document.createElement("div");y.className="p-world";const f=document.createElementNS("http://www.w3.org/2000/svg","svg");f.setAttribute("class","p-edges");const _=document.createElement("div");_.className="p-layer p-frames";let p;const R=a=>{var h,g;p!==void 0&&((h=Ie.get(p))==null||h.classList.remove("selected")),p=a,a!==void 0&&((g=Ie.get(a))==null||g.classList.add("selected"))},j=document.createElement("div");j.className="p-layer p-nodes",j.setAttribute("role","listbox"),j.setAttribute("aria-multiselectable","true"),j.setAttribute("aria-label","会话节点"),y.append(f,_,j);const K=document.createElement("div");K.className="p-marquee";const we=document.createElement("div");we.className="p-toolbar";const Me=document.createElement("span");Me.className="p-zoom mono",Me.textContent="100%";const D=(a,h,g)=>{const F=document.createElement("button");return F.type="button",F.textContent=a,F.title=h,F.addEventListener("click",g,S),F},U=()=>{const a=document.createElement("span");return a.className="p-sep",a.setAttribute("role","separator"),a.setAttribute("aria-orientation","vertical"),a};we.append(D("适配","适配视图(快捷键 0)",()=>it()),D("-","缩小",()=>pe(1/1.2)),Me,D("+","放大",()=>pe(1.2)),U(),D("建队","组成团队(G):先框选至少 2 个节点",()=>O.startCreateFromSelection()),D("整理成员","每队框内仅属一队的成员自动排齐(多队成员不动)",()=>vt()),D("一键重排","全板队框+成员重排:框尺寸随内容自适应、框位行流式平铺(远端队框与多归属成员不动)",()=>St()),D("撤销","撤销上一次布局改动:拖动、缩放、整理、重排、载入时避让(Ctrl+Z;入队离队不撤销)",()=>Oe()));const ce=D("未入网","未入网会话(点击选择入网)",()=>O.toggleNetMenu());ce.className="p-netbtn",ce.setAttribute("aria-haspopup","menu"),we.append(U(),ce);const Re=Ws(we,t,lt,a=>ne(a)),Ee=D("节点","节点清单:本机与对等节点(未组队/未入网在此管理)",()=>Z.toggle());Ee.className="p-nodebtn",Ee.setAttribute("aria-haspopup","dialog"),we.appendChild(Ee);const le=document.createElement("span");le.setAttribute("aria-live","polite"),le.className="p-lamp";const He=document.createElement("i"),fe=document.createElement("span");fe.textContent="布局",le.append(He,fe),le.addEventListener("click",()=>{le.classList.contains("error")&&e.onLampClick()},S),le.addEventListener("keydown",a=>{const h=a;(h.key==="Enter"||h.key===" ")&&le.classList.contains("error")&&(h.preventDefault(),e.onLampClick())},S),we.appendChild(le);const q=document.createElement("div");q.className="p-status";const de=document.createElement("span"),ee=document.createElement("span"),te=document.createElement("span");te.className="mut";const Ce=document.createElement("span");Ce.className="mut",q.append(de,ee,te,Ce),q.tabIndex=0,q.setAttribute("role","button"),q.setAttribute("aria-label","定位在途路由与联邦对端"),q.title="定位在途与联邦(回车)",q.addEventListener("click",()=>ve(),S),q.addEventListener("keydown",a=>{const h=a;(h.key==="Enter"||h.key===" ")&&(h.preventDefault(),ve())},S);const Be=bi(),Ye=document.createElement("div");Ye.className="p-notice-stack",Ye.setAttribute("role","log"),Ye.setAttribute("aria-live","polite"),E.append(G,y,K,we,q,Be,Ye);let qe=0,ut=0;const kt=()=>e.viewSize?e.viewSize():{w:E.clientWidth,h:E.clientHeight},Je=()=>{const a=kt();qe=a.w,ut=a.h};function Qe(){y.style.transform=_s(s);const a=24*s.scale;G.style.backgroundSize=`${a}px ${a}px`,G.style.backgroundPosition=`${-s.x*s.scale}px ${-s.y*s.scale}px`,Me.textContent=`${Math.round(s.scale*100)}%`}function vt(){const a=u.capture();ri(t),qt(t,new Set(nt.keys())),u.commit(a),N(),Se()}function St(){const a=u.capture();Vs(t,new Set(nt.keys()))&&(qt(t,new Set(nt.keys())),u.commit(a),N(),Se())}function Se(){Qe(),t.revision!==r&&(r=t.revision,ft(),At(),ps(f,t)),ge()}const Ie=new Map,tt=new Map;function ft(){var h;const a=new Set;for(const[g,F]of t.allFrames()){a.add(g);let P=Ie.get(g);if(P===void 0){P=document.createElement("div"),P.className="p-frame",P.dataset.name=g;const oe=document.createElement("div");oe.className="p-frame-head",oe.dataset.frame=g,oe.tabIndex=0,oe.setAttribute("role","button"),oe.setAttribute("aria-haspopup","menu"),oe.setAttribute("aria-label",`团队框 ${g}(拖动整组,回车菜单)`);const Fe=document.createElement("span");Fe.className="ttl";const Ge=document.createElement("span");Ge.className="cnt mono";const rt=document.createElement("span");rt.className="route mono",oe.append(Fe,Ge,rt),P.appendChild(oe);for(const yt of["n","s","e","w","ne","nw","se","sw"]){const wt=document.createElement("div");wt.className=`p-frame-handle p-h-${yt}`,wt.dataset.frame=g,wt.dataset.dir=yt,P.appendChild(wt)}_.appendChild(P),Ie.set(g,P)}const ue=Ps(g);P.style.setProperty("--frame-line",ue.line),P.style.setProperty("--frame-bg",ue.bg),P.style.left=`${F.x}px`,P.style.top=`${F.y}px`,P.style.width=`${F.w}px`,P.style.height=`${F.h}px`;const W=P.querySelector(".ttl"),B=P.querySelector(".cnt"),z=P.querySelector(".route"),ie=k.has(g),Ae=ie?tn(g):g;W.textContent!==Ae&&(W.textContent=Ae),P.classList.toggle("is-roster",ie);let Le=0,Ne=0;for(const oe of t.allNodes())oe.memberships.find(Ge=>Ge.team===g)!==void 0&&(Le+=1,oe.memberships.length>1&&(Ne+=1));const Ke=`${Le} 成员`+(Ne>0?` +${Ne} 跨队`:"");B.textContent!==Ke&&(B.textContent=Ke);const v=Gs(nt.get(g),Te.has(g)),be=v!==void 0&&w.hosts.has(dt(nt.get(g))),he=(v==null?void 0:v.text)??((h=Ht.find(oe=>oe.name===g))==null?void 0:h.team)??g;z.textContent!==he&&(z.textContent=he),z.title=`${(v==null?void 0:v.title)??""}${be?` · ${Gt}`:""}`,gi(P,be),P.classList.toggle("is-mirror",v!==void 0),P.classList.toggle("is-syncing",(v==null?void 0:v.syncing)===!0);const je=`团队框 ${g}${v!==void 0?`(${v.text})`:""}${be?`(${Gt})`:""}(拖动整组,回车菜单)`,$e=P.querySelector(".p-frame-head");$e.getAttribute("aria-label")!==je&&$e.setAttribute("aria-label",je)}for(const[g,F]of[...Ie])a.has(g)||(F.remove(),Ie.delete(g))}function At(){const a=new Set;for(const h of t.allNodes()){a.add(h.id);let g=tt.get(h.id);g===void 0&&(g=pi(h.id),j.appendChild(g),tt.set(h.id,g));const F=mt(h);g.style.left=`${F.x}px`,g.style.top=`${F.y}px`,g.classList.toggle("cold",!h.live),g.classList.toggle("remote",h.remote===!0);const P=h.live&&h.remote!==!0?I.get(h.id):void 0;g.classList.toggle("is-working",(P==null?void 0:P.status)==="running");const ue=fi(P),W=g.querySelector(".work");W.textContent!==ue&&(W.textContent=ue),g.classList.toggle("selected",t.isSelected(h.id)),g.setAttribute("aria-selected",String(t.isSelected(h.id)));const B=h.id.slice(5),z=ui(h,h.remote===!0?A.get(B)??[]:[],Q.get(B)),ie=h.remote===!0&&(h.id.startsWith("member-")?w.members.has(h.id):w.hosts.has(B));g.classList.toggle("is-unreachable",ie);const Ae=g.querySelector(".nm-text");Ae.textContent!==z.title&&(Ae.textContent=z.title);const Le=g.querySelector(".sub"),Ne=ie?`未应答 · ${z.sub}`:z.sub;Le.textContent!==Ne&&(Le.textContent=Ne);const Ke=ie?`${z.tip} · ${Gt}`:z.tip;g.title!==Ke&&(g.title=Ke);const v=h.id.startsWith("member-")?me.get(h.remoteHandle??""):B;hi(g.querySelector(".prio"),h,h.remote===!0&&v!==void 0?X.get(v):void 0)}for(const[h,g]of[...tt])a.has(h)||(g.remove(),tt.delete(h));Re.refresh()}const d=$s(f,t);let A=new Map,I=new Map;const Q=new Map,X=new Map;let me=new Map;function ge(){d.render(Y())}function ve(){s=$n(Es(t.contentBounds(),d.placements()),E.clientWidth||qe,E.clientHeight||ut),Qe(),N()}const ne=Ys({model:t,viewSize:kt,setVp:a=>{s=a},applyViewport:Qe,markDirty:N,cardEl:a=>tt.get(a)});function We(a){var F;const h=a.sessions.filter(P=>P.live!==!1).length,g=(P,ue,W)=>{const B=document.createElement("b");B.className=ue,B.textContent=W,P.replaceChildren(B)};g(de,"ok",`● ${h} live`),g(ee,"warn",`● ${a.sessions.length-h} cold`),te.textContent=`${((F=a.inFlight)==null?void 0:F.length)??0} inFlight`,Ce.className="mut",Ce.textContent=`${a.teams.length} 队 · ${a.peerCount} peer`}const Te=new Map,Xe=a=>{Te.set(a,(Te.get(a)??0)+1),r=-1},Lt=a=>{r=-1;const h=(Te.get(a)??0)-1;h<=0?Te.delete(a):Te.set(a,h)};let nt=new Map,k=new Set,w=to({});const H=Zs(e.now);function $(a){const h=a.type==="create-team"&&a.roster===!0||k.has(Rt(a));if(h&&a.type==="remove-team"&&!window.confirm(`解散网络队「${tn(a.name)}」并撤回成员与白名单?`))return;if(h&&a.type==="reorder"){L("error","roster 队不支持置顶路由");return}if(h&&(a.type==="create-team"||a.type==="add-member")&&a.ids.some(W=>{var B;return((B=t.getNode(W))==null?void 0:B.remote)===!0||!se.some(z=>z.id===W&&z.joined===!0)})){L("error","roster 只接受本机已入网会话,远端或未入网成员未写入");return}function g(W){const B=z=>{var Ae;const ie=[];for(const Le of z){if(!Le.startsWith("peer-")&&!Le.startsWith("member-")){ie.push(Le);continue}const Ne=(Ae=t.getNode(Le))==null?void 0:Ae.remoteHandle;Ne!==void 0&&Ne!==""&&ie.push(Ne)}return ie};if(W.type==="add-member"||W.type==="remove-member"||W.type==="create-team"){const z=B(W.ids),ie=W.type!=="create-team"?nt.get(W.team):void 0;return z.length>0||ie!==void 0?{...W,ids:z,...ie!==void 0?{fleetPeer:ie}:{}}:W}return W.type==="remove-team"&&nt.has(W.name)?H.fork(W,nt.get(W.name)):W}if(a.type==="add-member"||a.type==="remove-member"||a.type==="reorder"||a.type==="create-team"){const W=a.type==="reorder"?a.ops.map(B=>B.id):[...a.ids];for(const B of W){if(B===""||B.startsWith("peer-")||B.startsWith("member-")||t.getNode(B)!==void 0)continue;const z=se.find(Le=>Le.id===B);if(z===void 0)continue;const ie=o==null?void 0:o.nodes[B],Ae=ie!==void 0?{x:ie.x,y:ie.y}:Sn(B);t.upsertNode({id:B,x:Ae.x,y:Ae.y,label:z.label,team:z.team,name:z.name,description:z.description,live:z.live!==!1,memberships:[],...z.teams!==void 0&&z.teams.length>0?{teams:z.teams}:{}})}}h&&a.type==="create-team"&&k.add(a.name);const F=Os(t,a),P=Rt(a);Xe(P),Se();const ue=g(h?{...a,roster:!0}:a);e.onCanvasAction(ue).then(W=>{Lt(P),!W&&a.type==="create-team"&&h&&k.delete(P),o=Jn(t,a,W,F,o),N(),H.settled(ue,W),Se()},()=>{Lt(P),a.type==="create-team"&&h&&k.delete(P),o=Jn(t,a,!1,F,o),N(),H.settled(ue,!1),L("error","操作通道异常,已回滚"),Se()})}function L(a,h){var F;for(;Ye.childElementCount>=3;)(F=Ye.firstElementChild)==null||F.remove();const g=document.createElement("div");g.className="p-notice"+(a==="error"?" error":""),g.setAttribute("role",a==="error"?"alert":"status"),g.textContent=h,Ye.appendChild(g),V.push(setTimeout(()=>g.remove(),4e3))}const O=Rs({root:E,netBtn:ce,signal:S,model:t,teams:()=>Ht,joined:a=>se.some(h=>h.id===a&&h.joined===!0),isRoster:a=>k.has(a),anchorFor:a=>(a.kind==="node"?tt.get(a.id):Ie.get(a.name))??null,emit:$,notice:L});let se=[],ae=new Set;const Z=li({root:E,trigger:Ee,signal:S,model:t,facts:()=>({sessions:se,canvasMemberIds:ae,remoteTeams:A,teams:Ht}),menuItem:O.menuItem,emit:$,openNameDialog:O.openNameDialog,locate:xe});zo(E,{signal:S,frames:()=>Ie,frameAt:(a,h)=>{const g=_e({clientX:a,clientY:h});return Kt(new Map(t.allFrames()),ct(s,g.x,g.y))},drop:(a,h)=>{var g;return((g=t.getNode(h))==null?void 0:g.memberships.some(F=>F.team===a))===!0?L("info","该会话已在这个队里"):$({type:"add-member",team:a,ids:[h]})}});function xe(a){var F;const h=t.getNode(a);if(h===void 0)return;Z.close();const g=((F=e.viewSize)==null?void 0:F.call(e))??{w:E.clientWidth>0?E.clientWidth:800,h:E.clientHeight>0?E.clientHeight:600};s=Nt({scale:s.scale,x:h.x-g.w/(2*s.scale),y:h.y-g.h/(2*s.scale)}),Qe(),r=-1,Se()}function _e(a){const h=E.getBoundingClientRect();return{x:a.clientX-h.left,y:a.clientY-h.top}}function J(a,h){var W;const g=_e(h),F=ct(s,g.x,g.y),P=Kt(new Map(t.allFrames()),F),ue=a.ids.filter(B=>{const z=t.getNode(B);return z===void 0?!1:z.remote!==!0?!0:z.remoteHandle!==void 0&&z.remoteHandle!==""});if(P!==void 0){const B=ue.filter(z=>{var ie;return!((ie=t.getNode(z))!=null&&ie.memberships.some(Ae=>Ae.team===P))});if(B.length>0){$({type:"add-member",team:P,ids:B});return}if(a.ids.length===1&&((W=t.getNode(a.clicked))==null?void 0:W.remote)!==!0){const z=t.teamMemberIds(P),ie=Fs(t,P);ie.join("\0")!==z.join("\0")&&$({type:"reorder",team:P,ops:vn(z,ie)})}}if(a.rosterOrigin!==void 0&&P!==a.rosterOrigin){const B=a.ids.filter(z=>t.teamMemberIds(a.rosterOrigin).includes(z));B.length>0&&$({type:"remove-member",team:a.rosterOrigin,ids:B})}}function Pe(a){if(qe===0&&Je(),O.isDialogOpen()){a.preventDefault();return}const h=a.target;if(O.isMenuOpen()){if(h!==null&&h.closest(".p-menu")!==null)return;O.closeMenu(),a.preventDefault();return}if(h!==null&&h.closest("button, input, textarea, select, .p-toolbar, .p-search, .p-lamp, .p-status, .p-legend")!==null)return;b=u.capture();const g=_e(a);if(a.button===2){M={x:g.x,y:g.y,target:a.target,moved:!1},a.preventDefault();try{E.setPointerCapture(a.pointerId??0)}catch{}return}const F=h!==null?h.closest(".p-node"):null,P=h!==null?h.closest(".p-frame-head"):null;if((F!==null||P!==null)&&a.button===1){n={kind:"pan",last:g,moved:!1},a.preventDefault();try{E.setPointerCapture(a.pointerId??0)}catch{}return}const ue=h!==null?h.closest(".p-frame-handle"):null;if(p!==void 0){const W=Ie.get(p),B=h!==null&&W!==void 0&&(W.contains(h)||W===h),z=P!==null&&P.dataset.frame===p;!B&&!z&&R(void 0)}if(ue!==null&&a.button===0){const W=ue.dataset.frame??"";R(W);const B=t.getFrame(W);if(B===void 0)return;n={kind:"frame-resize",name:W,dir:ue.dataset.dir??"se",startRect:{...B},origin:ct(s,g.x,g.y),moved:!1},a.preventDefault();try{E.setPointerCapture(a.pointerId??0)}catch{}return}if(F!==null){if(a.button!==0)return;const W=F.dataset.id??"",B=t.isSelected(W);!B&&!a.shiftKey&&t.setSelection([W]);const z=a.shiftKey||B?t.isSelected(W)?t.selectedIds():[...t.selectedIds(),W]:[W],ie=Kt(new Map(t.allFrames()),ct(s,g.x,g.y));n={kind:"node",clicked:W,ids:z,...ie&&k.has(ie)&&t.teamMemberIds(ie).includes(W)?{rosterOrigin:ie}:{},last:ct(s,g.x,g.y),moved:!1,el:F},F.classList.add("dragging")}else if(P!==null){if(a.button!==0)return;const W=P.dataset.frame??"";R(W);const B=t.beginFrameDrag(W);if(B===void 0)return;n={kind:"frame",name:W,snap:B,origin:ct(s,g.x,g.y),moved:!1}}else if(a.button===1||a.button===0&&i)n={kind:"pan",last:g,moved:!1};else if(a.button===0)n={kind:"marquee",origin:g,last:g,additive:a.shiftKey},K.style.display="block",K.style.left=`${g.x}px`,K.style.top=`${g.y}px`,K.style.width="0px",K.style.height="0px";else return;a.preventDefault();try{E.setPointerCapture(a.pointerId??0)}catch{}}function Ze(a){const h=_e(a);if(M!==null){const g=h.x-M.x,F=h.y-M.y;Math.hypot(g,F)>4&&(M.moved=!0,s=Nt(un(s,-g,-F)),M.x=h.x,M.y=h.y,Qe());return}if(n.kind==="node"){const g=ct(s,h.x,h.y),F=g.x-n.last.x,P=g.y-n.last.y;if(F===0&&P===0)return;n.moved=!0,n.last=g,t.dragNodes(n.ids,F,P);const ue=Kt(new Map(t.allFrames()),g),W=n.ids.filter(z=>{const ie=t.getNode(z);return ie===void 0?!1:ie.remote!==!0||ie.remoteHandle!==void 0&&ie.remoteHandle!==""}),B=ue!==void 0&&W.length>0;for(const[z,ie]of Ie)ie.classList.toggle("drop-target",B&&z===ue);Se()}else if(n.kind==="frame"){const g=ct(s,h.x,h.y),F=g.x-n.origin.x,P=g.y-n.origin.y;if(!n.moved&&F===0&&P===0)return;n.moved=!0,t.applyFrameDrag(n.snap,F,P),Se()}else if(n.kind==="frame-resize"){const g=ct(s,h.x,h.y),F=g.x-n.origin.x,P=g.y-n.origin.y;if(!n.moved&&F===0&&P===0)return;n.moved=!0;const ue=220,W=120,B={...n.startRect};let{x:z,y:ie,w:Ae,h:Le}=B;n.dir.includes("e")&&(Ae=Math.max(ue,B.w+F)),n.dir.includes("s")&&(Le=Math.max(W,B.h+P)),n.dir.includes("w")&&(Ae=Math.max(ue,B.w-F),z=B.x+(B.w-Ae)),n.dir.includes("n")&&(Le=Math.max(W,B.h-P),ie=B.y+(B.h-Le)),t.setFrame(n.name,{x:Math.round(z),y:Math.round(ie),w:Math.round(Ae),h:Math.round(Le)}),Se()}else if(n.kind==="pan")s=un(s,h.x-n.last.x,h.y-n.last.y),n.last=h,n.moved=!0,Qe();else if(n.kind==="marquee"){const g=Math.min(n.origin.x,h.x),F=Math.min(n.origin.y,h.y);K.style.left=`${g}px`,K.style.top=`${F}px`,K.style.width=`${Math.abs(h.x-n.origin.x)}px`,K.style.height=`${Math.abs(h.y-n.origin.y)}px`,n.last=h}}function et(a){var h,g;if(M!==null){const F=M.moved,P=M.target,ue=M.x,W=M.y;M=null,F?(C=!0,N()):P!==null&&O.contextMenuAt(ue,W,P);return}if(n.kind==="node"){const F=n.clicked;if(n.moved)J(n,a),N();else if(a.shiftKey){const P=t.selectedIds();t.setSelection(P.includes(F)?P.filter(ue=>ue!==F):[...P,F])}else t.setSelection([F]),(h=e.onNodePick)==null||h.call(e,F);for(const P of Ie.values())P.classList.remove("drop-target");(g=n.el)==null||g.classList.remove("dragging"),Se()}else if(n.kind==="frame"||n.kind==="frame-resize")n.moved&&(qt(t,new Set(nt.keys()),n.name),N(),Se());else if(n.kind==="pan")n.moved&&N();else if(n.kind==="marquee"){const F=n.last,P=ct(s,Math.min(n.origin.x,F.x),Math.min(n.origin.y,F.y)),ue=ct(s,Math.max(n.origin.x,F.x),Math.max(n.origin.y,F.y));t.marqueeSelect({x:P.x,y:P.y,w:ue.x-P.x,h:ue.y-P.y},n.additive),K.style.display="none",Se()}n={kind:"none"},b!==void 0&&(u.commit(b),b=void 0);try{E.releasePointerCapture(a.pointerId??0)}catch{}}function pt(a){var g;for(const F of Ie.values())F.classList.remove("drop-target");n.kind==="node"&&((g=n.el)==null||g.classList.remove("dragging"));const h=n.kind==="pan"&&n.moved||(M==null?void 0:M.moved)===!0;K.style.display="none",M=null,n={kind:"none"},b!==void 0&&u.revert(b)&&Se(),h&&N(),b=void 0;try{E.releasePointerCapture(a.pointerId??0)}catch{}}function Ve(a){O.isMenuOpen()&&O.closeMenu();const h=_e(a);if(a.shiftKey&&!a.ctrlKey){const g=a.deltaMode===1?16:1;s=Nt(un(s,(a.deltaX??0)*g,(a.deltaY??0)*g))}else{const g=a.deltaMode===1?16:1,F=Math.exp(-((a.deltaY??0)*g)*.0015);s=Xn(s,F,h.x,h.y)}a.preventDefault(),Qe(),N()}function pe(a){Je(),s=Xn(s,a,qe/2,ut/2),Qe(),N()}function Oe(){u.undo()?(N(),Se()):L("info","没有可撤销的布局改动")}function it(){Je(),s=qn(Un(t.contentBounds(),t.allNodes()),qe,ut,zn(we,q)),Qe(),N()}function It(a){var ue,W,B,z,ie,Ae,Le;if(O.isDialogOpen()||((W=(ue=a.target)==null?void 0:ue.closest)==null?void 0:W.call(ue,".p-search"))!==null)return;if((a.ctrlKey||a.metaKey)&&a.key.toLowerCase()==="k"){a.preventDefault(),Re.focus();return}if((a.ctrlKey||a.metaKey)&&!a.shiftKey&&a.key.toLowerCase()==="z"){a.preventDefault(),Oe();return}if(a.ctrlKey||a.metaKey)return;if(O.isMenuOpen()){a.key==="Escape"&&(O.closeMenu(),a.preventDefault());return}if(a.key===" "&&a.target===E){i=!0,a.preventDefault();return}const h=((z=(B=a.target)==null?void 0:B.closest)==null?void 0:z.call(B,".p-frame-head"))??null;if((a.key==="Enter"||a.key===" ")&&h!==null){a.preventDefault();const Ne=h.getBoundingClientRect();O.contextMenuAt(Ne.left+Ne.width/2,Ne.top+Ne.height/2,h);return}if(a.key===" "&&((Ae=(ie=a.target)==null?void 0:ie.classList)!=null&&Ae.contains("p-node"))){const Ke=a.target.dataset.id??"",v=t.selectedIds();t.setSelection(v.includes(Ke)?v.filter(be=>be!==Ke):[...v,Ke]),Se(),a.preventDefault();return}if(a.key==="F10"&&a.shiftKey||a.key==="ContextMenu"){a.preventDefault();const Ne=document.activeElement??null,Ke=((Le=Ne==null?void 0:Ne.getBoundingClientRect)==null?void 0:Le.call(Ne))??{left:0,top:0,width:0,height:0};O.contextMenuAt(Ke.left+Ke.width/2,Ke.top+Ke.height/2,Ne);return}if(a.key==="Delete"||a.key==="Backspace"){a.preventDefault(),cn();return}if(a.altKey&&(a.key==="ArrowUp"||a.key==="ArrowDown")){a.preventDefault(),ko(a.key==="ArrowUp");return}if(a.key==="g"||a.key==="G"){O.startCreateFromSelection();return}if(a.key==="0"){it();return}if(a.key==="="||a.key==="+"){pe(1.2);return}if(a.key==="-"){pe(1/1.2);return}if(a.key==="Escape"){if(O.isMenuOpen()){O.closeMenu(),Se();return}t.setSelection([]),Se();return}const g=a.shiftKey?40:8,P={ArrowLeft:[-g,0],ArrowRight:[g,0],ArrowUp:[0,-g],ArrowDown:[0,g]}[a.key];if(P!==void 0){a.preventDefault();const Ne=t.selectedIds();if(Ne.length>0){const Ke=u.capture();t.nudge(Ne,P[0],P[1]),u.commit(Ke),Se(),N()}}}function cn(){var F,P,ue;const a=document.activeElement,h=((F=a==null?void 0:a.closest)==null?void 0:F.call(a,".p-frame-head"))??null,g=((P=a==null?void 0:a.closest)==null?void 0:P.call(a,".p-node"))??null;if(h!==null){$({type:"remove-team",name:h.dataset.frame??""});return}if(g!==null){const W=g.dataset.id??"",B=((ue=t.getNode(W))==null?void 0:ue.memberships.map(z=>z.team))??[];if(B.length===0){L("info","该节点未加入任何团队");return}if(B.length===1){$({type:"remove-member",team:B[0],ids:[W]});return}O.openMenu(window.innerWidth/2,window.innerHeight/2,{kind:"node",id:W},"leave",g);return}L("info","焦点不在节点或团队框上")}function ko(a){var Ae,Le;const h=document.activeElement,g=((Ae=h==null?void 0:h.closest)==null?void 0:Ae.call(h,".p-node"))??null;if(g===null)return;const F=g.dataset.id??"",P=((Le=t.getNode(F))==null?void 0:Le.memberships)??[];if(P.length!==1)return;const ue=P[0].team,W=t.teamMemberIds(ue),B=W.indexOf(F),z=a?Math.max(0,B-1):Math.min(W.length-1,B+1);if(z===B)return;const ie=[...W];ie.splice(B,1),ie.splice(z,0,F),$({type:"reorder",team:ue,ops:vn(W,ie)})}function Mn(a){a.key===" "&&(i=!1)}E.addEventListener("pointerdown",a=>Pe(a),S),E.addEventListener("pointermove",a=>Ze(a),S),E.addEventListener("pointerup",a=>et(a),S),E.addEventListener("pointercancel",a=>pt(a),S),E.addEventListener("wheel",a=>Ve(a),{...S,passive:!1}),E.addEventListener("keydown",a=>It(a),S),E.addEventListener("keyup",a=>Mn(a),S),E.addEventListener("contextmenu",a=>{var g,F;const h=a;if(((F=(g=h.target)==null?void 0:g.closest)==null?void 0:F.call(g,"input, textarea, .p-search"))==null){if(h.preventDefault(),C){C=!1;return}O.contextMenuAt(h.clientX,h.clientY,h.target)}},S);let Ht=[];function Eo(a){var Ke;Ht=a.teams,k=new Set([...a.teams.filter(v=>v.kind==="roster").map(v=>v.name),...[...k].filter(v=>Te.has(v))]),a.peers,d.setInFlight(a.inFlight??[]),se=a.sessions,O.setUnjoined(a.sessions.filter(v=>v.joined!==!0&&!v.id.startsWith("peer-")));const h=Ss(a.teams);ae=new Set(h.keys());const g=new Set,F=v=>{const be=h.get(v)??[];if(Te.size===0)return be;const he=be.filter($e=>!Te.has($e.team)),je=[];for(const[$e]of Te){const Fe=t.teamMemberIds($e).indexOf(v);Fe>=0&&je.push({team:$e,index:Fe})}return[...he,...je]};let P;if(o===void 0&&!t.allNodes().some(v=>v.remote!==!0)){const v=a.sessions.filter(be=>{var he;return be.joined===!0&&(F(be.id).length>0||(((he=be.teams)==null?void 0:he.length)??0)>0)}).map(be=>be.id);Je(),P=ds(a.teams,v,qe>0?qe:void 0)}const ue=a.peerOrg!==void 0?As(a.peerOrg,a.sessions,a.remoteTeams):new Set;a.peerOrg!==void 0&&(ae=new Set([...ae,...ue]));for(const v of a.sessions){if(v.joined!==!0)continue;const be=F(v.id);if(!(be.length===0&&(v.teams===void 0||v.teams.length===0)&&!ue.has(v.id)))if(g.add(v.id),t.getNode(v.id)!==void 0)t.upsertNode({id:v.id,x:t.getNode(v.id).x,y:t.getNode(v.id).y,label:v.label,team:v.team,name:v.name,description:v.description,live:v.live!==!1,memberships:be,...v.teams!==void 0&&v.teams.length>0?{teams:v.teams}:{}});else{const he=o==null?void 0:o.nodes[v.id];let je,$e;if(he!==void 0)je=he.x,$e=he.y;else{const oe=(P==null?void 0:P.get(v.id))??Sn(v.id);je=oe.x,$e=oe.y}t.upsertNode({id:v.id,x:je,y:$e,label:v.label,team:v.team,name:v.name,description:v.description,live:v.live!==!1,memberships:be,...v.teams!==void 0&&v.teams.length>0?{teams:v.teams}:{}})}}for(const v of t.nodeIds())!g.has(v)&&!v.startsWith("peer-")&&!v.startsWith("member-")&&t.removeNode(v);const W=new Set;A=bs(a.remoteTeams??[]),me=new Map([...A].flatMap(([v,be])=>be.map(he=>[he.team,v]))),I=new Map(a.sessions.map(v=>[v.id,{status:v.status,queued:v.queued}])),w=to(a),Q.clear();for(const v of a.peers??[])Q.set(dt(v.url),v.score),X.set(dt(v.url),{link:v.link,verified:v.verified});if(a.peers!==void 0){const v=t.contentBounds(),be=xs(a.peers,v);a.peers.forEach((he,je)=>{var wt,An,Ln,In;const $e=hs(he.url);W.add($e);const oe=o==null?void 0:o.nodes[$e],Fe=t.getNode($e),Ge=Fe!==void 0?{x:Fe.x,y:Fe.y}:oe!==void 0?{x:oe.x,y:oe.y}:{x:((wt=be[je])==null?void 0:wt.x)??200,y:((An=be[je])==null?void 0:An.y)??0},rt=dt(he.url),yt=(In=(Ln=A.get(rt))==null?void 0:Ln.find(Io=>Io.team.includes("/")))==null?void 0:In.team;t.upsertNode({id:$e,x:Ge.x,y:Ge.y,label:he.url,team:"",name:he.url,peerUrl:he.url,remoteHandle:yt,live:!0,remote:!0,memberships:[]}),t.upsertScore($e,he.score)})}for(const v of t.nodeIds())v.startsWith("peer-")&&!W.has(v)&&t.removeNode(v);const B=new Set;for(const[v,be]of A){const he=t.allNodes().find(oe=>oe.remote===!0&&dt(oe.peerUrl??"")===v&&!oe.id.startsWith("member-")),je=((he==null?void 0:he.x)??400)+190;let $e=(he==null?void 0:he.y)??0;for(const oe of be){if(!oe.team.includes("/"))continue;const Fe=`member-${oe.team.replace(/[^a-z0-9-]/gi,"-")}`;if(B.has(Fe))continue;B.add(Fe);const Ge=o==null?void 0:o.nodes[Fe],rt=t.getNode(Fe),yt=rt!==void 0?{x:rt.x,y:rt.y}:Ge!==void 0?{x:Ge.x,y:Ge.y}:{x:je,y:$e};$e+=92,t.upsertNode({id:Fe,x:yt.x,y:yt.y,label:oe.team,team:oe.team,name:oe.name!==void 0&&oe.name!==""?oe.name:oe.team,remoteHandle:oe.team,live:!0,remote:!0,memberships:[]})}}for(const v of t.nodeIds())v.startsWith("member-")&&!B.has(v)&&t.removeNode(v);const z=new Map;for(const v of t.allNodes())v.remote!==!0||v.remoteHandle===void 0||v.remoteHandle===""||(!z.has(v.remoteHandle)||v.id.startsWith("member-"))&&z.set(v.remoteHandle,v.id);for(const v of a.teams){if(Te.has(v.name))continue;const be=[];for(const $e of v.members){const oe=z.get($e.id)??$e.id;t.getNode(oe)!==void 0&&be.push(oe)}const he=[...t.teamMemberIds(v.name)].sort().join("|"),je=[...be].sort().join("|");he!==je&&t.setTeamMembers(v.name,be)}const ie=new Map,Ae=nt;if(nt=ie,a.peerOrg!==void 0){let v=0;const be=new Set(a.teams.map(he=>he.name));H.sweep(a.peerOrg);for(const he of a.peerOrg){const je=new Set((a.remoteTeams??[]).map(oe=>oe.team)),$e=wo(a.sessions,je);for(const oe of he.org){if(oe.name===""||be.has(oe.name)||H.hides(oe.name,he.url))continue;const Fe=oe.members.map(rt=>Ms(rt,$e,a.remoteTeams,he.url)).filter(rt=>t.getNode(rt)!==void 0),Ge=(Ke=o==null?void 0:o.frames)==null?void 0:Ke[oe.name];t.getFrame(oe.name)===void 0&&t.setFrame(oe.name,Ge!==void 0?{x:Ge.x,y:Ge.y,w:Ge.w,h:Ge.h}:{x:200+v%4*280,y:940+Math.floor(v/4)*160,w:250,h:130}),t.setTeamMembers(oe.name,Fe),ie.set(oe.name,he.url),v+=1}}}for(const[v,be]of Ae)ie.has(v)||t.removeFrame(v);const Le=new Map;for(const v of t.allNodes())v.remote===!0&&v.remoteHandle!==void 0&&v.remoteHandle!==""&&Le.set(v.remoteHandle,v.id);const Ne=go(a.teams);for(const v of a.teams){if(t.getFrame(v.name)!==void 0||Te.has(v.name))continue;const be=o==null?void 0:o.frames[v.name];if(be!==void 0){t.setFrame(v.name,{...be});continue}const he=[],je=[];for(const oe of v.members){const Fe=t.getNode(Le.get(oe.id)??oe.id);Fe!==void 0&&(je.push(mt(Fe)),Ne.get(Fe.id)===v.name&&he.push(mt(Fe)))}const $e=he.length>0?he:je;$e.length>0&&t.setFrame(v.name,En($e))}for(const[v]of t.allFrames())Te.has(v)||!a.teams.some(be=>be.name===v)&&!ie.has(v)&&t.removeFrame(v);if(Z.refresh(),We(a),!l&&n.kind==="none"&&t.nodeIds().length>0){l=!0;const v=u.capture();qt(t,new Set(nt.keys())),u.commit(v)}c&&n.kind==="none"&&t.nodeIds().length>0&&(Je(),qe>0&&ut>0&&(c=!1,s=qn(Un(t.contentBounds(),t.allNodes()),qe,ut,zn(we,q)))),Se()}function Sn(a){return vo(a,t.allNodes().filter(h=>h.remote!==!0))}function No(a){const h=ho(a);if(h===void 0)return;o=h;const g=e.viewportStore;if(g===void 0)c=!1,n.kind==="none"&&(s=Nt({...h.viewport}));else if(!m&&n.kind==="none"){m=!0;const F=g.get(x());F!=null&&Number.isFinite(F.x)&&Number.isFinite(F.y)&&Number.isFinite(F.scale)?(s=Nt({x:F.x,y:F.y,scale:F.scale}),c=!1):x()==="wide"&&(s=Nt({...h.viewport}),c=!1)}r=-1,Se()}function $o(){return rs(s,t.positions(),t.frameRects())}function Mo(a,h){le.classList.remove("pending","saved","error"),a==="pending"&&le.classList.add("pending"),a==="saved"&&le.classList.add("saved"),a==="error"&&le.classList.add("error"),a==="error"?(le.tabIndex=0,le.setAttribute("role","button"),le.setAttribute("aria-label","布局保存失败,按回车重试")):(le.removeAttribute("tabindex"),le.removeAttribute("role"),le.removeAttribute("aria-label"));const g=a==="pending"?"布局待保存…":a==="saved"?`布局已保存 ${h??""}`.trimEnd():a==="error"?"保存失败 · 回车重试":"布局";fe.textContent=g}function So(){E.style.display="block",Je(),Qe(),E.focus()}function Ao(){E.style.display="none"}function Lo(){re.abort();for(const a of V)clearTimeout(a)}return{root:E,reconcile:Eo,activate:So,deactivate:Ao,adoptExternalLayout:No,snapshotDoc:$o,setLamp:Mo,notice:L,destroy:Lo,seam:{pointerDown:Pe,pointerMove:Ze,pointerUp:et,pointerCancel:pt,wheel:Ve,key:It,keyUp:Mn,contextMenu(a){a.preventDefault(),O.contextMenuAt(a.clientX,a.clientY,a.target)}}}}const wi=800;function xi(e){let t,o=!1,s=!1,n=!1,i="idle";function r(b){b!==i&&(i=b,e.onLamp(b))}function c(){t!==void 0&&(t(),t=void 0)}function l(){c(),t=e.schedule(()=>{t=void 0,u(!1)},wi)}async function u(b){if(o){s=!0;return}o=!0,c();const m=e.snapshot();let x;try{x=JSON.stringify(m)}catch{o=!1,r("error"),e.onHttpError("layout document is not JSON-serializable");return}try{const N=await e.send(m,{keepalive:b});if(N===null||typeof N!="object"||N.ok!==!0){r("error");const Y=N!==null&&typeof N=="object"&&typeof N.error=="string"?N.error:"layout save refused";e.onHttpError(`layout save: ${Y}`)}else JSON.stringify(e.snapshot())===x&&(e.onAdopt(N.layout),r("saved"))}catch(N){r("error"),e.onHttpError(`layout save unreachable: ${String((N==null?void 0:N.message)??N).slice(0,80)}`)}if(o=!1,i==="error"){n=!1;return}if(n){n=!1,u(!0);return}s&&(s=!1,r("pending"),l())}return{markDirty(){if(s=!1,r("pending"),o){s=!0;return}l()},retry(){i!=="error"||o||(r("pending"),u(!1))},flush(){if(o){n=!0,s=!0;return}c(),u(!0)},isBusy(){return o},dispose(){c()}}}function no(e){return e!=null&&typeof e.error=="string"?e.error:void 0}function Ci(e){const t=new Map;let o=0;function s(r,c){o+=1;const l=t.get(r)??Promise.resolve(),u=async()=>{try{return await c()}finally{o-=1}},b=l.then(u,u);return t.set(r,b.then(()=>{},()=>{})),b}async function n(r){var re,V,M,C;let c;try{c=await e.send(r)}catch(S){const E=String((S==null?void 0:S.message)??S).slice(0,80);return e.onNotice("error",`画布不可达:${E}`),!1}if(c.status>=400)return e.onNotice("error",no(c.body)??`HTTP ${c.status}`),!1;if(((re=c.body)==null?void 0:re.ok)===!0)return!0;const l=c.body!=null&&typeof c.body=="object"?no(c.body):void 0;if(l!==void 0)return e.onNotice("error",l),!1;const u=String(r.name??""),b=String(r.id??""),m=(V=c.body)==null?void 0:V.members,x=(M=c.body)==null?void 0:M.teams,N=Array.isArray(m)&&m.every(S=>typeof S=="string"),Y=Array.isArray(x)&&x.every(S=>typeof S=="string");return((C=c.body)==null?void 0:C.ok)===!1&&(r.action==="add-member"&&N&&m.includes(b)||r.action==="remove-member"&&N&&!m.includes(b)||r.action==="remove"&&Y&&!x.includes(u))?!0:(e.onNotice("error","画布操作未确认:"+String(r.action)+"(可能队伍/成员已达上限,请重试)"),!1)}async function i(r,c){for(const l of c)if(!await n({...r,id:l}))return!1;return!0}return{createTeam(r,c){return s(r,async()=>{if(!await n({action:"create",name:r}))return!1;for(let l=0;l<c.length;l++)if(!await n({action:"add-member",name:r,id:c[l]}))return!1;return!0})},addMembers(r,c){return s(r,()=>i({action:"add-member",name:r},c))},removeMembers(r,c){return s(r,()=>i({action:"remove-member",name:r},c))},runRosterOps(r,c){return s(r,async()=>{for(const l of c){const u=l.op==="remove"?{action:"remove-member",name:r,id:l.id}:{action:"add-member",name:r,id:l.id};if(!await n(u))return!1}return!0})},removeTeam(r){return s(r,()=>n({action:"remove",name:r}))},hasPending(){return o>0}}}const Co=document.getElementById("app"),ki=(()=>{try{return window.sessionStorage.getItem("dsh_a2a_key")??""}catch{return""}})(),yn=window.__DSH_A2A_KEY__??ki,ze=(e,t={})=>fetch(e,{...t,headers:{...t.headers??{},...yn!==""?{"X-API-Key":yn}:{}}});yn===""&&ze("/__dsh_a2a/owner-settings").then(e=>{if(e.status!==401)return;const t=document.createElement("div");t.className="nexus-keygate",t.style.cssText="position:fixed;inset:0;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:10px;background:#fff;z-index:9999;font:14px/1.5 system-ui,sans-serif;color:#000";const o=document.createElement("div");o.textContent="此面板经远程面打开(密钥不随页面下发)——输入控制密钥";const s=document.createElement("input");s.type="password",s.placeholder="X-API-Key",s.setAttribute("aria-label","控制密钥");const n=document.createElement("button");n.type="button",n.textContent="进入面板";const i=document.createElement("div");i.style.color="#b00";const r=()=>{const c=s.value.trim();c!==""&&fetch("/__dsh_a2a/owner-settings",{headers:{"X-API-Key":c}}).then(l=>{if(l.status===401){i.textContent="密钥不对,再试一次";return}try{window.sessionStorage.setItem("dsh_a2a_key",c)}catch{}window.location.reload()})};n.addEventListener("click",r),s.addEventListener("keydown",c=>{c.key==="Enter"&&r()}),t.append(o,s,n,i),document.body.appendChild(t)});const Pt=document.createElement("div");Pt.className="nexus-fault";Co.appendChild(Pt);const{fault:wn,clear:Ei}=Oo({show(e){Pt.textContent=e,Pt.style.display="block"},hide(){Pt.style.display="none"}},e=>console.error(e));let Qt;const oo="dsh-a2a.viewport.",Ni={get(e){try{const t=window.localStorage.getItem(oo+e);return t===null?void 0:JSON.parse(t)}catch{return}},set(e,t){try{window.localStorage.setItem(oo+e,JSON.stringify({x:t.x,y:t.y,scale:t.scale}))}catch{}}},st=yi({viewportStore:Ni,onDirty:()=>on.markDirty(),onLampClick:()=>on.retry(),onNodePick:e=>{Qt==null||Qt(e)},onCanvasAction:async e=>{const t=await Mi(e);return an(),t}}),on=xi({snapshot:()=>st.snapshotDoc(),send:(e,t)=>ze("/__dsh_a2a/canvas-layout",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"save",layout:e}),cache:"no-store",keepalive:t.keepalive}).then(async o=>await o.json()),schedule:(e,t)=>{const o=setTimeout(e,t);return()=>{clearTimeout(o)}},now:Date.now,onLamp:e=>{xn=e;const t=new Date,o=String(t.getHours()).padStart(2,"0")+":"+String(t.getMinutes()).padStart(2,"0");st.setLamp(e,o)},onAdopt:e=>{st.adoptExternalLayout(e)},onHttpError:e=>wn(e)});window.addEventListener("pagehide",()=>on.flush());const Ot=Ci({send:async e=>{const t=await ze("/__dsh_a2a/canvas",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),cache:"no-store"});return{status:t.status,body:await t.json()}},onNotice:(e,t)=>st.notice(e,t)});async function so(e,t,o,s){const n=await ze("/__dsh_a2a/fleet-canvas-op",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({peer:e,op:t,name:o,...s!==void 0?{id:s}:{}}),cache:"no-store"}).catch(()=>{}),i=n!==void 0?await n.json().catch(()=>{}):void 0;return(i==null?void 0:i.ok)===!0&&t==="remove"&&i.removed===!1&&st.notice("info",`属主那边已没有「${o}」,无需解散`),(i==null?void 0:i.ok)===!0?!0:(st.notice("error",`跨主机团队操作失败:${String((i==null?void 0:i.error)??"对端无响应")}`),!1)}async function $i(e,t){const o=async s=>{const n=await ze("/__dsh_a2a/roster-op",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:t,...s})}).catch(()=>{}),i=n!==void 0?await n.json().catch(()=>{}):void 0;return n!=null&&n.ok&&(i==null?void 0:i.ok)===!0?!0:(st.notice("error",`roster 操作失败:${String((i==null?void 0:i.error)??(n?`HTTP ${n.status}`:"无响应"))}`),!1)};if(e.type==="create-team")return o({op:"create",ids:e.ids});if(e.type==="remove-team")return o({op:"dissolve"});if(e.type==="add-member"||e.type==="remove-member"){for(const s of e.ids)if(!await o({op:e.type,id:s}))return!1;return!0}return st.notice("error","roster 不支持该操作"),!1}function Mi(e){if((e.type==="add-member"||e.type==="remove-member")&&e.fleetPeer!==void 0){const t=e.fleetPeer;return(async()=>{for(const o of e.ids)if(!await so(t,e.type,e.team,o))return!1;return!0})()}if(e.type==="remove-team"&&e.fleetPeer!==void 0)return so(e.fleetPeer,"remove",e.name);if(e.roster===!0){const t=xo(Rt(e));return t!==void 0?$i(e,t):(st.notice("error","无效的 roster 框名"),Promise.resolve(!1))}switch(e.type){case"create-team":return Ot.createTeam(e.name,e.ids,e.created);case"add-member":return Ot.addMembers(e.team,e.ids);case"remove-member":return Ot.removeMembers(e.team,e.ids);case"remove-team":return Ot.removeTeam(e.name);case"reorder":return Ot.runRosterOps(e.team,e.ops);case"join-network":case"leave-network":return Si(e.type==="join-network"?"join":"leave",e.id)}}async function Si(e,t){const o=await ze(`/__dsh_a2a/${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:t}),cache:"no-store"}).catch(()=>{});return o!==void 0&&o.ok}let xn="idle",fn=new Set,io=0,sn=!1,ro,pn=!1;async function Ai(){const e=await ze("/__dsh_a2a/canvas-layout",{cache:"no-store"});if(!e.ok)throw new Error(`/__dsh_a2a/canvas-layout ${e.status}`);return(await e.json()).layout??null}const rn=ss({now:()=>Date.now(),async ownerSettingsRead(){try{return await(await ze("/__dsh_a2a/owner-settings")).json()}catch{return{ok:!1,error:"unreachable"}}},async ownerSettingsWrite(e){try{return await(await ze("/__dsh_a2a/owner-settings",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})).json()}catch{return{ok:!1,error:"unreachable"}}},async abandon(e,t){try{return(await ze("/__dsh_a2a/tasks/abandon",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({task_id:e,reason:t})})).ok}catch{return!1}},copy(e){var t;(t=navigator.clipboard)==null||t.writeText(e).catch(()=>{})},async cliHomeOptions(e,t){try{const o=await ze("/__dsh_a2a/canvas",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({action:"cli-home-options",name:e,id:t})}),s=await o.json();return{...s,ok:o.ok&&s.ok===!0}}catch(o){return{ok:!1,error:String(o)}}},async canvasOp(e,t,o,s){try{const n=await ze("/__dsh_a2a/canvas",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({action:e,name:t,id:o,...s===void 0?{}:{home:s}})}),i=await n.json().catch(()=>({}));return n.ok&&i.ok!==!1?!0:(console.warn(`canvas ${e} ${t}: ${i.error??`HTTP ${n.status}`}`),!1)}catch{return!1}},async dispatchQuick(e,t){try{const o=await ze("/__dsh_a2a/dispatch",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({team:e,message:t})}),s=await o.json().catch(()=>({}));return{ok:o.ok&&s.ok===!0,task_id:s.task_id,reply:s.reply,error:s.error??`HTTP ${o.status}`}}catch(o){return{ok:!1,error:o instanceof Error?o.message:String(o)}}},async sessionLog(e){try{const t=await ze(`/__dsh_a2a/session-log?id=${encodeURIComponent(e)}`),o=await t.json().catch(()=>({}));return{ok:t.ok&&o.ok===!0,messages:o.messages,error:o.error??(t.ok?void 0:`HTTP ${t.status}`)}}catch(t){return{ok:!1,error:t instanceof Error?t.message:String(t)}}},async sessionLogList(){try{const e=await ze("/__dsh_a2a/session-log"),t=await e.json().catch(()=>({}));return{ok:e.ok&&t.ok===!0,sessions:t.sessions,count:typeof t.count=="number"?t.count:void 0,error:t.error??(e.ok?void 0:`HTTP ${e.status}`)}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}},async remoteSessionLog(e){try{const t=new URLSearchParams;e.team!==void 0&&t.set("team",e.team),e.peer!==void 0&&t.set("peer",e.peer),e.id!==void 0&&t.set("id",e.id),e.limit!==void 0&&t.set("limit",String(e.limit));const o=await ze(`/__dsh_a2a/remote-session-log?${t.toString()}`),s=await o.json().catch(()=>({}));return{ok:o.ok&&s.ok===!0,messages:s.messages,sessions:s.sessions,error:s.error??(o.ok?void 0:`HTTP ${o.status}`),via:s.via}}catch(t){return{ok:!1,error:t instanceof Error?t.message:String(t)}}},board:{root:st.root,activate:()=>st.activate(),deactivate:()=>st.deactivate(),available:()=>sn}});Co.appendChild(rn.root);Qt=e=>{rn.openNodeChat(e)};if(new URLSearchParams(window.location.search).get("mode")==="plan"){const e=window.setInterval(()=>{sn&&(rn.selectTab("board"),window.clearInterval(e))},300);window.setTimeout(()=>window.clearInterval(e),3e4)}async function an(){var e,t;try{const o=await ze("/__dsh_a2a/state",{cache:"no-store"});if(!o.ok)throw new Error(`/__dsh_a2a/state ${o.status}`);const s=await o.json();if(Date.now()-io>=15e3){io=Date.now();try{const m=await ze("/__dsh_a2a/nodes",{cache:"no-store"});if(!m.ok)throw new Error(`nodes ${m.status}`);const x=await m.json();fn=new Set((x.bindings??[]).filter(N=>N.mounted!==null&&N.effective!==null&&(N.effective.core===!1||N.effective.mutable===!1)).map(N=>N.session))}catch{fn.clear()}}const n={...s,sessions:(s.sessions??[]).map(m=>({...m,...fn.has(m.id)?{nodePromptMissing:!0}:{}}))};if(Ei(),sn=s.canvas!==void 0,rn.update(n),sn)try{const m=await Ai(),x=JSON.stringify(m??null);x!==ro&&(ro=x,(xn==="idle"||xn==="saved")&&!on.isBusy()&&st.adoptExternalLayout(m)),pn=!0}catch(m){if(!pn){wn(`canvas layout 获取失败:${String(m)}`);return}}else pn=!0;const i=(s.sessions??[]).map(m=>({...m,joined:m.joined===!0})),r=[...((e=s.canvas)==null?void 0:e.teams)??[],...Ds(((t=s.registry)==null?void 0:t.teams)??[],s.zone??"")],c=(s.peers??[]).filter(m=>m!==null&&typeof m=="object"&&typeof m.url=="string"),l=(s.inFlight??[]).filter(m=>m!==null&&typeof m=="object"&&typeof m.team=="string"&&typeof m.peer=="string"&&Number.isFinite(m.startedAt)),u=(s.remote??[]).filter(m=>m!==null&&typeof m=="object"&&typeof m.team=="string"&&typeof m.via=="string").map(m=>({team:m.team,name:m.name,via:m.via,workspace:m.workspace,...m.unreachable===!0?{unreachable:!0}:{},...typeof m.origin=="string"&&m.origin!==""?{origin:m.origin}:{},...Array.isArray(m.teams)&&m.teams.length>0?{teams:m.teams.filter(x=>typeof x=="string"&&x!=="")}:{}})),b=(s.peerOrg??[]).filter(m=>m!==null&&typeof m=="object").filter(m=>typeof m.url=="string"&&Array.isArray(m.org)).map(m=>({url:m.url,...m.unreachable===!0?{unreachable:!0}:{},org:m.org.filter(x=>x!==null&&typeof x=="object").filter(x=>typeof x.team=="string"&&x.team!=="").map(x=>({name:typeof x.name=="string"?x.name:"",team:x.team,members:Array.isArray(x.members)?x.members.filter(N=>typeof N=="string"):[]}))}));st.reconcile({sessions:i,teams:r,peerCount:c.length,peers:c,inFlight:l,remoteTeams:u,peerOrg:b})}catch(o){wn(`state 轮询失败:${String(o)}`)}}an();window.setInterval(()=>{document.hidden||an()},3e3);document.addEventListener("visibilitychange",()=>{document.hidden||an()});
|