@nelsonlongxiang/dsh-open-a2a-net 0.6.28 → 0.6.29
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 +85 -14
- package/README_zh.md +81 -7
- package/assets/nexusDist/assets/index-BqepxJ7E.css +1 -0
- package/assets/nexusDist/assets/index-CTWH6QRh.js +9 -0
- package/assets/nexusDist/index.html +2 -2
- package/cli/a2a.mjs +624 -624
- package/cordis.patch.yml +21 -21
- package/lib/client.js +64 -64
- package/lib/client.js.map +1 -1
- package/lib/faces/admin.js +744 -0
- package/lib/index.js +139 -737
- package/lib/recursion-guard.js +78 -0
- package/lib/runtime.js +1 -0
- package/lib/skill/SKILL.md +34 -9
- package/lib/skill/references/cli.md +24 -7
- package/lib/skill/references/discovery.md +5 -2
- package/lib/skill/references/pitfalls.md +2 -1
- package/lib/skill/references/routing.md +18 -8
- package/lib/skill/references/setup.md +152 -0
- package/lib/task-ledger.js +6 -0
- package/lib/types/faces/admin.d.ts +132 -0
- package/lib/types/index.d.ts +11 -3
- package/lib/types/recursion-guard.d.ts +56 -0
- package/lib/types/runtime.d.ts +34 -0
- package/lib/types/task-ledger.d.ts +6 -0
- package/nexus-stage/package-lock.json +2262 -2262
- package/nexus-stage/src/canvas-ops.ts +175 -175
- package/nexus-stage/src/canvas-wire.ts +156 -156
- package/nexus-stage/src/edges.ts +72 -72
- package/nexus-stage/src/federation-overlay.ts +103 -103
- package/nexus-stage/src/federation.ts +240 -240
- package/nexus-stage/src/layout-doc.ts +143 -143
- package/nexus-stage/src/layout-wire.ts +158 -158
- package/nexus-stage/src/planning-card-text.ts +73 -0
- package/nexus-stage/src/planning-fit.ts +45 -0
- package/nexus-stage/src/planning-legend.ts +38 -0
- package/nexus-stage/src/planning-overlap.ts +134 -0
- package/nexus-stage/src/planning-relayout.ts +121 -0
- package/nexus-stage/src/planning-search.ts +168 -0
- package/nexus-stage/src/planning-view.ts +63 -88
- package/nexus-stage/src/planning.css +39 -8
- 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/nexus-stage/src/viewport.ts +24 -1
- package/nexus-stage/src/wb-chat.ts +20 -6
- package/nexus-stage/src/wb-ledger.ts +20 -7
- package/nexus-stage/src/wb-names.ts +43 -0
- package/nexus-stage/src/workbench.css +8 -2
- package/nexus-stage/src/workbench.ts +55 -17
- package/nexus-stage/src/world.ts +5 -1
- package/package.json +216 -214
- package/assets/nexusDist/assets/index-1niOBYxp.js +0 -5
- package/assets/nexusDist/assets/index-uQf7NwjF.css +0 -1
- package/nexus-stage/scripts/__pycache__/mockhost.cpython-312.pyc +0 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
var ao=Object.defineProperty;var lo=(t,e,n)=>e in t?ao(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var kt=(t,e,n)=>lo(t,typeof e!="symbol"?e+"":e,n);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))s(o);new MutationObserver(o=>{for(const i of o)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 n(o){const i={};return o.integrity&&(i.integrity=o.integrity),o.referrerPolicy&&(i.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?i.credentials="include":o.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function s(o){if(o.ep)return;o.ep=!0;const i=n(o);fetch(o.href,i)}})();const Jt=6e4;function co(t,e,n=Date.now){let s=-Jt;return{fault(o){const i=n();i-s>=Jt&&(e(`[nexus] ${o}`),s=i),t.show(o)},clear(){t.hide(),s=-Jt}}}function it(t){return t.name??t.team??t.label??""}function Wn(t,e){var i,r;const n=(l,m)=>l!==void 0&&l.trim()!==""?{name:l,remote:m}:void 0,s=(t.sessions??[]).find(l=>l.team===e);if(s!==void 0)return n(it(s),!1);const o=(t.remote??[]).find(l=>l.team===e);return o!==void 0?n(it(o),!0):n((r=(((i=t.canvas)==null?void 0:i.teams)??[]).find(l=>l.team===e))==null?void 0:r.name,!1)}function mo(t,e){const n=Wn(t,e);return n===void 0?e:n.remote?`${n.name}(远端)`:n.name}function Yt(t,e,n,s=""){const o=Wn(e,n);if(t.textContent=`${s}${(o==null?void 0:o.name)??n}`,t.title=n,(o==null?void 0:o.remote)===!0){const i=t.appendChild(document.createElement("span"));i.className="wb-row-remote",i.textContent="远端",i.title="名字由对端自行发布"}}const uo=60*6e4;function $t(t){var e;return t.direction==="inbound"||t.direction===void 0&&((e=t.peer)==null?void 0:e.startsWith("local:"))===!0}function gn(t){var e;return((e=t.peer)==null?void 0:e.startsWith("local:"))===!0?t.peer.slice(6):void 0}function Tt(t,e){return t.settleable!==void 0?t.settleable===!1:e-t.startedAt>=uo}function en(t,e){const n=(t.tasks??[]).filter(r=>r.receiptExpected!==!1),s=n.filter(r=>!$t(r)&&Tt(r,e)),o=n.filter(r=>$t(r)&&Tt(r,e)),i=t.tasksDead??[];return{stale:s,owedOverdue:o,deadLetters:i.filter(r=>r.reason!=="fire-forget"),expired:i.filter(r=>r.reason==="fire-forget")}}function we(t,e){const n=document.createElement(t);return e!==void 0&&(n.className=e),n}function vn(t,e){const n=Math.max(0,Math.round((e-t)/1e3));if(n<90)return`${n}s`;const s=Math.round(n/60);if(s<90)return`${s}m`;const o=Math.round(s/60);return o<48?`${o}h`:`${Math.round(o/24)}d`}function Pt(t,e,n,s,o){const i=we("div",`wb-led-tile${o!==void 0?` is-${o}`:""}`);i.title=s,i.appendChild(we("span","wb-led-tile-v")).textContent=String(n),i.appendChild(we("span","wb-led-tile-k")).textContent=e,t.appendChild(i)}const tn=[{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 fo(t,e,n){const s=we("div","wb-led-split"),o=we("div","wb-led-split-bar");o.setAttribute("role","img");const i=we("div","wb-led-split-legend"),r=new Set(tn.map(c=>c.key)),l=tn.map(c=>[c.tone,c.label,e[c.key]??0]);for(const[c,h]of Object.entries(e))r.has(c)||l.push(["other",c,h]);const m=[];for(const[c,h,b]of l){if(b<=0)continue;const L=we("span",`wb-led-seg is-${c}`);L.style.width=`${Math.max(2,b/n*100)}%`,o.appendChild(L);const T=we("span","wb-led-split-item");T.appendChild(we("i",`wb-led-swatch is-${c}`)),T.appendChild(document.createTextNode(`${h} ${b}`)),i.appendChild(T),m.push(`${h} ${b}`)}o.setAttribute("aria-label",`归档结局:${m.join(",")}`),s.append(o,i),t.appendChild(s)}function po(t,e){var Le;t.replaceChildren();const{state:n,now:s}=e,o=n.tasks??[],i=n.tasksDead??[],r=n.archivedCount??0,l=en(n,s),m=o.filter(P=>P.receiptExpected===!1),c=o.filter(P=>P.receiptExpected!==!1),h=c.filter(P=>$t(P)),b=c.filter(P=>!$t(P)),L=l.stale,T=b.filter(P=>!Tt(P,s)),U=l.stale.length,ne=we("div","wb-led-tiles");Pt(ne,"待回执",c.length,`要回执、仍未结算的任务(含陈旧与本机欠对方的入站行)${m.length>0?`;另有免回执 ${m.length} 条不计`:""}`),Pt(ne,"陈旧",U,"我方派发、要回执、已等待 ≥1h 仍未回执(可催办);本机欠对方的入站行在「待本机回执」组另计,免回执行不算陈旧",U>0?"warn":void 0),Pt(ne,"死信",l.deadLetters.length,"超过 24h TTL 仍未结算(unconsumed);需清账(abandon)才能移出。免回执到期另列,不算死信",l.deadLetters.length>0?"danger":void 0),Pt(ne,"已归档",r,"已离开台账并留档的任务(结算、拒绝或放弃),用于审计"),t.appendChild(ne),r>0&&n.archivedSplit!==void 0&&fo(t,n.archivedSplit,r);const be=(P,z)=>{const ie=we("div",`wb-led-card is-${z.tone}`),re=we("div","wb-led-card-head");re.appendChild(we("span",`wb-led-dir${z.inbound?" is-in":""}`)).textContent=z.inbound?"↙":"↗";const te=we("span","wb-led-brief");te.textContent=z.brief!==void 0&&z.brief!==""?z.brief:"(无摘要——派发未带 brief)",(z.brief===void 0||z.brief==="")&&te.classList.add("is-missing"),re.appendChild(te),ie.appendChild(re);const K=we("div","wb-led-meta"),ae=K.appendChild(we("span","wb-led-team"));z.inbound?z.sender!==void 0?Yt(ae,n,z.sender,"来自 "):ae.textContent="来自 对端":Yt(ae,n,z.team,"发往 "),z.inbound&&Yt(K.appendChild(we("span","wb-led-to")),n,z.team,"至 "),K.appendChild(we("span")).textContent=z.atText,K.appendChild(we("span","wb-led-task")).textContent=z.taskId;for(const de of z.chips)K.appendChild(we("span","wb-led-chip")).textContent=de;if(ie.appendChild(K),ie.title=`${z.taskId}
|
|
2
|
+
${z.team}`,z.dead!==void 0){const de=z.dead,Me=de.reason==="fire-forget",Ae=we("button",`wb-btn wb-led-abandon${Me?" is-quiet":""}`);Ae.type="button",Ae.textContent=Me?"移出":"清账",Ae.title=Me?"可选:把这条已过期的免回执记录移出台账(不是失败,不处理也无妨)":"从台账移出这条死信(abandon)",Ae.addEventListener("click",Ve=>{Ve.stopPropagation(),Ae.disabled=!0,e.abandon(de.taskId,"workbench dead-letter cleanup").then(qe=>{Ae.disabled=!1,Ae.textContent=qe?"已清":"失败"})}),ie.appendChild(Ae)}if(e.canOpenTeam(z.team)){ie.classList.add("is-link"),ie.setAttribute("role","button"),ie.tabIndex=0,ie.setAttribute("aria-label",`${te.textContent},打开 ${z.team} 的对话`);const de=()=>{e.openTeam(z.team)};ie.addEventListener("click",de),ie.addEventListener("keydown",Me=>{(Me.key==="Enter"||Me.key===" ")&&(Me.preventDefault(),de())})}P.appendChild(ie)},$=(P,z,ie,re)=>{if(z===0)return null;const te=we("div",`wb-led-group is-${ie}`);te.dataset.group=P;const K=we("div","wb-led-group-head");return K.appendChild(we("span")).textContent=`${P} · ${z}`,K.appendChild(we("span","wb-led-group-hint")).textContent=re,te.appendChild(K),t.appendChild(te),te},p=(P,z)=>{const ie=$t(P);return{brief:P.brief,team:P.team,sender:gn(P),taskId:P.taskId,atText:`${vn(P.startedAt,s)} 前${ie?"收到":"派发"}`,inbound:ie,tone:z,chips:[...P.settleable===!0?["可结算"]:[],...P.receiptExpected===!1?["无回执债"]:[],...ie?["入站"]:[],...P.status!=="pending"?[P.status]:[]]}},H=(P,z,ie)=>({brief:P.brief,team:P.team,sender:gn(P),taskId:P.taskId,atText:`${vn(P.deadAt,s)} 前${ie}`,inbound:$t(P),tone:z,dead:P,chips:P.reason!==void 0&&P.reason!==""&&P.reason!=="unspecified"&&P.reason!=="fire-forget"?[P.reason]:[]}),v=$("死信",l.deadLetters.length,"danger","需清账");if(v!==null)for(const P of[...l.deadLetters].sort((z,ie)=>ie.deadAt-z.deadAt))be(v,H(P,"danger","死信"));const f=$("陈旧",L.length,"warn","我方派发 ≥1 小时仍无回执,可催办");if(f!==null)for(const P of[...L].sort((z,ie)=>z.startedAt-ie.startedAt))be(f,p(P,"warn"));const M=l.owedOverdue.length,y=$("待本机回执",h.length,M>0?"warn":"quiet",M>0?`对方在等本机回执 · ${M} 条超过 1 小时`:"对方在等本机回执");if(y!==null)for(const P of[...h].sort((z,ie)=>z.startedAt-ie.startedAt))be(y,p(P,Tt(P,s)?"warn":"quiet"));const O=$("等待回执",T.length,"quiet","1 小时内");if(O!==null)for(const P of[...T].sort((z,ie)=>ie.startedAt-z.startedAt))be(O,p(P,"quiet"));const x=$("免回执",m.length,"muted","不等回执,24h 后自动归档");if(x!==null)for(const P of m)be(x,p(P,"muted"));const R=$("已过期(免回执)",l.expired.length,"muted","正常记账,不是失败");if(R!==null)for(const P of[...l.expired].sort((z,ie)=>ie.deadAt-z.deadAt))be(R,H(P,"muted","过期"));o.length+i.length===0&&(t.appendChild(we("div","wb-led-empty")).textContent="台账为空——没有待回执的任务");const D=n.idempotency,fe=(Le=n.reconcile)==null?void 0:Le.state;if(D!==void 0||fe!==void 0){const P=we("details","wb-led-forensics wb-forensics");P.appendChild(we("summary")).textContent="取证";const z=we("div","wb-led-forensics-body");D!==void 0&&(z.appendChild(we("div")).textContent=`幂等 claims ${D.claimsFresh??0} · replays ${D.replays??0} · conflicts ${D.conflicts??0}`),fe!==void 0&&(z.appendChild(we("div")).textContent=`reconcile ${fe}`),P.appendChild(z),t.appendChild(P)}const Ce=c.length+l.deadLetters.length;return{badge:Ce>0?String(Ce):"",tone:l.deadLetters.length>0?"danger":U>0||M>0?"warn":void 0}}const At=4e3,ho=32;function he(t,e){const n=document.createElement(t);return e!==void 0&&(n.className=e),n}function Ft(t,e,n=""){const s=he("button",`wb-icon-btn wb-chat-act ${n}`.trim());return s.type="button",s.setAttribute("aria-label",t),s.title=t,s.textContent=e,s}function Vt(t,e){const n=Math.max(0,Math.round((e-t)/1e3));if(n<60)return"刚刚";const s=Math.round(n/60);if(s<60)return`${s} 分钟前`;const o=Math.round(s/60);return o<48?`${o} 小时前`:`${Math.round(o/24)} 天前`}function bo(t){return t>=1e6?`${(t/1e6).toFixed(1)} MB`:t>=1e3?`${Math.round(t/1e3)} KB`:`${t} B`}function qt(t){const e=t.kind==="session"||t.kind==="remote"?t.team:void 0;return e!==void 0&&e!==""?e:void 0}function yn(t){return t.kind==="remote"?`remote:${t.team}`:`${t.kind}:${t.id}`}function go(t){let e=null,n=null,s=!1,o=!1;const i=new Map,r=new Map,l=new Map,m=new Map,c=new Set,h=new Map,b=new Map,L=he("aside","wb-chat");L.setAttribute("aria-label","对话");const T=he("div","wb-chat-head"),U=Ft("返回会话列表","‹","wb-chat-back"),ne=he("span","wb-chat-dot"),be=he("div","wb-chat-titles"),$=he("span","wb-chat-title"),p=he("span","wb-chat-sub");be.append($,p);const H=Ft("刷新对话","↻","wb-chat-refresh"),v=Ft("会话详情","ⓘ","wb-chat-info-btn");v.setAttribute("aria-expanded","false");const f=Ft("关闭对话","✕","wb-chat-close");T.append(U,ne,be,H,v,f);const M=he("div","wb-chat-info");M.hidden=!0;const y=he("div","wb-chat-thread");y.setAttribute("role","log"),y.setAttribute("aria-live","polite"),y.tabIndex=0;const O=he("div","wb-chat-notice"),x=he("div","wb-chat-log"),R=he("div","wb-chat-sent");y.append(O,x,R);const D=he("div","wb-chat-foot");L.append(T,M,y,D),U.addEventListener("click",()=>{(e==null?void 0:e.kind)==="peer"&&(e.picked=void 0,tt())}),H.addEventListener("click",()=>{if(e===null)return;const d=fe(e);d!==void 0&&i.delete(d),e.kind==="peer"&&e.picked===void 0&&e.url!==void 0&&l.delete(`peer:${e.url}`),Ae(!0)}),v.addEventListener("click",()=>{o=!o,M.hidden=!o,v.setAttribute("aria-expanded",String(o))}),f.addEventListener("click",()=>vt()),y.addEventListener("scroll",()=>{const d=e!==null?fe(e):void 0;d!==void 0&&r.set(d,y.scrollTop)}),document.addEventListener("keydown",d=>{if(d.key!=="Escape"||!L.classList.contains("is-open"))return;const N=d.target;if(N instanceof HTMLElement){if(!L.contains(N)){const I=N instanceof HTMLTextAreaElement||N instanceof HTMLInputElement||N.isContentEditable,G=N.closest(".wb-stage-board")!==null;if(I||G)return}vt()}});function fe(d){if(d.kind==="session"||d.kind==="log")return t.sessionLog!==void 0?`local:${d.id}`:void 0;if(d.kind==="remote")return t.remoteSessionLog!==void 0?`remote:${d.team}`:void 0;if(d.picked!==void 0&&d.url!==void 0&&t.remoteSessionLog!==void 0)return`peer:${d.url}:${d.picked}`}function Ce(d){var N,I,G;return d.kind==="session"||d.kind==="log"?((N=t.sessionLog)==null?void 0:N.call(t,d.id))??Promise.resolve({ok:!1,error:"sessionLog unavailable"}):d.kind==="remote"?((I=t.remoteSessionLog)==null?void 0:I.call(t,{team:d.team}))??Promise.resolve({ok:!1,error:"remoteSessionLog unavailable"}):((G=t.remoteSessionLog)==null?void 0:G.call(t,{peer:d.url,id:d.picked}))??Promise.resolve({ok:!1,error:"remoteSessionLog unavailable"})}function Le(){const d=e;if(d===null)return;const N=d.kind==="log"||d.kind==="remote"||d.kind==="session"&&d.live===!1;ne.className=`wb-chat-dot ${d.kind==="peer"?"is-peer":N?"is-cold":"is-live"}`,ne.title=d.kind==="peer"?"对端主机":d.kind==="log"?"只读日志":d.kind==="remote"?"远端会话":d.live===!1?"冷会话":"在线",$.textContent=d.kind==="peer"&&d.picked!==void 0?`…${d.picked.slice(-12)}`:d.title,p.textContent=d.kind==="peer"&&d.picked!==void 0?d.title:d.sub,U.hidden=!(d.kind==="peer"&&d.picked!==void 0)}function P(d,N){const I=he("div","wb-kv");I.appendChild(he("span","wb-kv-k")).textContent=d,I.appendChild(he("span","wb-kv-v")).textContent=N,M.appendChild(I)}function z(){var N,I,G;M.replaceChildren();const d=e;d!==null&&(d.kind==="session"?(P("会话",d.id),d.team!==void 0&&P("路由",d.team),P("来源","本机会话日志")):d.kind==="log"?(P("会话",d.id),P("来源","本机会话日志(不在网络目录)")):d.kind==="remote"?(P("路由",d.team),((N=d.row)==null?void 0:N.origin)!==void 0&&P("来源",d.row.origin),((I=d.row)==null?void 0:I.via)!==void 0&&P("经",d.row.via),((G=d.row)==null?void 0:G.workspace)!==void 0&&P("工作区",d.row.workspace)):(P("对端",d.url??d.sub),d.picked!==void 0&&P("会话",d.picked),P("来源","经本机代理读取对端 /a2a/log")))}function ie(d){return d.kind==="log"?"只读日志 —— 此会话当前不在网络目录(可能已归档或未入网)。":d.kind==="remote"?t.remoteSessionLog!==void 0?"远端会话 —— 经本机代理从对端 /a2a/log 读取最近对话。":"远端节点的对话记录在对端机器上;本页的代理读取面未启用。":d.kind==="peer"?d.url===void 0||t.remoteSessionLog===void 0?`对端主机节点(${d.sub})—— 会话记录存放在对端机器上,本页只读本机会话日志。`:d.picked===void 0?"对端主机 —— 选择一个会话阅读(经本机代理读取对端 /a2a/log)。":"":t.sessionLog===void 0?"本页未接入会话日志读取,只显示从这里发出的消息。":""}function re(){return y.scrollHeight-y.scrollTop-y.clientHeight<=ho}function te(d){const N=()=>{y.scrollTop=y.scrollHeight};N(),requestAnimationFrame(N)}function K(d,N){const I=he("div",`wb-chat-empty${N==="error"?" is-error":""}`);return I.textContent=d,I}function ae(d,N){const I=d==="user",G=he("div",`wb-msg ${I?"wb-msg-user":"wb-msg-assistant"}`),Y=he("span","wb-msg-who");Y.textContent=I?"问":"答";const me=he("div","wb-msg-text");return me.textContent=N,G.append(Y,me),G}function de(d){if(x.replaceChildren(),d===void 0){x.appendChild(K("读取中…"));return}if(d.ok!==!0||d.messages===void 0){x.appendChild(K(`无法读取(${d.error??"未知错误"})`,"error"));return}if(d.messages.length===0){x.appendChild(K("暂无对话记录"));return}for(const N of d.messages)x.appendChild(ae(N.role,N.text))}function Me(d,N){if(x.replaceChildren(),N===void 0){x.appendChild(K("读取中…"));return}if(N.ok!==!0||N.sessions===void 0){x.appendChild(K(`无法读取(${N.error??"未知错误"})`,"error"));return}if(N.sessions.length===0){x.appendChild(K("对端没有可读会话"));return}const I=he("div","wb-chat-sessions"),G=t.now();for(const Y of N.sessions){const me=he("button","wb-chat-session");me.type="button",me.appendChild(he("span","wb-chat-session-id")).textContent=`…${Y.id.slice(-12)}`;const ce=[Y.mtimeMs!==void 0?Vt(Y.mtimeMs,G):"",bo(Y.sizeBytes)].filter(Boolean).join(" · ");me.appendChild(he("span","wb-chat-session-meta")).textContent=ce,me.title=Y.id,me.addEventListener("click",()=>{(e==null?void 0:e.kind)!=="peer"||e.url!==d||(e.picked=Y.id,tt())}),I.appendChild(me)}x.appendChild(I)}function Ae(d=!1){const N=e;if(N===null)return;if(O.textContent=ie(N),O.hidden=O.textContent==="",N.kind==="peer"&&N.picked===void 0){if(N.url===void 0||t.remoteSessionLog===void 0){x.replaceChildren();return}const Y=N.url,me=`peer:${Y}`;if(!d&&l.has(me)){Me(Y,l.get(me));return}l.set(me,void 0),Me(Y,void 0),t.remoteSessionLog({peer:Y}).then(ce=>{l.set(me,ce),(e==null?void 0:e.kind)==="peer"&&e.url===Y&&e.picked===void 0&&Me(Y,ce)},ce=>{const ge={ok:!1,error:ce instanceof Error?ce.message:String(ce)};l.set(me,ge),(e==null?void 0:e.kind)==="peer"&&e.url===Y&&e.picked===void 0&&Me(Y,ge)});return}const I=fe(N);if(I===void 0){x.replaceChildren(),et(!0);return}const G=()=>{const Y=r.get(I);Y===void 0||d?te():(y.scrollTop=Y,requestAnimationFrame(()=>{e!==null&&fe(e)===I&&(y.scrollTop=Y)}))};if(!d&&i.has(I)&&i.get(I)!==void 0){de(i.get(I)),et(!0),G();return}d&&r.delete(I),i.set(I,void 0),de(void 0),et(!0),Ce(N).then(Y=>{var me;i.set(I,Y),(Y==null?void 0:Y.ok)===!0&&Y.messages!==void 0&&((me=t.onTranscript)==null||me.call(t,N,Y.messages)),!(e===null||fe(e)!==I)&&(de(Y),et(),G())},Y=>{const me={ok:!1,error:Y instanceof Error?Y.message:String(Y)};i.set(I,me),e!==null&&fe(e)===I&&de(me)})}function Ve(d){return((n==null?void 0:n.tasks)??[]).filter(N=>N.team===d)}function qe(d){return((n==null?void 0:n.tasksDead)??[]).filter(N=>N.team===d)}let De="";function We(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 Ke(d,N){const I=d.direction==="inbound";if(d.receiptExpected===!1)return{text:I?"来信 · 无需回执":"已送达 · 无回执",tone:"muted",hint:"免回执消息:不等回执,24h 后自动归档"};const G=Tt(d,N),Y=I?G?"待本机回执 · 超 1 小时":"待本机回执":G?"陈旧":"待回执",me=d.status!=="pending"?` · ${d.status}`:"";return{text:`${Y}${me}`,tone:G?"warn":"wait",hint:`${I?"对方等待本机回执;":""}${I?"收到":"派发"}于 ${Vt(d.startedAt,N)}`}}function xt(d,N){const I=`结算于 ${Vt(d.resolvedAt,N)}`;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 ce=d.endedBy==="cancelled"?"撤回":"放弃";return d.late===!0?{text:`已${ce} · 回执迟到`,tone:"warn",hint:`${I};本机${ce}之后对方回执才到,结局不改写`}:{text:`已${ce}`,tone:"muted",hint:`${I};本机${ce},未等到回执`}}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 G=d.summary!==void 0&&d.summary!==""?` · ${d.summary}`:"";if(d.outcome==="abandoned")return{text:"已回执 · 对方放弃",tone:"warn",hint:`${I};对方回执报告放弃${G}`};const Y=tn.find(ce=>ce.key===d.outcome),me=(Y==null?void 0:Y.tone)==="completed"?"ok":(Y==null?void 0:Y.tone)==="failed"?"danger":(Y==null?void 0:Y.tone)==="rejected"?"warn":"muted";return d.outcome==="unclassified"?{text:"已回执",tone:"ok",hint:`${I};回执未带结论${G}`}:{text:`已回执 · ${(Y==null?void 0:Y.label)??d.outcome}`,tone:me,hint:`${I}${G}`}}function rt(d,N,I){const G=qe(N).find(ce=>ce.taskId===d);if(G!==void 0)return We(G);const Y=Ve(N).find(ce=>ce.taskId===d);if(Y!==void 0)return Ke(Y,I);const me=((n==null?void 0:n.archived)??[]).find(ce=>ce.taskId===d&&ce.team===N);return me!==void 0?xt(me,I):c.has(d)?{text:"已离开台账",tone:"muted",hint:"已结算、放弃或撤回之一;主机未给出这条的结局(旧主机,或已超出最近 64 条归档)"}:{text:"已派发",tone:"muted",hint:"异步送达;回执到达后进台账"}}function Ue(d){const N=t.now(),I=m.get(d)??[],G=new Set(I.map(J=>J.taskId).filter(J=>J!==void 0)),Y=J=>J!==void 0&&J!==""?J:"(无摘要)",me=Ve(d).filter(J=>!G.has(J.taskId)).map(J=>({at:J.startedAt,side:J.direction==="inbound"?"theirs":"mine",text:Y(J.brief),status:Ke(J,N),taskId:J.taskId})),ce=qe(d).filter(J=>!G.has(J.taskId)).map(J=>{var ze;const Oe=J.direction??h.get(J.taskId)??(((ze=J.peer)==null?void 0:ze.startsWith("local:"))===!0?"inbound":void 0);return{at:J.startedAt,side:Oe==="inbound"?"theirs":Oe==="outbound"?"mine":"system",text:Y(J.brief),status:We(J),taskId:J.taskId}}),ge=I.map(J=>({at:J.at,side:"mine",text:J.text,status:J.state==="sending"?{text:"发送中…",tone:"muted"}:J.state==="failed"?{text:`失败:${J.error??"未知原因"}`,tone:"danger"}:J.taskId!==void 0?rt(J.taskId,d,N):{text:"已派发",tone:"muted"},taskId:J.taskId}));return[...me,...ce,...ge].sort((J,Oe)=>J.at-Oe.at)}function et(d=!1){const N=e,I=N!==null?qt(N):void 0,G=I!==void 0?Ue(I):[],Y=JSON.stringify([I??"",...G.map(ge=>[ge.taskId??"",ge.side,ge.text,ge.status.text])]);if(!d&&Y===De)return;De=Y;const me=re();if(R.replaceChildren(),G.length===0)return;const ce=he("div","wb-chat-divider");ce.textContent="台账往来 · 异步送达,回执进台账",R.appendChild(ce);for(const ge of G){const J=ge.side==="mine"?"wb-msg wb-msg-user wb-msg-out":ge.side==="theirs"?"wb-msg wb-msg-assistant wb-msg-in":"wb-msg wb-msg-ledger",Oe=he("div",J);Oe.appendChild(he("span","wb-msg-who")).textContent=ge.side==="mine"?"我":ge.side==="theirs"?"对方":"台账记录",Oe.appendChild(he("div","wb-msg-text")).textContent=ge.text;const ze=he("div","wb-msg-meta");ge.taskId!==void 0&&(ze.appendChild(he("span","wb-msg-task")).textContent=ge.taskId);const $e=he("span",`wb-msg-status is-${ge.status.tone}`);$e.textContent=ge.status.text,ge.status.hint!==void 0&&($e.title=ge.status.hint),ze.appendChild($e),Oe.appendChild(ze),R.appendChild(Oe)}me&&te()}function gt(d){const N=d.text.value.length;d.note.classList.remove("is-error"),d.note.textContent=N>At*.9?`${N}/${At}`:"Enter 发送 · Shift+Enter 换行",N>At&&d.note.classList.add("is-error"),d.submit.disabled=d.text.value.trim()===""||N>At}function Se(d){d.style.height="auto",d.style.height=`${Math.min(d.scrollHeight,160)}px`}function He(d){const N=he("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 G=he("button","wb-dispatch-submit");G.type="submit",G.textContent="发送",G.setAttribute("aria-label","发送");const Y=he("div","wb-dispatch-note");Y.setAttribute("aria-live","polite");const me=he("div","wb-chat-composer-row");me.append(I,G),N.append(me,Y);const ce={team:d,form:N,text:I,note:Y,submit:G};return I.addEventListener("input",()=>{Se(I),gt(ce)}),I.addEventListener("keydown",ge=>{ge.key!=="Enter"||ge.shiftKey||ge.ctrlKey||ge.altKey||ge.metaKey||ge.isComposing||(ge.preventDefault(),N.requestSubmit())}),N.addEventListener("submit",ge=>{ge.preventDefault();const J=I.value.trim();if(J===""||J.length>At||t.dispatchQuick===void 0)return;const Oe={text:J,at:t.now(),state:"sending"},ze=m.get(d)??[];ze.push(Oe),m.set(d,ze),I.value="",Se(I),gt(ce),I.focus({preventScroll:!0}),et(),te(),t.dispatchQuick(d,J).then($e=>$e,$e=>({ok:!1,error:$e instanceof Error?$e.message:String($e)})).then($e=>{$e.ok===!0?(Oe.state="sent",Oe.taskId=$e.task_id,Y.classList.remove("is-error"),Y.textContent=`已派发${$e.task_id!==void 0?` · ${$e.task_id}`:""} · 回执将入台账`):(Oe.state="failed",Oe.error=$e.error??"未知原因",I.value===""&&(I.value=J,Se(I)),Y.classList.add("is-error"),Y.textContent=`失败:${Oe.error}`,G.disabled=I.value.trim()===""),e!==null&&qt(e)===d&&et()})}),gt(ce),ce}function Ye(){const d=e;if(D.replaceChildren(),d===null)return;const N=qt(d);if(N!==void 0&&t.dispatchQuick!==void 0){let G=b.get(N);G===void 0&&(G=He(N),b.set(N,G)),D.appendChild(G.form),s&&(s=!1,G.text.focus({preventScroll:!0}));return}s=!1;const I=he("div","wb-chat-readonly");I.textContent=d.kind==="log"?"只读日志:此会话不在网络目录,不能从这里派发。":d.kind==="peer"?"对端主机:选择会话阅读;要派发请打开它的远端会话节点。":"此节点没有可派发的路由。",D.appendChild(I)}function tt(){Le(),z(),Ae(),Ye()}function pt(d){const N=e!==null&&yn(e)===yn(d);e=d,N||(s=!0),tt(),L.classList.add("is-open")}function vt(){e=null,L.classList.remove("is-open")}function at(d){n=d;for(const I of(d==null?void 0:d.tasks)??[])c.add(I.taskId),h.set(I.taskId,I.direction==="inbound"?"inbound":"outbound");const N=e;if(N!==null){if(N.kind==="session"&&d!==null){const I=(d.sessions??[]).find(G=>G.id===N.id);I!==void 0&&(N.title=it(I),N.live=I.live)}Le(),et()}}return{root:L,open:pt,close:vt,isOpen:()=>e!==null,update:at}}const Xn="dsh-a2a.rail.tab";function vo(){try{return window.localStorage.getItem(Xn)}catch{return null}}function yo(t){try{window.localStorage.setItem(Xn,t)}catch{}}function wo(t,e={}){var be;const n=document.createElement("aside");n.className="wb-rail";const s=document.createElement("div");s.className="wb-tabs",s.setAttribute("role","tablist"),s.setAttribute("aria-label","工作台侧栏");const o=document.createElement("div");o.className="wb-tabpanels",n.append(s,o);const i=new Map,r=new Map,l=new Map,m=new Set;for(const $ of t){const p=document.createElement("button");p.type="button",p.className="wb-tab",p.id=`wb-tab-${$.key}`,p.dataset.sec=$.key,p.setAttribute("role","tab"),p.setAttribute("aria-controls",`wb-panel-${$.key}`);const H=document.createElement("span");H.className="wb-tab-label",H.textContent=$.label;const v=document.createElement("span");v.className="wb-tab-badge",p.append(H,v),p.addEventListener("click",()=>T($.key)),s.appendChild(p);const f=document.createElement("section");f.className="wb-tabpanel",f.id=`wb-panel-${$.key}`,f.dataset.sec=$.key,f.setAttribute("role","tabpanel"),f.setAttribute("aria-labelledby",p.id),f.tabIndex=-1,o.appendChild(f),i.set($.key,p),r.set($.key,f),l.set($.key,v)}const c=()=>t.map($=>$.key).filter($=>!m.has($)),h=vo();let b=((be=t.find($=>$.key===h))==null?void 0:be.key)??t[0].key;s.addEventListener("keydown",$=>{const p=c(),H=p.indexOf(b);let v;$.key==="ArrowRight"?v=p[(H+1)%p.length]:$.key==="ArrowLeft"?v=p[(H-1+p.length)%p.length]:$.key==="Home"?v=p[0]:$.key==="End"&&(v=p[p.length-1]),v!==void 0&&($.preventDefault(),T(v,{focus:!0}))});function L(){for(const $ of t){const p=$.key===b,H=i.get($.key);H.setAttribute("aria-selected",String(p)),H.tabIndex=p?0:-1,H.classList.toggle("is-active",p),H.hidden=m.has($.key),r.get($.key).hidden=!p}}function T($,p={}){var v;if(m.has($))return;const H=$!==b;b=$,yo($),L(),p.focus===!0&&i.get($).focus(),H&&((v=e.onChange)==null||v.call(e,$))}function U($,p,H){const v=l.get($);v.textContent=p,v.className=`wb-tab-badge${H!==void 0?` is-${H}`:""}`}function ne($,p){p?m.add($):m.delete($),m.has(b)&&(b=c()[0]??t[0].key),L()}return L(),{root:n,panel:$=>r.get($),select:T,selected:()=>b,setBadge:U,setHidden:ne}}const xo=[{key:"all",label:"全部",hint:"不过滤:目录全部条目"},{key:"local",label:"本机",hint:"本机会话节点(现场 + 冷启动)"},{key:"canvas",label:"队",hint:"画布队(人类手工分配的组队)"},{key:"remote",label:"远端",hint:"远端会话队(来自对端卡片)"},{key:"logs",label:"日志",hint:"本机日志:不在网络目录里的会话档案"}];function Qe(t,e){const n=document.createElement(t);return e!==void 0&&(n.className=e),n}function Dt(...t){const e=[];for(const n of t)n!==void 0&&(typeof n=="string"?e.push(n):e.push(...n));return e.join(" ").toLowerCase()}function Co(t,e){const n=Math.max(0,Math.round((e-t)/1e3));if(n<60)return"刚刚";const s=Math.round(n/60);if(s<60)return`${s} 分钟前`;const o=Math.round(s/60);return o<48?`${o} 小时前`:`${Math.round(o/24)} 天前`}function wn(t){return t>=1e6?`${(t/1e6).toFixed(1)} MB`:t>=1e3?`${Math.round(t/1e3)} KB`:`${t} B`}function ko(t,e){const n=new Date(e);n.setHours(0,0,0,0);const s=n.getTime();return t>=s?"今天":t>=s-864e5?"昨天":"更早"}function Eo(t,e){var H;t.replaceChildren();const{state:n,search:s,filter:o}=e,i=s!==""||o!=="all",r=(v,f)=>(o==="all"||o===v)&&(s===""||f.includes(s)),l=(v,f,M)=>{const y=Qe("div","wb-dir-group"),O=Qe("div","wb-dir-head");return O.appendChild(Qe("span","wb-dir-head-label")).textContent=`${v} · ${f}`,M!==void 0&&(O.appendChild(Qe("span","wb-dir-head-note")).textContent=M),y.appendChild(O),t.appendChild(y),y},m=(v,f,M,y,O,x,R)=>{const D=Qe("button","wb-item");D.type="button",D.appendChild(Qe("span",`wb-dot ${f}`)).textContent=M;const fe=Qe("span","wb-item-text");return fe.appendChild(Qe("span","wb-item-label")).textContent=y,O!==""&&(fe.appendChild(Qe("span","wb-item-sub")).textContent=O),D.appendChild(fe),R!==void 0&&(D.title=R),D.addEventListener("click",x),v.appendChild(D),D},c=(v,f)=>{if(f===void 0||f.length===0)return;const M=Qe("span","wb-item-badge"),y=f.map(O=>O.slice(O.lastIndexOf("/")+1));M.textContent=`▤ ${y.slice(0,2).join(" ")}${y.length>2?` +${y.length-2}`:""}`,M.title=`画布队:${f.join(" · ")}`,v.appendChild(M)},h=(n.sessions??[]).filter(v=>r("local",Dt(it(v),v.team,v.label,v.id,v.canvasTeams))),b=h.filter(v=>v.live===!0),L=h.filter(v=>v.live!==!0);if(h.length>0){const v=l("本机会话",h.length,L.length>0?`${b.length} 在线 · ${L.length} 冷`:void 0);for(const f of[...b,...L]){const M=f.live===!0,y=m(v,M?"wb-dot-live":"wb-dot-cold",M?"●":"○",it(f),M?f.team:`冷 · ${f.team}`,()=>e.openChat({kind:"session",id:f.id,title:it(f),sub:f.team,team:f.team,live:f.live}),f.id);c(y,f.canvasTeams)}}const T=(((H=n.canvas)==null?void 0:H.teams)??[]).filter(v=>r("canvas",Dt(v.name,v.team,v.members.map(f=>f.team??f.id))));if(T.length>0){const v=l("画布队",T.length);for(const f of T){const M=f.members.filter(y=>y.remote===!0).length;m(v,"wb-dot-canvas","▤",f.name,`${f.members.length} 成员${M>0?` · ${M} 远端`:""}`,()=>e.selectCanvas(f),f.team)}}const U=(n.remote??[]).filter(v=>r("remote",Dt(it(v),v.team,v.origin,v.workspace,v.canvasTeams)));if(U.length>0){const v=l("远端节点",U.length);for(const f of U){const M=m(v,"wb-dot-remote","◇",it(f),f.origin!==void 0&&f.origin!==""?f.origin:f.team,()=>e.openChat({kind:"remote",team:f.team,title:it(f),sub:f.team,row:f}),f.team);c(M,f.canvasTeams)}}const ne=new Set((n.sessions??[]).map(v=>v.id)),be=e.logs.filter(v=>!ne.has(v.id)&&r("logs",Dt(v.id,e.titles.get(v.id))));if(be.length>0){const v=e.logTotal!==void 0&&e.logTotal>e.logs.length,f=l("本机日志",be.length,v?`显示 ${e.logs.length} / 共 ${e.logTotal}`:void 0);let M="";for(const y of[...be].sort((O,x)=>x.mtimeMs-O.mtimeMs)){const O=ko(y.mtimeMs,e.now);O!==M&&(M=O,f.appendChild(Qe("div","wb-dir-day")).textContent=O);const x=e.titles.get(y.id),R=m(f,"wb-dot-log","❐",x??`会话 …${y.id.slice(-12)}`,`${Co(y.mtimeMs,e.now)} · ${wn(y.sizeBytes)}`,()=>e.openChat({kind:"log",id:y.id,title:x??`…${y.id.slice(-12)}`,sub:"本机日志"}),`${y.id}
|
|
3
|
+
${new Date(y.mtimeMs).toLocaleString()} · ${wn(y.sizeBytes)}`);x===void 0&&R.classList.add("is-untitled")}}h.length+T.length+U.length+be.length===0&&(t.appendChild(Qe("div","wb-dir-empty")).textContent=i?"无匹配条目":"目录为空");const $=n.sessions??[];return`${$.filter(v=>v.live===!0).length}/${$.length}`}const Kn="dsh-a2a.logtitles",$o=300,xn=60;function No(){try{const t=window.localStorage.getItem(Kn),e=t===null?null:JSON.parse(t);if(e!==null&&typeof e=="object")return new Map(Object.entries(e).filter(n=>typeof n[1]=="string"))}catch{}return new Map}function Mo(t,e,n){const s=n.find(r=>r.role==="user"&&r.text.trim()!=="")??n.find(r=>r.text.trim()!=="");if(s===void 0)return!1;const o=s.text.trim().split(`
|
|
4
|
+
`)[0].trim(),i=o.length>xn?`${o.slice(0,xn-1)}…`:o;if(t.get(e)===i)return!1;for(t.delete(e),t.set(e,i);t.size>$o;)t.delete(t.keys().next().value);try{window.localStorage.setItem(Kn,JSON.stringify(Object.fromEntries(t)))}catch{}return!0}function ct(t){return t.name??t.team??t.label??""}function St(t,e){const n=Math.max(0,Math.round((e-t)/1e3));if(n<90)return`${n}s`;const s=Math.round(n/60);if(s<90)return`${s}m`;const o=Math.round(s/60);return o<48?`${o}h`:`${Math.round(o/24)}d`}function S(t,e){const n=document.createElement(t);return e!==void 0&&(n.className=e),n}function Cn(t,e,n){const s=S("div","wb-kv");s.appendChild(S("span","wb-kv-k")).textContent=e,s.appendChild(S("span","wb-kv-v")).textContent=n,t.appendChild(s)}function Ao(t){try{return new URL(t).host}catch{return t}}const So=[{key:"directory",label:"目录"},{key:"hosts",label:"主机"},{key:"ledger",label:"台账"},{key:"activity",label:"活动"},{key:"plan",label:"规划"}];function Lo(t){const e=t.board;let n="data",s,o=null,i="",r="all",l=null,m=null,c=[],h;const b=No();let L=!1;const T=S("div","wb");T.setAttribute("data-testid","wb-root");const U=S("header","wb-header"),ne=S("button","wb-icon-btn wb-menu");ne.type="button",ne.dataset.testid="wb-menu",ne.setAttribute("aria-label","打开目录抽屉"),ne.textContent="☰",ne.addEventListener("click",()=>T.classList.toggle("is-rail-open")),U.appendChild(ne);const be=S("div","wb-title");be.appendChild(S("span","wb-title-main")).textContent="A2A 工作台";const $=S("span","wb-badge");be.appendChild($),U.appendChild(be);const p=S("button","wb-icon-btn wb-owner-btn");p.type="button",p.dataset.testid="wb-owner-btn",p.setAttribute("aria-label","主人设置(三键面板)"),p.title="主人设置:入网白名单 / 可见性 / 发布",p.textContent="⚙",p.addEventListener("click",()=>{at=!at,N()}),U.appendChild(p);const H=S("div","wb-header-stats");U.appendChild(H);const v=S("button","wb-icon-btn wb-rail-toggle");v.type="button",v.dataset.testid="wb-rail-toggle",v.setAttribute("aria-label","折叠/展开侧栏"),v.textContent="◧",v.addEventListener("click",()=>{T.classList.toggle("is-rail-collapsed"),n==="canvas"&&e!==void 0&&e.activate()}),U.appendChild(v);const f=S("div","wb-body"),M=wo(So),y=M.root,O=S("div","wb-directory"),x=S("div","wb-dir-tools"),R=document.createElement("input");R.className="wb-search",R.type="search",R.placeholder="搜索:名称 / 队 / 会话 / 节点",R.setAttribute("aria-label","统一搜索目录"),R.addEventListener("input",()=>{i=R.value.trim().toLowerCase(),Ke()}),x.appendChild(R);const D=S("div","wb-filters");for(const C of xo){const w=S("button","wb-filter");w.type="button",w.textContent=C.label,w.dataset.filter=C.key,w.title=C.hint,w.addEventListener("click",()=>{r=C.key,Ke()}),D.appendChild(w)}x.appendChild(D),M.panel("directory").appendChild(x),M.panel("directory").appendChild(O);const fe=S("section","wb-pane"),Ce=S("section","wb-pane"),Le=S("section","wb-pane"),P=S("section","wb-pane"),z=[["ledger",fe],["activity",Ce],["plan",Le],["hosts",P]],ie=S("main","wb-stage"),re=S("section","wb-stage-board");e!==void 0&&(re.appendChild(e.root),ie.appendChild(re));const te=S("div","wb-data"),K=S("aside","wb-inspector"),ae=S("div","wb-inspector-head");ae.appendChild(S("span","wb-inspector-title")).textContent="详情";const de=S("button","wb-icon-btn");de.type="button",de.setAttribute("aria-label","关闭详情"),de.textContent="✕",de.addEventListener("click",()=>We(void 0)),ae.appendChild(de),K.appendChild(ae);const Me=S("div","wb-inspector-body");K.appendChild(Me);const Ae=go({now:t.now,sessionLog:t.sessionLog,remoteSessionLog:t.remoteSessionLog,dispatchQuick:t.dispatchQuick,onTranscript:(C,w)=>{C.kind!=="log"&&C.kind!=="session"||Mo(b,C.id,w)&&Ke()}});ie.appendChild(te),f.appendChild(y),f.appendChild(ie),f.appendChild(K),f.appendChild(Ae.root),T.appendChild(U),T.appendChild(f);function Ve(C){for(const[w,A]of z){const _=C==="canvas"?M.panel(w):te;M.setHidden(w,C!=="canvas"),A.parentElement!==_&&_.appendChild(A)}}function qe(){const w=e!==void 0&&e.available()?"canvas":"data";T.dataset.mode=w,re.classList.toggle("is-hidden",w!=="canvas"),te.classList.toggle("is-hidden",w==="canvas"),Ve(w),w!==n&&(e!==void 0&&(w==="canvas"?e.activate():e.deactivate()),n=w)}function De(C){for(;C.firstChild!==null;)C.removeChild(C.firstChild);return C}function We(C){s=C,((C==null?void 0:C.kind)!=="canvas"||(l==null?void 0:l.name)!==C.row.name)&&(l=null),(C==null?void 0:C.kind)!=="canvas"&&(m=null),G(),T.classList.remove("is-rail-open")}function Ke(){for(let w=0;w<D.children.length;w++){const A=D.children[w];A.classList.toggle("is-active",A.dataset.filter===r)}if(o===null){O.replaceChildren(S("div","wb-muted")),O.firstElementChild.textContent="载入中…",M.setBadge("directory","");return}const C=Eo(O,{state:o,logs:c,logTotal:h,titles:b,search:i,filter:r,now:t.now(),openChat:ce,selectCanvas:w=>We({kind:"canvas",row:w})});M.setBadge("directory",C)}function xt(){const C=De(P);if(o===null){M.setBadge("hosts","");return}const w=t.now(),A=[...o.peers??[]].sort((_,F)=>{const j=se=>se.link==="linked"?0:1;return j(_)-j(F)||(F.score??0)-(_.score??0)});if(M.setBadge("hosts",A.length>0?`${A.filter(_=>_.link==="linked").length}/${A.length}`:""),A.length===0){C.appendChild(S("div","wb-nodelist-empty")).textContent="暂无 tracked peer——配 peers 种子或等 referral 到达";return}for(const _ of A){const F=Ao(_.url),j=S("div","wb-host-row"),se=S("span","wb-host-lamp"),oe=_.lastContactAt,Q=oe===void 0?void 0:w-oe,ve=_.lastContactOk;Q===void 0?se.classList.add("is-unknown"):ve===!1&&Q<=5*6e4?se.classList.add("is-fail"):Q<=6e4?se.classList.add("is-live"):Q<=5*6e4?se.classList.add("is-warm"):se.classList.add("is-cold"),se.title=oe===void 0?"尚无接触记录":`最近接触 ${St(oe,w)}${ve===!1?"(失败)":ve===!0?"(成功)":""}`,j.appendChild(se),j.appendChild(S("span","wb-host-name")).textContent=_.name!==void 0&&_.name!==""?_.name:F;const Ie=S("span",`wb-host-badge ${_.link==="linked"?"is-linked":"is-stranger"}`);Ie.textContent=`${_.link==="linked"?"linked":"stranger"} ${_.verified===!0?"✓":"✗"}`,Ie.title=_.link==="linked"?`已建立运营者链接(互种或 canvas 引用);${_.verified===!0?"验签有效":"尚未持有验签通过的卡片"}`:"无运营者关系(验签 ≠ 关系)",j.appendChild(Ie),_.version!==void 0&&_.version!==""&&(j.appendChild(S("span","wb-host-ver")).textContent=_.version),j.appendChild(S("span","wb-host-url mono")).textContent=F,j.setAttribute("role","button"),j.tabIndex=0,j.title=`${_.url} · score ${String(_.score??0)}`;const Z=()=>{ce({kind:"peer",id:`peer-${F}`,title:_.name!==void 0&&_.name!==""?_.name:F,sub:F,url:_.url})};j.addEventListener("click",Z),j.addEventListener("keydown",Te=>{(Te.key==="Enter"||Te.key===" ")&&(Te.preventDefault(),Z())}),C.appendChild(j)}}function rt(){if(o===null){fe.replaceChildren(),M.setBadge("ledger","");return}const C=o,w=_=>{const F=(C.sessions??[]).find(se=>se.team===_);if(F!==void 0)return{kind:"session",id:F.id,title:ct(F),sub:F.team,team:F.team,live:F.live};const j=(C.remote??[]).find(se=>se.team===_);if(j!==void 0)return{kind:"remote",team:j.team,title:ct(j),sub:j.team,row:j}},A=po(fe,{state:C,now:t.now(),abandon:(_,F)=>t.abandon(_,F),canOpenTeam:_=>w(_)!==void 0,openTeam:_=>{const F=w(_);return F===void 0?!1:(ce(F),!0)}});M.setBadge("ledger",A.badge,A.tone)}function Ue(C,w,A){Yt(C.appendChild(S("span","wb-row-team")),w,A)}function et(){var se;const C=De(Ce);if(o===null)return;const w=t.now(),A=o.inFlight??[];M.setBadge("activity",A.length>0?String(A.length):"",A.length>0?"accent":void 0);const _=S("div","wb-pane-head");if(_.textContent=`在途 ${A.length} · 活动 ${((se=o.activity)==null?void 0:se.length)??0}`,C.appendChild(_),A.length>0){const oe=S("div","wb-pane-subhead");oe.textContent="在途路由",C.appendChild(oe);for(const Q of A){const ve=S("div","wb-row");ve.appendChild(S("span","wb-row-dir")).textContent="→",Ue(ve,o,Q.team),ve.appendChild(S("span","wb-row-meta")).textContent=`${Q.peer} · ${St(Q.startedAt,w)}`,C.appendChild(ve)}}const F=S("div","wb-pane-subhead");F.textContent="活动环(最新在前)",C.appendChild(F);const j=o.activity??[];if(j.length===0){C.appendChild(S("div","wb-muted")).textContent="暂无活动";return}for(const oe of j){const Q=S("div","wb-row"),ve=S("span","wb-row-dir");ve.textContent=oe.dir==="out"?"→":"←",oe.ok!==!0&&ve.classList.add("is-fail"),Q.appendChild(ve),Ue(Q,o,oe.team),Q.appendChild(S("span","wb-row-meta")).textContent=`${oe.peer} · ${St(oe.ts,w)}`,Q.appendChild(S("span","wb-row-badges")).textContent=oe.ok===!0?"":"失败",C.appendChild(Q)}}function gt(C){var se,oe;const w=t.now(),A=[],_=en(C,w);_.deadLetters.length>0&&A.push({severity:"high",text:`清账 ${_.deadLetters.length} 条死信(目标早已离开或死信化,无回执可期)`});for(const Q of _.stale){const ve=Q.brief===void 0||Q.brief===""?"":`「${Q.brief}」`;A.push({severity:"normal",text:`催办 ${Q.taskId} → ${mo(C,Q.team)}(等待 ${St(Q.startedAt,w)} 无回执)${ve}`,brief:`a2a_route 催收回执:task ${Q.taskId}(team ${Q.team})${ve===""?"":`原任务「${Q.brief}」`}已派发 ${St(Q.startedAt,w)},请回报结果或回执。`})}const F=(C.sessions??[]).filter(Q=>Q.live!==!0).map(Q=>ct(Q));if(F.length>0){const Q=F.slice(0,3).join("、")+(F.length>3?` 等 ${F.length} 个`:"");A.push({severity:"normal",text:`冷会话 ${F.length} 个(${Q}):在 GUI 打开即可唤醒加入面`})}for(const Q of((se=C.reconcile)==null?void 0:se.rows)??[])if(Q.needsRepair===!0){const ve=(C.sessions??[]).find(Z=>Z.id===Q.id),Ie=ve!==void 0?`${ct(ve)}(${Q.id})`:Q.id;A.push({severity:"high",text:`reconcile 需修复:${Ie} ${Q.error}`})}const j=((oe=C.idempotency)==null?void 0:oe.conflicts)??0;return j>0&&A.push({severity:"high",text:`幂等冲突 ${j} 例:人工核查 UNIQUE-ization 流量`}),A}function Se(){const C=De(Le);if(o===null)return;const w=gt(o);M.setBadge("plan",w.length>0?String(w.length):"",w.some(F=>F.severity==="high")?"danger":void 0);const A=S("div","wb-pane-head");A.textContent=w.length===0?"网络健康——无待办行动":`待办行动 ${w.length}`,C.appendChild(A);for(const F of w){const j=S("div",`wb-action${F.severity==="high"?" wb-action-high":""}`);if(j.appendChild(S("span","wb-action-text")).textContent=F.text,F.brief!==void 0){const se=S("button","wb-btn");se.type="button",se.textContent="复制催办",se.addEventListener("click",()=>t.copy(F.brief??"")),j.appendChild(se)}C.appendChild(j)}const _=S("div","wb-pane-subhead");_.textContent="派单起草(复制后在任一会话粘贴执行)",C.appendChild(_),C.appendChild(He)}const He=S("div","wb-draft"),Ye=document.createElement("select");Ye.className="wb-select";const tt=document.createElement("textarea");tt.className="wb-textarea",tt.rows=3,tt.placeholder="任务正文:目标、验收、期限…";const pt=S("button","wb-btn wb-btn-primary");pt.type="button",pt.textContent="复制任务书",pt.addEventListener("click",()=>{const C=Ye.value,w=tt.value.trim();C===""||w===""||t.copy(`a2a_route 派单 → ${C}:
|
|
5
|
+
${w}`)}),He.appendChild(Ye),He.appendChild(tt),He.appendChild(pt);function vt(){var F;const C=Ye.value;De(Ye);const w=document.createElement("option");if(w.value="",w.textContent="选择目标队…",Ye.appendChild(w),o===null)return;const A=o,_=new Map;for(const j of A.sessions??[])j.team!==void 0&&j.team!==""&&_.set(j.team,`${ct(j)}(会话队)`);for(const j of((F=A.canvas)==null?void 0:F.teams)??[])_.set(j.team,`${j.name}(canvas 队)`);for(const j of A.remote??[])_.set(j.team,`${ct(j)}(远端)`);for(const[j,se]of _){const oe=document.createElement("option");oe.value=j,oe.textContent=`${se} · ${j}`,Ye.appendChild(oe)}C!==""&&_.has(C)&&(Ye.value=C)}let at=!1,d=null;function N(){var C;G(),at&&((C=t.ownerSettingsRead)==null||C.call(t).then(w=>{if(at){if(w.ok!==!0){d=null,G();return}d={teamJoinAllowlist:w.teamJoinAllowlist??[],teamScopeInfo:w.teamScopeInfo!==!1,announce:w.announce===!0,announceRestartPending:w.announceRestartPending===!0},G()}}))}function I(C){const w=S("div","wb-card"),A=S("div","wb-inspector-head");A.appendChild(S("span","wb-inspector-title")).textContent="主人设置";const _=S("button","wb-icon-btn");if(_.type="button",_.setAttribute("aria-label","关闭主人设置"),_.textContent="✕",_.addEventListener("click",()=>{at=!1,G()}),A.appendChild(_),w.appendChild(A),t.ownerSettingsRead===void 0){const xe=S("div","wb-hint");xe.textContent="此宿主未提供主人设置面(旧版本)——升级后可用。",w.appendChild(xe),C.appendChild(w);return}if(d===null){const xe=S("div","wb-hint");xe.textContent="读取中…",w.appendChild(xe),C.appendChild(w);return}const F=d,j=S("div","wb-side-head");j.textContent="入网白名单(精确团队名)",w.appendChild(j);for(const xe of F.teamJoinAllowlist){const nt=S("div","wb-member-row");nt.appendChild(S("span","wb-member-label")).textContent=xe;const dt=S("button","wb-member-remove");dt.type="button",dt.textContent="移除",dt.addEventListener("click",()=>{var _t;(_t=t.ownerSettingsWrite)==null||_t.call(t,{teamJoinAllowlist:F.teamJoinAllowlist.filter(Ot=>Ot!==xe)}).then(()=>N())}),nt.appendChild(dt),w.appendChild(nt)}const se=S("div","wb-member-add"),oe=S("input","wb-member-manual");oe.type="text",oe.placeholder="dsh/团队名(精确,无通配)",oe.setAttribute("aria-label","新增白名单团队名");const Q=S("button","wb-member-submit");Q.type="button",Q.textContent="加入";const ve=()=>{var nt;const xe=oe.value.trim();xe===""||F.teamJoinAllowlist.includes(xe)||(nt=t.ownerSettingsWrite)==null||nt.call(t,{teamJoinAllowlist:[...F.teamJoinAllowlist,xe]}).then(()=>N())};Q.addEventListener("click",ve),oe.addEventListener("keydown",xe=>{xe.key==="Enter"&&ve()}),se.append(oe,Q),w.appendChild(se);const Ie=S("div","wb-side-head");Ie.textContent="目录可见性(teamScopeInfo)",w.appendChild(Ie);const Z=S("div","wb-member-row"),Te=S("button","wb-member-submit");Te.type="button",Te.textContent=F.teamScopeInfo?"已开:仅显示已加入团队(点击放开为全舰队可见)":"已关:全舰队可见(点击收窄为已加入团队)",Te.addEventListener("click",()=>{var xe;(xe=t.ownerSettingsWrite)==null||xe.call(t,{teamScopeInfo:!F.teamScopeInfo}).then(()=>N())}),Z.appendChild(Te),w.appendChild(Z);const Re=S("div","wb-hint");Re.textContent="精度说明:teamScopeInfo 只管「目录显示范围」。关上它不会解锁任何通信准入——会话入网(S3)与目标级路由(F5)规则原样生效。",w.appendChild(Re);const Ge=S("div","wb-side-head");Ge.textContent="节点发布(announce)",w.appendChild(Ge);const lt=S("div","wb-member-row"),Xe=S("button","wb-member-submit");if(Xe.type="button",Xe.textContent=F.announce?"已开:本节点发布签名卡(点击关闭)":"已关:本节点不发布(点击开启——重启宿主后生效)",Xe.addEventListener("click",()=>{var xe;(xe=t.ownerSettingsWrite)==null||xe.call(t,{announce:!F.announce}).then(()=>N())}),lt.appendChild(Xe),w.appendChild(lt),F.announceRestartPending){const xe=S("div","wb-hint");xe.textContent="有 announce 变更待生效:重启宿主后按新配置发布。",w.appendChild(xe)}C.appendChild(w)}function G(){var _;const C=De(Me);if(at){K.classList.add("is-open"),I(C);return}if(K.classList.toggle("is-open",s!==void 0),s===void 0)return;const w=s,A=S("div","wb-card");if(w.kind==="canvas"){const F=(((_=o==null?void 0:o.canvas)==null?void 0:_.teams)??[]).find(Z=>Z.name===w.row.name)??w.row;Cn(A,"Canvas 队",F.name),Cn(A,"路由队",F.team);const j=S("div","wb-side-head");if(j.textContent=`成员 · ${F.members.length}`,A.appendChild(j),F.members.length===0){const Z=S("div","wb-muted");Z.textContent="空队——用下方表单添加成员",A.appendChild(Z)}for(const Z of F.members){const Te=S("div","wb-member-row"),Re=Z.remote===!0?"◇ 远端":Z.live===!0?"● 现场":Z.joined===!0?"○ 冷启":"· 未入网";Te.appendChild(S("span","wb-member-dot")).textContent=Re;const Ge=S("span","wb-member-label"),lt=((o==null?void 0:o.sessions)??[]).find(xe=>xe.id===Z.id);Ge.textContent=Z.remote===!0?Z.id:lt!==void 0?ct(lt):Z.id,Ge.title=Z.team??Z.id,Te.appendChild(Ge);const Xe=S("button","wb-member-remove");Xe.type="button",Xe.textContent="移除",Xe.addEventListener("click",async()=>{Xe.disabled=!0,await t.canvasOp("remove-member",F.name,Z.id)||(Xe.disabled=!1)}),Te.appendChild(Xe),A.appendChild(Te)}if((l==null?void 0:l.name)!==F.name){const Z=S("form","wb-member-add"),Te=document.createElement("select");Te.className="wb-member-pick",Te.setAttribute("aria-label","选择成员");const Re=document.createElement("input");Re.type="text",Re.className="wb-member-manual",Re.placeholder="或输入远端句柄 zone/id8",Re.setAttribute("aria-label","远端成员句柄");const Ge=S("button","wb-member-submit");Ge.type="submit",Ge.textContent="添加",Z.appendChild(Te),Z.appendChild(Re),Z.appendChild(Ge),Z.addEventListener("submit",async lt=>{lt.preventDefault();const Xe=Re.value.trim(),xe=Xe!==""?Xe:Te.value;if(xe==="")return;Ge.disabled=!0;const nt=await t.canvasOp("add-member",F.name,xe);Ge.disabled=!1,nt&&(Re.value="")}),l={name:F.name,form:Z,pick:Te,manual:Re}}const se=l.pick,oe=se.value;De(se),se.appendChild(new Option("本机会话(现场/冷启动)…","",!0,!0));const Q=new Set(F.members.map(Z=>Z.id));for(const Z of(o==null?void 0:o.sessions)??[])Q.has(Z.id)||se.appendChild(new Option(`${ct(Z)} — 本机`,Z.id));let ve=!1;for(const Z of(o==null?void 0:o.remote)??[])Z.team.includes("/")&&(Q.has(Z.team)||(ve||(se.appendChild(new Option("远端会话队(目录卡片)…","",!0,!1)),ve=!0),se.appendChild(new Option(`${ct(Z)} — 远端`,Z.team))));ve||se.appendChild(new Option("(暂无可拉入的远端会话队——见下方说明)","",!0,!1)),oe!==""&&Array.from(se.options).some(Z=>Z.value===oe)&&(se.value=oe),A.appendChild(l.form);const Ie=S("div","wb-hint");Ie.textContent="成员由人类在此手工分配(agent 不可自组队)。远端成员走对端目录路由,不做本机冷唤醒;地址由目录在派发时重解析。远端下拉只列 zone/id8 会话句柄——若为空,说明目录里还没有已链接对端的会话队(未链接的对端只给最小卡);此时可在输入框手输句柄(如 dsh/xxxxxxxx)先把人拉进来,句柄本身即链接手势。",A.appendChild(Ie),t.dispatchQuick!==void 0&&A.appendChild(me(F.team))}C.appendChild(A)}function Y(C){const w=S("form","wb-dispatch-form"),A=document.createElement("textarea");A.className="wb-dispatch-text",A.placeholder="一句话任务…(≤4000 字符,异步送达,回执进台账)",A.setAttribute("aria-label","快派消息");const _=S("button","wb-dispatch-submit");_.type="submit",_.textContent="发送";const F=S("div","wb-dispatch-note");return w.appendChild(A),w.appendChild(_),w.appendChild(F),A.addEventListener("keydown",j=>{j.key!=="Enter"||j.shiftKey||j.ctrlKey||j.altKey||j.metaKey||j.isComposing||(j.preventDefault(),_.disabled||w.requestSubmit())}),w.addEventListener("submit",async j=>{var Q;j.preventDefault();const se=A.value.trim();if(se===""||_.disabled)return;_.disabled=!0,F.textContent="派发中…";let oe;try{oe=await(((Q=t.dispatchQuick)==null?void 0:Q.call(t,C,se))??Promise.resolve({ok:!1,error:"dispatch unavailable"}))}catch(ve){oe={ok:!1,error:ve instanceof Error?ve.message:String(ve)}}_.disabled=!1,oe.ok===!0&&(A.value=""),A.focus({preventScroll:!0}),F.textContent=oe.ok===!0?`已派发${oe.task_id!==void 0?` · ${oe.task_id}`:""} · 回执将入台账(待回执)`:`失败:${oe.error??"未知原因"}`}),{form:w,text:A,note:F}}function me(C){const w=S("div","wb-dispatch"),A=S("div","wb-side-head");return A.textContent="快派",w.appendChild(A),(m==null?void 0:m.team)!==C&&(m={team:C,...Y(C)}),w.appendChild(m.form),w}function ce(C){Ae.open(C),T.classList.remove("is-rail-open")}function ge(C){if(o===null)return;const w=(o.sessions??[]).find(_=>_.id===C);if(w!==void 0){ce({kind:"session",id:C,title:ct(w),sub:w.team,team:w.team,live:w.live});return}if(C.startsWith("peer-")){const _=C.slice(5),F=(o.peers??[]).find(j=>j.url.includes(_));ce({kind:"peer",id:C,title:F!==void 0?F.url:_,sub:_,url:F==null?void 0:F.url});return}c.find(_=>_.id===C)!==void 0&&ce({kind:"log",id:C,title:`…${C.slice(-12)}`,sub:"档案"})}function J(){var Q,ve;$.textContent=(o==null?void 0:o.version)!==void 0?`v${o.version}`:"",$.hidden=(o==null?void 0:o.version)===void 0;const C=De(H);if(o===null)return;const w=[],A=en(o,t.now()),_=A.deadLetters.length;_>0&&w.push({text:`死信 ${_}`,tone:"danger",title:"超过 24h TTL 仍未结算的任务(unconsumed),需在台账清账",tab:"ledger",group:"死信"});const F=A.stale.length;F>0&&w.push({text:`陈旧 ${F}`,tone:"warn",title:"我方派发、要回执、已等待 ≥1h 仍未回执(可催办;免回执行不算)",tab:"ledger",group:"陈旧"});const j=A.owedOverdue.length;j>0&&w.push({text:`欠回执 ${j}`,tone:"warn",title:"对方投递给本机、已等待本机回执超过 1 小时",tab:"ledger",group:"待本机回执"});const se=((Q=o.idempotency)==null?void 0:Q.conflicts)??0;se>0&&w.push({text:`幂等冲突 ${se}`,tone:"danger",title:"同一幂等键对应了不同载荷,需人工核查",tab:"ledger",group:"取证"});const oe=(((ve=o.reconcile)==null?void 0:ve.rows)??[]).filter(Ie=>Ie.needsRepair===!0).length;if(oe>0&&w.push({text:`需修复 ${oe}`,tone:"danger",title:"reconcile 无法自动恢复的会话,见行动计划",tab:"plan"}),w.length===0){C.appendChild(S("span","wb-header-ok")).textContent="● 无异常";return}for(const Ie of w){const Z=S("button",`wb-alert wb-alert-${Ie.tone}`);Z.type="button",Z.textContent=Ie.text,Z.title=`${Ie.title}(点击查看)`,Z.addEventListener("click",()=>Oe(Ie.tab,Ie.group)),C.appendChild(Z)}}function Oe(C,w){var F;const A=z.find(([j])=>j===C)[1];n==="canvas"&&(T.classList.add("is-rail-open"),M.select(C,{focus:!1}));const _=w===void 0?A:w==="取证"?A.querySelector("details.wb-led-forensics"):Array.from(A.querySelectorAll(".wb-led-group")).find(j=>j.dataset.group===w)??null;_!==null&&(_ instanceof HTMLDetailsElement&&(_.open=!0),(F=_.scrollIntoView)==null||F.call(_,{block:"start",behavior:"smooth"}))}function ze(C){o=C,t.sessionLogList!==void 0&&!L&&(L=!0,t.sessionLogList().then(w=>{c=w.ok&&w.sessions!==void 0?w.sessions:[],h=w.ok?w.count:void 0}).catch(()=>{}).finally(()=>{L=!1,Ke()})),J(),Ke(),vt(),xt(),rt(),Ae.update(C),et(),Se(),G(),qe()}function $e(C){if(C==="board"){qe();return}M.select(C)}return ze(null),{root:T,update:ze,mode:()=>n,selectTab:$e,openNodeChat:ge}}const bt=1e6,ln=.25,cn=3,Un=256,zn=96;function Mt(t){const e=typeof t=="number"?t:Number.NaN;if(Number.isFinite(e))return Math.max(-bt,Math.min(bt,Math.round(e)))}function Gn(t){if(t===null||typeof t!="object")return;const e=t,n=Mt(e.x),s=Mt(e.y);return n===void 0||s===void 0?void 0:{x:n,y:s}}function Io(t){const e=Gn(t);if(e===void 0)return;const n=t,s=Mt(n.w),o=Mt(n.h);if(!(s===void 0||o===void 0||s<=0||o<=0))return{...e,w:Math.min(s,bt),h:Math.min(o,bt)}}function Jn(t){if(t===null||typeof t!="object")return;const e=t;if(e.version!==1)return;const n=e.viewport;if(n===null||typeof n!="object")return;const s=n,o=Mt(s.x),i=Mt(s.y),r=s.scale,l=typeof r=="number"?r:Number.NaN;if(o===void 0||i===void 0||!Number.isFinite(l))return;const m=Math.max(ln,Math.min(cn,l)),c={};if(e.nodes!==null&&typeof e.nodes=="object")for(const[b,L]of Object.entries(e.nodes)){if(typeof b!="string"||b===""||b.length>128)continue;const T=Gn(L);if(T!==void 0&&(c[b]=T),Object.keys(c).length>=Un)break}const h={};if(e.frames!==null&&typeof e.frames=="object")for(const[b,L]of Object.entries(e.frames)){if(typeof b!="string"||b===""||b.includes("/")||b.length>40)continue;const T=Io(L);if(T!==void 0&&(h[b]=T),Object.keys(h).length>=zn)break}return{version:1,viewport:{x:o,y:i,scale:m},nodes:c,frames:h}}function To(t,e,n){const s=r=>Math.max(-bt,Math.min(bt,Math.round(r))),o={};for(const[r,l]of e)if(!(typeof r!="string"||r===""||r.length>128)&&(o[r]={x:s(l.x),y:s(l.y)},Object.keys(o).length>=Un))break;const i={};for(const[r,l]of n){if(typeof r!="string"||r===""||r.includes("/")||r.length>40)continue;const m=s(l.w),c=s(l.h);if(!(m<=0||c<=0)&&(i[r]={x:s(l.x),y:s(l.y),w:Math.min(m,bt),h:Math.min(c,bt)},Object.keys(i).length>=zn))break}return{version:1,viewport:{x:s(t.x),y:s(t.y),scale:Math.max(ln,Math.min(cn,t.scale))},nodes:o,frames:i}}function Vn(t){let e=2166136261;for(let n=0;n<t.length;n++)e^=t.charCodeAt(n),e=Math.imul(e,16777619)>>>0;return e>>>0}const je=172,Fe=56,yt=[150,290,430],Ze=16;function _o(t){const e=Vn(t),n=Math.floor(e/Ze)%yt.length,o=e%Ze/Ze*Math.PI*2+n*(Math.PI/Ze),i=yt[n];return{x:Math.round(Math.cos(o)*i),y:Math.round(Math.sin(o)*i*.6)}}function qn(t){const e=new Map;for(const n of t)for(const s of n.members)e.has(s.id)||e.set(s.id,n.name);return e}const kn=64,En=24,$n=20,Oo=4,Nn=24,Mn=44,Po=24;function Fo(t,e,n=Number.POSITIVE_INFINITY){const s=new Set(e),o=qn(t),i=t.map(b=>[...new Set(b.members.map(L=>L.id))].filter(L=>s.has(L)&&o.get(L)===b.name));i.push(e.filter(b=>!o.has(b)));const r=new Map;let l=0,m=0,c=0,h=0;for(const b of i){if(b.length===0)continue;const L=Math.min(3,Math.max(b.length>1?2:1,Math.ceil(Math.sqrt(b.length)))),T=Math.ceil(b.length/L),U=Math.max(260,L*je+(L-1)*En+Nn*2),ne=Math.max(160,T*Fe+(T-1)*$n+Mn+Po);h>0&&(h%Oo===0||l+U>n)&&(l=0,m+=c+kn,c=0),b.forEach((be,$)=>{const p=$%L,H=Math.floor($/L);r.set(be,{x:l+Nn+je/2+p*(je+En),y:m+Mn+Fe/2+H*(Fe+$n)})}),l+=U+kn,c=Math.max(c,ne),h+=1}return r}const Rt=12;function Qn(t,e){const n=m=>e.every(c=>Math.abs(c.x-m.x)>=je+Rt||Math.abs(c.y-m.y)>=Fe+Rt),s=_o(t);if(n(s))return s;const o=Vn(t),i=Ze*yt.length,r=Math.floor(o/Ze)%yt.length*Ze+o%Ze;for(let m=1;m<i;m++){const c=(r+m)%i,h=Math.floor(c/Ze),b=c%Ze/Ze*Math.PI*2+h*(Math.PI/Ze),L=yt[h],T={x:Math.round(Math.cos(b)*L),y:Math.round(Math.sin(b)*L*.6)};if(n(T))return T}const l=yt[yt.length-1];for(let m=0;;m++)for(let c=0;c<6;c++){const h={x:Math.round(-l+c*(je+Rt)),y:Math.round(l*.6+Fe*2+m*(Fe+Rt))};if(n(h))return h}}function ut(t){return{x:t.x-je/2,y:t.y-Fe/2,w:je,h:Fe}}function dn(t){if(t.length===0)return{x:0,y:0,w:260,h:160};let e=Number.POSITIVE_INFINITY,n=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY,o=Number.NEGATIVE_INFINITY;for(const h of t)e=Math.min(e,h.x),n=Math.min(n,h.y),s=Math.max(s,h.x+h.w),o=Math.max(o,h.y+h.h);const i=24,r=44,l=24,m=Math.max(260,Math.round(s-e+i*2)),c=Math.max(160,Math.round(o-n+r+l));return{x:Math.round(e-i),y:Math.round(n-r),w:m,h:c}}class mn{constructor(){kt(this,"revisionCounter",0);kt(this,"nodes",new Map);kt(this,"frames",new Map);kt(this,"selection",new Set);kt(this,"viewport",{x:0,y:0,scale:1})}get revision(){return this.revisionCounter}getNode(e){return this.nodes.get(e)}allNodes(){return[...this.nodes.values()]}nodeIds(){return[...this.nodes.keys()]}getFrame(e){return this.frames.get(e)}allFrames(){return[...this.frames.entries()]}isSelected(e){return this.selection.has(e)}selectedIds(){return[...this.selection]}bump(){this.revisionCounter+=1}dragNodes(e,n,s){let o=!1;for(const i of e){const r=this.nodes.get(i);r!==void 0&&(r.x+=n,r.y+=s,o=!0)}o&&this.bump()}beginFrameDrag(e){const n=this.frames.get(e);if(n===void 0)return;const s=[];for(const o of this.nodes.values())for(const i of o.memberships)if(i.team===e){s.push([o.id,o.x,o.y]);break}return{name:e,rect:{...n},centers:s}}applyFrameDrag(e,n,s){const o=this.frames.get(e.name);if(o!==void 0){o.x=e.rect.x+n,o.y=e.rect.y+s;for(const[i,r,l]of e.centers){const m=this.nodes.get(i);m!==void 0&&(m.x=r+n,m.y=l+s)}this.bump()}}nudge(e,n,s){this.dragNodes(e,n,s)}marqueeSelect(e,n){n||this.selection.clear();for(const s of this.nodes.values()){const o=ut(s);o.x<e.x+e.w&&o.x+o.w>e.x&&o.y<e.y+e.h&&o.y+o.h>e.y&&this.selection.add(s.id)}this.bump()}setSelection(e){this.selection=new Set(e),this.bump()}upsertNode(e){const n=this.nodes.get(e.id);if(n===void 0){this.nodes.set(e.id,e),this.bump();return}n.label=e.label,n.name=e.name,n.description=e.description,n.live=e.live,n.memberships=e.memberships,this.bump()}removeNode(e){this.nodes.delete(e)&&(this.selection.delete(e),this.bump())}setFrame(e,n){this.frames.set(e,n),this.bump()}removeFrame(e){this.frames.delete(e)&&this.bump()}upsertScore(e,n){const s=this.nodes.get(e);s===void 0||s.score===n||(s.score=n,this.bump())}positions(){const e=new Map;for(const[n,s]of this.nodes)e.set(n,{x:s.x,y:s.y});return e}frameRects(){const e=new Map;for(const[n,s]of this.frames)e.set(n,{...s});return e}teamMemberIds(e){const n=[];for(const s of this.nodes.values()){const o=s.memberships.find(i=>i.team===e);o!==void 0&&n.push({id:s.id,index:o.index})}return n.sort((s,o)=>s.index-o.index).map(s=>s.id)}setTeamMembers(e,n){for(const s of this.nodes.values()){const o=s.memberships.filter(r=>r.team!==e),i=n.indexOf(s.id);i>=0&&o.push({team:e,index:i}),s.memberships=o}this.bump()}contentBounds(){let e=Number.POSITIVE_INFINITY,n=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY,o=Number.NEGATIVE_INFINITY;const i=r=>{e=Math.min(e,r.x),n=Math.min(n,r.y),s=Math.max(s,r.x+r.w),o=Math.max(o,r.y+r.h)};for(const r of this.nodes.values())r.remote!==!0&&i(ut(r));for(const r of this.frames.values())i(r);return e===Number.POSITIVE_INFINITY?null:{minX:e,minY:n,maxX:s,maxY:o}}static fromState(e){const n=new mn,s=Jn(e.layout),o=new Map;for(const i of e.teams)for(let r=0;r<i.members.length;r++){const l=i.members[r].id,m=o.get(l)??[];m.push({team:i.name,index:r}),o.set(l,m)}for(const i of e.sessions){if(i.joined!==!0)continue;const r=s==null?void 0:s.nodes[i.id];let l,m;if(r!==void 0&&typeof r.x=="number"&&typeof r.y=="number")l=r.x,m=r.y;else{const c=Qn(i.id,[...n.nodes.values()]);l=c.x,m=c.y}n.nodes.set(i.id,{id:i.id,x:l,y:m,label:i.label,team:i.team,name:i.name,description:i.description,live:i.live!==!1,memberships:o.get(i.id)??[]})}for(const i of e.teams){const r=s==null?void 0:s.frames[i.name];if(r!==void 0){n.frames.set(i.name,{x:r.x,y:r.y,w:r.w,h:r.h});continue}const l=[];for(const m of i.members){const c=n.nodes.get(m.id);c!==void 0&&l.push(ut(c))}l.length>0&&n.frames.set(i.name,dn(l))}return n.viewport=s!==void 0?{...s.viewport}:{x:0,y:0,scale:1},n}}const Do=24,Zn=-13,Ro=Zn+Do;function Bo(t,e,n){const s=[],o=new Set;for(const i of t){const r=e.get(i.name);if(r===void 0)continue;const l=r.x+r.w/2,m=r.y+Ro;for(const c of i.members){const h=n.get(c.id);if(h===void 0)continue;const b=o.has(c.id);o.add(c.id),s.push({x1:l,y1:m,x2:h.x,y2:h.y-Fe/2,dashed:b,team:i.name,id:c.id})}}return s}function jo(t){return`peer-${Nt(t).replace(/[^A-Za-z0-9.:\[\]-]/g,"-")}`}function Nt(t){try{return new URL(t).host}catch{return t}}function Ho(t){const e=new Map;for(const n of t){const s=n.via!==void 0&&n.via!==""?Nt(n.via):"",o=e.get(s)??[];o.push(n),e.set(s,o)}return e}const Yo=140,Wo=200,Xo=90,Ko=20,Bt=60;function Uo(t,e){const n=e!==null?e.maxX+Yo:Wo,s=e!==null?e.minY:0;return t.map((o,i)=>({url:o.url,score:o.score,x:n,y:s+i*Xo}))}function zo(t,e,n,s){const o=new Map;for(const r of t){if(!e.has(r.team))continue;const l=`${r.team}\0${r.peer}`,m=o.get(l);m===void 0?o.set(l,{team:r.team,peer:r.peer,startedAt:r.startedAt,count:1}):(m.startedAt=Math.min(m.startedAt,r.startedAt),m.count+=1)}const i=[];for(const r of o.values()){const l=e.get(r.team);if(l===void 0)continue;const m=n.find(h=>{try{return new URL(h.url).host===r.peer}catch{return!1}});if(m===void 0)continue;const c=Math.max(0,Math.round((s-r.startedAt)/1e3));i.push({x1:l.x,y1:l.y,x2:m.x,y2:m.y,label:`a2a_route · ${r.peer} · ${c}s`+(r.count>1?` ×${r.count}`:"")})}return i}function Go(t,e){const n=e!==null?{x:e.maxX+Ko,y:t.length>0?(t[0].y+t[t.length-1].y)/2:(e.minY+e.maxY)/2}:{x:-80,y:0};return t.map((s,o)=>({x1:n.x,y1:n.y,x2:s.x,y2:s.y,label:o===0?"gns referral":""}))}function Jo(t,e){if(t===null&&e.length===0)return null;let n=t!==null?t.minX:Number.POSITIVE_INFINITY,s=t!==null?t.minY:Number.POSITIVE_INFINITY,o=t!==null?t.maxX:Number.NEGATIVE_INFINITY,i=t!==null?t.maxY:Number.NEGATIVE_INFINITY;for(const r of e)n=Math.min(n,r.x-Bt),s=Math.min(s,r.y-Bt),o=Math.max(o,r.x+Bt),i=Math.max(i,r.y+Bt);return{minX:n,minY:s,maxX:o,maxY:i}}const Vo=11;function qo(t,e){let n=[],s=[],o=[];function i(l){for(const h of n)h.remove();n=[];const m=e.allNodes().filter(h=>h.remote===!0).map(h=>({url:h.peerUrl??h.id.slice(5),score:h.score,x:h.x,y:h.y}));s=m;const c=e.contentBounds();if(c!==null){const h=new Map;for(const[b,L]of e.allFrames())h.set(b,{name:b,x:L.x+L.w/2,y:L.y+Vo});for(const b of zo(o,h,m,l))n.push(...r(b,"e-activity",b.label));for(const b of Go(m,c))n.push(...r(b,"e-federal",b.label))}}function r(l,m,c){const h=document.createElementNS("http://www.w3.org/2000/svg","line");h.setAttribute("class",m),h.setAttribute("x1",String(l.x1)),h.setAttribute("y1",String(l.y1)),h.setAttribute("x2",String(l.x2)),h.setAttribute("y2",String(l.y2)),t.appendChild(h);const b=[h];if(c!==""){const L=document.createElementNS("http://www.w3.org/2000/svg","text");L.setAttribute("class","edge-label mono"),L.setAttribute("x",String((l.x1+l.x2)/2+14)),L.setAttribute("y",String((l.y1+l.y2)/2+18)),L.textContent=c,t.appendChild(L),b.push(L)}return b}return{render:i,flyTo(l){return l(),s},placements:()=>s,setInFlight:l=>{o=l}}}const An={x:0,y:0,scale:1};function Xt(t){return Math.max(ln,Math.min(cn,t))}function Et(t){const e=Number.isFinite(t.scale)?t.scale:1,n=Number.isFinite(t.x)?t.x:0,s=Number.isFinite(t.y)?t.y:0;return{x:n,y:s,scale:Xt(e)}}function mt(t,e,n){return{x:t.x+e/t.scale,y:t.y+n/t.scale}}function Qt(t,e,n){return{x:t.x+e/t.scale,y:t.y+n/t.scale,scale:t.scale}}function Sn(t,e,n,s){const o=Xt(t.scale*e);return o===t.scale?t:{x:t.x+n/t.scale-n/o,y:t.y+s/t.scale-s/o,scale:o}}const Qo=680,Zo=.8,es=.6,Ln=16;function un(t,e,n,s=Number.POSITIVE_INFINITY){if(t===null||e<=0||n<=0)return An;const o=t.maxX-t.minX,i=t.maxY-t.minY;if(!(o>0)||!(i>0))return An;const r=.9*Math.min(e/o,n/i),l=Math.min(s,r),m=e<Qo?Zo:es;if(r<m){const h=Xt(Math.min(s,m));return{x:t.minX-Ln/h,y:t.minY-Ln/h,scale:h}}const c=Xt(l);return{x:(t.minX+t.maxX)/2-e/(2*c),y:(t.minY+t.maxY)/2-n/(2*c),scale:c}}function ts(t){return`translate(${-t.x*t.scale}px, ${-t.y*t.scale}px) scale(${t.scale})`}function In(t,e){let n=t===null?null:{...t,minY:t.minY+Zn};for(const s of e){if(s.remote!==!0)continue;const o=ut(s);n=n===null?{minX:o.x,minY:o.y,maxX:o.x+o.w,maxY:o.y+o.h}:{minX:Math.min(n.minX,o.x),minY:Math.min(n.minY,o.y),maxX:Math.max(n.maxX,o.x+o.w),maxY:Math.max(n.maxY,o.y+o.h)}}return n}function Tn(t,e,n,s){const o=s>0&&s<n/2?s:0,i=un(t,e,n-o,1);return o===0||t===null?i:{...i,y:i.y-o/i.scale}}function _n(...t){const e=Math.max(0,...t.map(n=>n.offsetHeight>0?n.offsetTop+n.offsetHeight:0));return e>0?e+8:0}function ns(t){return t.type==="join-network"||t.type==="leave-network"?"$network":t.type==="create-team"||t.type==="remove-team"?t.name:t.team}function os(t,e){if(e.type==="create-team"){const o=e.ids.map(i=>t.getNode(i)).filter(i=>i!==void 0).map(i=>ut(i));return o.length>0&&t.setFrame(e.name,dn(o)),t.setTeamMembers(e.name,e.ids),()=>{t.setTeamMembers(e.name,t.teamMemberIds(e.name).filter(i=>!e.ids.includes(i))),t.removeFrame(e.name)}}if(e.type==="add-member"){const o=t.teamMemberIds(e.team),i=e.ids.filter(r=>!o.includes(r));return t.setTeamMembers(e.team,[...o,...i]),()=>{t.setTeamMembers(e.team,t.teamMemberIds(e.team).filter(r=>!i.includes(r)))}}if(e.type==="remove-member"){const o=t.teamMemberIds(e.team);return t.setTeamMembers(e.team,o.filter(i=>!e.ids.includes(i))),()=>{const i=t.teamMemberIds(e.team);t.setTeamMembers(e.team,[...i,...e.ids.filter(r=>!i.includes(r))])}}if(e.type==="remove-team"){const o=t.teamMemberIds(e.name),i=t.getFrame(e.name),r=i!==void 0?{...i}:void 0;return t.setTeamMembers(e.name,[]),t.removeFrame(e.name),()=>{r!==void 0&&t.setFrame(e.name,r),t.setTeamMembers(e.name,o)}}if(e.type==="join-network"||e.type==="leave-network")return()=>{};const n=t.teamMemberIds(e.team);let s=[...n];for(const o of e.ops)o.op==="remove"?s=s.filter(i=>i!==o.id):s.push(o.id);return t.setTeamMembers(e.team,s),()=>{let o=t.teamMemberIds(e.team);for(let i=0;i<n.length;i++){const r=n[i];o[i]!==r&&o.includes(r)&&(o=o.filter(l=>l!==r),o.push(r))}t.setTeamMembers(e.team,o)}}function nn(t,e){const n=[...t],s=[];for(let o=0;o<e.length;o++){const i=e[o];n[o]!==i&&n.includes(i)&&(s.push({op:"remove",id:i}),s.push({op:"add",id:i}),n.splice(n.indexOf(i),1),n.push(i))}return s}function ss(t,e){return t.teamMemberIds(e).map(n=>{var s;return{id:n,y:((s=t.getNode(n))==null?void 0:s.y)??0}}).sort((n,s)=>n.y-s.y).map(n=>n.id)}function On(t,e){let n,s=Number.POSITIVE_INFINITY;for(const[o,i]of t){if(e.x<i.x||e.x>i.x+i.w||e.y<i.y||e.y>i.y+i.h)continue;const r=i.w*i.h;r<s&&(n=o,s=r)}return n}const Pn=[9133302,3900150,1357990,16096779,15485081,8702998];function is(t){const{root:e,netBtn:n,signal:s,model:o}=t;function i(){return o.selectedIds().map(f=>{var M;return{id:f,y:((M=o.getNode(f))==null?void 0:M.y)??0}}).sort((f,M)=>f.y-M.y).map(f=>f.id)}function r(){if(l!==null)return;const f=i().filter(M=>{const y=o.getNode(M);return y===void 0?!1:y.remote!==!0||y.remoteHandle!==void 0&&y.remoteHandle!==""});if(f.length<2){t.notice("info","框选至少 2 个会话节点");return}m(f)}let l=null;function m(f){const M=document.createElement("div");M.className="p-dialog";const y=document.createElement("div");y.className="p-dialog-panel",y.setAttribute("role","dialog"),y.setAttribute("aria-modal","true"),y.setAttribute("aria-labelledby","p-dialog-title");const O=document.createElement("div");O.id="p-dialog-title",O.className="p-dialog-title",O.textContent=`组建团队(${f.length} 个节点,自上而下即优先级)`;const x=document.createElement("input");x.className="p-dialog-input",x.maxLength=40,x.setAttribute("aria-label","团队名");const R=document.createElement("div");R.className="p-dialog-err",R.setAttribute("aria-live","polite");const D=document.createElement("div");D.className="p-dialog-row";const fe=document.createElement("button");fe.type="button",fe.textContent="组建";const Ce=document.createElement("button");Ce.type="button",Ce.textContent="取消",D.append(fe,Ce),y.append(O,x,R,D),M.appendChild(y),e.appendChild(M);const Le=document.activeElement,P=()=>{M.remove(),l=null,Le==null||Le.focus()},z=()=>{const re=x.value.trim();return re===""||re.length>40||re.includes("/")||/^\d+$/.test(re)?"队名需 1..40 字,不含“/”,不为纯数字":null},ie=()=>{const re=z();if(re!==null){R.textContent=re,x.focus();return}const te=x.value.trim();if(P(),o.getFrame(te)!==void 0){t.notice("info",`已加入现有团队「${te}」`),t.emit({type:"add-member",team:te,ids:f});return}t.emit({type:"create-team",name:te,ids:f,created:!0})};fe.addEventListener("click",ie),Ce.addEventListener("click",P),x.addEventListener("keydown",re=>{const te=re;te.key==="Enter"&&(te.preventDefault(),ie()),te.key==="Escape"&&(te.preventDefault(),P())}),M.addEventListener("keydown",re=>{const te=re;if(te.key==="Escape"){te.preventDefault(),te.stopPropagation(),P();return}if(te.key!=="Tab")return;te.preventDefault();const K=Array.from(y.querySelectorAll("input, button")),ae=K.indexOf(document.activeElement),de=te.shiftKey?K[(ae-1+K.length)%K.length]:K[(ae+1)%K.length];de==null||de.focus()},s),l={wrap:M,restoreFocus:Le},x.focus()}let c=null,h="root",b=null,L=null,T=[];function U(){L==null||L.remove(),L=null}function ne(){var y;if(L!==null){U();return}if(T.length===0)return;const f=document.createElement("div");f.className="p-menu p-netmenu",f.setAttribute("role","menu"),f.setAttribute("aria-label","未入网会话");for(const O of T)f.appendChild($(`${O.name!==void 0&&O.name!==""?O.name:O.label} — 入网`,!0,()=>{U(),t.emit({type:"join-network",id:O.id})}));L=f,e.appendChild(f);const M=n.getBoundingClientRect();f.style.left=`${String(Math.min(M.left,window.innerWidth-220))}px`,f.style.top=`${String(Math.max(8,M.top-(T.length*30+10)))}px`,f.addEventListener("keydown",O=>{O.key==="Escape"&&(O.stopPropagation(),U(),n.focus())}),(y=f.querySelector("button"))==null||y.focus(),document.addEventListener("pointerdown",O=>{if(L===null)return;const x=O.target;x!==null&&(x.closest(".p-netmenu")!==null||x===n||n.contains(x))||U()},s)}function be(){c==null||c.remove(),c=null,h="root",b!==null&&b.isConnected?b.focus():e.focus(),b=null}function $(f,M,y){const O=document.createElement("button");return O.type="button",O.setAttribute("role","menuitem"),O.textContent=f,M?O.addEventListener("click",()=>{be(),y()}):(O.disabled=!0,O.setAttribute("aria-disabled","true")),O}function p(f,M,y,O="root",x){var Ce,Le,P,z,ie,re;x!==void 0&&(b=x),b===null&&(b=t.anchorFor(y)),c==null||c.remove(),h=O;const R=document.createElement("div");R.className="p-menu",R.setAttribute("role","menu"),R.setAttribute("aria-label","团队操作");let D=[];if(y.kind==="frame")D=[$(`解散团队「${y.name}」`,!0,()=>t.emit({type:"remove-team",name:y.name}))];else{const te=y.id;if(O==="root"){const K=$("组成团队…",o.selectedIds().length>=2,()=>m(i()));K.title="先框选或 Shift 加选至少 2 个节点",D.push(K),t.teams().length>0&&(D.push($("加入团队 ▸",!0,()=>p(f,M,y,"join"))),(((Ce=o.getNode(te))==null?void 0:Ce.memberships.map(de=>de.team))??[]).length>0&&(D.push($("置顶路由 ▸",!0,()=>p(f,M,y,"promote"))),D.push($("离队 ▸",!0,()=>p(f,M,y,"leave"))))),((Le=o.getNode(te))==null?void 0:Le.remote)!==!0&&D.push($("退网",!0,()=>t.emit({type:"leave-network",id:te})))}else{D.push($("‹ 返回",!0,()=>p(f,M,y,"root")));for(const K of t.teams())if(O==="join"){const ae=((P=o.getNode(te))==null?void 0:P.memberships.some(de=>de.team===K.name))??!0;D.push($(ae?`${K.name}(已加入)`:K.name,!ae,()=>t.emit({type:"add-member",team:K.name,ids:[te]})))}else if(O==="leave"){const ae=((z=o.getNode(te))==null?void 0:z.memberships.some(de=>de.team===K.name))??!1;D.push($(K.name,ae,()=>t.emit({type:"remove-member",team:K.name,ids:[te]})))}else{const ae=((ie=o.getNode(te))==null?void 0:ie.memberships.some(de=>de.team===K.name))??!1;D.push($(K.name,ae,()=>{const de=o.teamMemberIds(K.name),Me=[te,...de.filter(Ae=>Ae!==te)];t.emit({type:"reorder",team:K.name,ops:nn(de,Me)})}))}}}R.append(...D),R.style.left=`${Math.min(f,window.innerWidth-200)}px`;const fe=D.length*30+8;R.style.top=`${Math.max(8,Math.min(M,window.innerHeight-fe-8))}px`,R.addEventListener("keydown",te=>{var Me,Ae,Ve,qe;const K=te,ae=Array.from(R.querySelectorAll("[role=menuitem]")),de=ae.indexOf(document.activeElement);K.key==="ArrowDown"?(K.preventDefault(),(Me=ae[(de+1+ae.length)%ae.length])==null||Me.focus()):K.key==="ArrowUp"?(K.preventDefault(),(Ae=ae[(de-1+ae.length)%ae.length])==null||Ae.focus()):K.key==="Home"?(K.preventDefault(),(Ve=ae[0])==null||Ve.focus()):K.key==="End"?(K.preventDefault(),(qe=ae[ae.length-1])==null||qe.focus()):K.key==="Escape"&&(K.preventDefault(),K.stopPropagation(),h!=="root"?p(f,M,y,"root"):be())}),e.appendChild(R),c=R,(re=D[0])==null||re.focus()}function H(f,M,y){if(l!==null)return;const O=(y==null?void 0:y.closest(".p-node"))??null;if(O!==null){const D=o.getNode(O.dataset.id??"");if((D==null?void 0:D.remote)===!0&&(D.remoteHandle===void 0||D.remoteHandle===""))return}const x=O,R=(y==null?void 0:y.closest(".p-frame-head"))??null;if(x!==null){const D=x.dataset.id??"";o.isSelected(D)||o.setSelection([D]),b=x,p(f,M,{kind:"node",id:D})}else R!==null&&(b=R,p(f,M,{kind:"frame",name:R.dataset.frame??""}))}function v(f){T=f,n.textContent=`未入网${T.length>0?`(${String(T.length)})`:""}`,n.disabled=T.length===0,n.setAttribute("aria-disabled",String(T.length===0)),T.length===0&&U()}return{menuItem:$,isMenuOpen:()=>c!==null,isDialogOpen:()=>l!==null,closeMenu:be,openMenu:p,contextMenuAt:H,openNameDialog:m,startCreateFromSelection:r,toggleNetMenu:ne,setUnjoined:v}}function rs(t,e){const n=e.trim().toLowerCase();return n===""?[]:t.filter(s=>s.name.toLowerCase().includes(n)||s.team.toLowerCase().includes(n)||(s.host??"").toLowerCase().includes(n)).slice(0,8)}function as(t,e){return t.allNodes().map(n=>{const s=n.id.slice(5),o=n.id.startsWith("member-")?n.name!==void 0&&n.name!==""?n.name:n.team:n.remote===!0?s:e(n);return{id:n.id,name:o,team:n.team,...n.remote===!0?{host:s}:{}}})}function ls(t,e=1200){t!==void 0&&(t.classList.add("pulse"),setTimeout(()=>t.classList.remove("pulse"),e))}function cs(t){return e=>{const n=t.model.getNode(e);if(n===void 0)return;const s=t.viewSize();t.setVp(un({minX:n.x,minY:n.y,maxX:n.x+je,maxY:n.y+Fe},s.w,s.h,1)),t.applyViewport(),t.markDirty(),ls(t.cardEl(e))}}function ds(t,e,n,s){const o=ms({onPick:s});return t.appendChild(o.root),{...o,refresh:()=>o.setIndex(as(e,n))}}function ms(t){const e=document.createElement("div");e.className="p-search";const n=document.createElement("input");n.type="search",n.className="p-search-input",n.placeholder="🔍 搜索(Ctrl+K)",n.title="搜索名字 / 句柄 / 宿主(Ctrl+K 聚焦,Esc 清空)",n.setAttribute("aria-label","搜索画板节点:名字、句柄或宿主");const s=document.createElement("div");s.className="p-search-list";let o=[],i=[],r=0;const l=()=>{s.style.display="none",s.textContent=""},m=()=>{if(s.textContent="",i.length===0){l();return}i.forEach((b,L)=>{const T=document.createElement("div");T.className="p-search-hit"+(L===r?" active":""),T.dataset.id=b.id,T.textContent=b.name===b.team?b.name:`${b.name} · ${b.team}`,T.addEventListener("mousedown",U=>{U.preventDefault(),t.onPick(b.id),c()}),s.appendChild(T)}),s.style.display="block"},c=()=>{n.value="",i=[],l()},h=()=>{i=rs(o,n.value),r=0,m()};return n.addEventListener("input",h),n.addEventListener("keydown",b=>{if(b.key==="Escape"){c(),n.blur(),b.stopPropagation();return}if(b.key==="ArrowDown"||b.key==="ArrowUp"){if(i.length===0)return;b.preventDefault(),r=(r+(b.key==="ArrowDown"?1:i.length-1))%i.length,m();return}b.key==="Enter"&&i.length>0&&(b.preventDefault(),t.onPick(i[r].id),c())}),e.append(n,s),{root:e,setIndex(b){o=b,n.value!==""&&h()},focus(){n.focus(),n.select()},clear(){c()}}}const jt=28,Fn=16,Dn=14,Rn=48,us=4,fs=180,ps=90,hs=1600;function bs(t){const e=t.wrapWidth??hs,n=t.frames.map(m=>{const c=Math.max(m.soleIds.length,1),h=Math.min(us,Math.max(1,Math.ceil(Math.sqrt(c)))),b=Math.ceil(c/h),L=Math.max(fs,jt*2+h*je+(h-1)*Fn),T=Math.max(ps,jt*2+b*Fe+(b-1)*Dn);return{name:m.name,w:L,h:T,rows:b,perRow:h,soleIds:m.soleIds}}),s=[],o=[];let i=0,r=0,l=0;for(const m of n){i>0&&i+m.w>e&&(i=0,r+=l+Rn,l=0);const c={x:i,y:r,w:m.w,h:m.h};s.push({name:m.name,rect:c});const h=c.x+jt+je/2;let b=c.y+jt+Fe/2;m.soleIds.forEach((L,T)=>{const U=T%m.perRow;T>0&&U===0&&(b+=Fe+Dn),o.push({id:L,x:h+U*(je+Fn),y:b})}),i+=m.w+Rn,l=Math.max(l,m.h)}return{frames:s,seats:o}}function gs(t,e){const n=[];for(const[o,i]of t.allFrames()){if(e.has(o))continue;const r=t.teamMemberIds(o).map(l=>t.getNode(l)).filter(l=>l!==void 0).filter(l=>l.memberships.length===1).map(l=>l.id);n.push({name:o,rect:i,soleIds:r})}if(n.length===0)return!1;const s=bs({frames:n});for(const o of s.frames)t.setFrame(o.name,o.rect);for(const o of s.seats){const i=t.getNode(o.id);i!==void 0&&t.dragNodes([o.id],o.x-i.x,o.y-i.y)}return!0}const wt=24,vs=200,on=(t,e)=>t.x<e.x+e.w&&e.x<t.x+t.w&&t.y<e.y+e.h&&e.y<t.y+t.h;function ys(t,e){const n=e.x+e.w+wt-t.x,s=e.x-wt-(t.x+t.w),o=e.y+e.h+wt-t.y,i=e.y-wt-(t.y+t.h),r=Math.abs(n)<=Math.abs(s)?n:s,l=Math.abs(o)<=Math.abs(i)?o:i;return Math.abs(r)<=Math.abs(l)?{dx:r,dy:0}:{dx:0,dy:l}}function ws(t,e,n,s){const o=t.beginFrameDrag(e);o!==void 0&&t.applyFrameDrag(o,n,s)}function xs(t,e,n){let s=!1;for(let o=0;o<vs;o++){const i=t.allFrames();let r;for(let $=0;$<i.length&&r===void 0;$++)for(let p=$+1;p<i.length;p++){const[H,v]=i[$],[f,M]=i[p];if(!(e.has(H)&&e.has(f))&&on(v,M)){r=[H,v,f,M];break}}if(r===void 0)return s;const[l,m,c,h]=r,b=$=>e.has($)?2:$===n?1:0,[L,T,U]=b(l)<b(c)?[l,m,h]:[c,h,m],{dx:ne,dy:be}=ys(T,U);ws(t,L,ne,be),s=!0}return s}function Cs(t){let e=!1;const n=t.allFrames(),s=(o,i)=>n.every(([r,l])=>i.has(r)||!on(o,l));for(const o of t.allNodes()){const i=new Set(o.memberships.map(U=>U.team)),r=ut(o),l=n.find(([U,ne])=>!i.has(U)&&on(r,ne));if(l===void 0)continue;const m=l[1],c=(U,ne)=>({x:U-je/2,y:ne-Fe/2,w:je,h:Fe}),h={x:m.x+m.w+wt+je/2,y:o.y},b={x:o.x,y:m.y+m.h+wt+Fe/2},L=Math.max(...n.map(([,U])=>U.x+U.w))+wt+je/2,T=s(c(h.x,h.y),i)?h:s(c(b.x,b.y),i)?b:{x:L,y:o.y};t.dragNodes([o.id],T.x-o.x,T.y-o.y),e=!0}return e}function Ht(t,e,n){const s=xs(t,e,n),o=Cs(t);return s||o}function ks(t){for(const[o,i]of t.allFrames()){const r=t.teamMemberIds(o).map(L=>t.getNode(L)).filter(L=>L!==void 0).filter(L=>L.memberships.length===1);if(r.length===0)continue;const l=Math.max(1,Math.floor((i.w-2*28+16)/(je+16))),m=Math.ceil(r.length/l),c=28*2+m*Fe+(m-1)*14;c>i.h&&t.setFrame(o,{...i,h:Math.min(c,i.h+400)});const h=i.x+28+je/2;let b=i.y+28+Fe/2;r.forEach((L,T)=>{const U=T%l;T>0&&U===0&&(b+=Fe+14);const ne=h+U*(je+16);t.dragNodes([L.id],ne-L.x,b-L.y)})}}function Es(t){const{root:e,trigger:n,signal:s,model:o}=t;let i=null,r="",l=null;function m(){l==null||l.remove(),l=null}function c(){m(),i==null||i.remove(),i=null}function h(){if(i!==null){c();return}const p=document.createElement("div");p.className="p-menu p-nodelist",p.setAttribute("role","dialog"),p.setAttribute("aria-label","节点清单"),i=p,e.appendChild(p);const H=n.getBoundingClientRect();p.style.left=`${String(Math.min(H.left,window.innerWidth-340))}px`,p.style.top=`${String(Math.max(8,H.top-320))}px`,p.addEventListener("keydown",v=>{v.key==="Escape"&&(v.stopPropagation(),c(),n.focus())}),b()}function b(){var O;const p=i;if(p===null)return;m(),p.textContent="";const H=document.createElement("div");H.className="p-nodelist-head";const v=document.createElement("span");v.className="p-nodelist-title",v.textContent="节点";const f=document.createElement("select");f.className="p-nodesel",f.setAttribute("aria-label","选择 host 或对等节点");const M=document.createElement("option");M.value="",M.textContent="本机",f.appendChild(M);for(const[x,R]of t.facts().remoteTeams){if(x==="")continue;const D=document.createElement("option");D.value=x,D.textContent=((O=R[0])==null?void 0:O.origin)!==void 0&&R[0].origin!==""?`${R[0].origin}(${x})`:x,f.appendChild(D)}r!==""&&!t.facts().remoteTeams.has(r)&&(r=""),f.value=r,f.addEventListener("change",()=>{r=f.value,b()}),H.append(v,f);const y=document.createElement("div");y.className="p-nodelist-body",p.append(H,y),r===""?be(y):$(y,t.facts().remoteTeams.get(r)??[])}function L(p,H){const v=document.createElement("span");return v.className="p-nodedot"+(H!==!0?" off":p===!1?" cold":""),v}function T(p,H){const v=document.createElement("button");return v.type="button",v.className="p-listbtn",v.textContent=p,v.addEventListener("click",f=>{f.stopPropagation(),H()}),v}function U(p,H){const v=document.createElement("div");if(v.className="p-nodelist-group",v.textContent=p,H!==void 0){const f=document.createElement("span");f.className="p-nodelist-note",f.textContent=H,v.appendChild(f)}return v}function ne(p,H){var M,y;m();const v=document.createElement("div");v.className="p-menu",v.setAttribute("role","menu"),v.setAttribute("aria-label","加入团队");for(const O of t.facts().teams){const x=((M=o.getNode(H))==null?void 0:M.memberships.some(R=>R.team===O.name))??!1;v.appendChild(t.menuItem(x?`${O.name}(已加入)`:O.name,!x,()=>{c(),t.emit({type:"add-member",team:O.name,ids:[H]})}))}v.appendChild(t.menuItem("新团队…",!0,()=>{c(),t.openNameDialog([H])})),l=v,e.appendChild(v);const f=p.getBoundingClientRect();v.style.left=`${String(Math.min(f.right+4,window.innerWidth-180))}px`,v.style.top=`${String(Math.max(8,f.top-60))}px`,v.addEventListener("keydown",O=>{O.key==="Escape"&&(O.stopPropagation(),m(),p.focus())}),(y=v.querySelector("button"))==null||y.focus()}function be(p){var y,O;const H=new Set(t.facts().canvasMemberIds);for(const x of t.facts().sessions)x.teams!==void 0&&x.teams.length>0&&H.add(x.id);const v=t.facts().sessions.filter(x=>x.joined===!0&&!H.has(x.id)),f=t.facts().sessions.filter(x=>x.joined!==!0),M=t.facts().sessions.filter(x=>x.joined===!0&&H.has(x.id));p.appendChild(U(`未组队 (${String(v.length)})`,"无网络能力"));for(const x of v){const R=document.createElement("div");R.className="p-noderow";const D=document.createElement("span");D.className="p-nodename",D.textContent=x.name!==void 0&&x.name!==""?x.name:x.label,D.title=x.team;const fe=document.createElement("span");fe.className="p-nonet",fe.textContent="无网络能力";const Ce=T("入队▸",()=>ne(Ce,x.id));R.append(L(x.live,!0),D,fe,Ce,T("退网",()=>{c(),t.emit({type:"leave-network",id:x.id})})),p.appendChild(R)}p.appendChild(U(`未入网 (${String(f.length)})`));for(const x of f){const R=document.createElement("div");R.className="p-noderow";const D=document.createElement("span");D.className="p-nodename",D.textContent=x.name!==void 0&&x.name!==""?x.name:x.label,D.title=x.id,R.append(L(x.live,!1),D,T("入网",()=>{c(),t.emit({type:"join-network",id:x.id})})),p.appendChild(R)}p.appendChild(U(`已组队 (${String(M.length)})`,"画布展示"));for(const x of M){const R=document.createElement("div");R.className="p-noderow";const D=document.createElement("span");D.className="p-nodename",D.textContent=x.name!==void 0&&x.name!==""?x.name:x.label,D.title=x.team;const fe=((y=o.getNode(x.id))==null?void 0:y.memberships.length)??0,Ce=((O=x.teams)==null?void 0:O.length)??0,Le=document.createElement("span");Le.className="p-teamcount",Le.textContent=`队×${String(Math.max(fe,0)+Ce)}`,R.append(L(x.live,!0),D,Le,T("定位",()=>{t.locate(x.id)})),p.appendChild(R)}if(t.facts().sessions.length===0){const x=document.createElement("div");x.className="p-nodelist-empty",x.textContent="无会话节点",p.appendChild(x)}}function $(p,H){var M;const v=H.filter(y=>y.teams===void 0||y.teams.length===0),f=H.filter(y=>y.teams!==void 0&&y.teams.length>0);p.appendChild(U(`未组队 (${String(v.length)})`,"无网络能力 · 只读"));for(const y of v){const O=document.createElement("div");O.className="p-noderow";const x=document.createElement("span");x.className="p-nodename",x.textContent=y.name!==void 0&&y.name!==""?y.name:y.team,x.title=y.team;const R=document.createElement("span");R.className="p-nonet",R.textContent="无网络能力",O.append(L(!0,!0),x,R),p.appendChild(O)}p.appendChild(U(`已组队 (${String(f.length)})`,"只读"));for(const y of f){const O=document.createElement("div");O.className="p-noderow";const x=document.createElement("span");x.className="p-nodename",x.textContent=y.name!==void 0&&y.name!==""?y.name:y.team,x.title=y.team;const R=document.createElement("span");R.className="p-teamcount",R.textContent=`队×${String(((M=y.teams)==null?void 0:M.length)??0)}`,O.append(L(!0,!0),x,R),p.appendChild(O)}if(H.length===0){const y=document.createElement("div");y.className="p-nodelist-empty",y.textContent="该节点未发布会话",p.appendChild(y)}}return document.addEventListener("pointerdown",p=>{if(i===null)return;const H=p.target;if(H===null){c();return}H.closest(".p-nodelist")!==null||H.closest(".p-menu")!==null||H===n||n.contains(H)||c()},s),{toggle:h,close:c,refresh:()=>{i!==null&&b()}}}function $s(t){let e=t;const n=e.search(/\|| ```|^```/);return n>=0&&(e=e.slice(0,n)),e.replace(/\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/(^|\s)#{1,6}\s+/g,"$1").replace(/\*\*|__|`/g,"").replace(/\s+/g," ").trim()}function Ns(t,e){const n=t.map(i=>i.name!==void 0&&i.name!==""?i.name:i.team),s=n.slice(0,2).join("、"),o=n.length>2?` +${n.length-2}`:"";return(e!==void 0?`score ${e} · `:"")+`${t.length} 远端团队`+(s!==""?`:${s}${o}`:"")}function Ms(t,e,n){if(t.id.startsWith("member-"))return{title:t.name!==void 0&&t.name!==""?t.name:t.team,sub:t.team,tip:t.team};if(t.remote===!0){const m=t.id.slice(5),c=e.length===1&&e[0].name!==void 0&&e[0].name!==""?e[0].name:void 0,h=Ns(e,n);return c!==void 0?{title:c,sub:`${m} · ${h}`,tip:`${c}
|
|
6
|
+
${m}
|
|
7
|
+
${h}`}:{title:m,sub:h,tip:`${m}
|
|
8
|
+
${h}`}}const s=it(t),o=t.team+(t.name!==void 0&&t.name!==""?" · "+t.name:""),i=$s(t.description??""),r=i!==""?i:o===s?"":t.team,l=(t.memberships.length>1?` · 跨队×${t.memberships.length}`:"")+(t.teams!==void 0&&t.teams.length>0?` · 网络队×${t.teams.length}`:"");return{title:s,sub:r+l,tip:i!==""?`${o}
|
|
9
|
+
${i}`:o}}const Bn="dsh-a2a.board.legend";function As(){const t=document.createElement("details");t.className="p-legend";const e=document.createElement("summary");e.textContent="图例",e.title="边的含义(点击展开 / 收起)";const n=document.createElement("div");n.className="p-legend-rows";const s=(o,i,r)=>{const l=document.createElement("span"),m=document.createElement("i");o&&(m.className="dashed"),r!==void 0&&(m.style.borderTopColor=r),l.append(m,document.createTextNode(i)),n.appendChild(l)};s(!1,"成员边(星形,框→成员)"),s(!0,"跨队多属(虚线)"),s(!1,"活动边(inFlight 路由,瞬时)","var(--accent)"),s(!0,"联邦线(→peer)","var(--federal)"),t.append(e,n);try{t.open=window.localStorage.getItem(Bn)==="open"}catch{}return t.addEventListener("toggle",()=>{try{window.localStorage.setItem(Bn,t.open?"open":"closed")}catch{}}),t}function Ss(t){return t<680?"narrow":t<1024?"medium":"wide"}function Ls(t){let e=0;for(let l=0;l<t.length;l++)e=(e*31+t.charCodeAt(l)&268435455)>>>0;const n=Pn[e%Pn.length],s="#"+n.toString(16).padStart(6,"0"),o=n>>16&255,i=n>>8&255,r=n&255;return{line:s,bg:`rgba(${o},${i},${r},0.05)`}}function Is(t){const e=new mn;let n,s={...e.viewport},o={kind:"none"},i=!1,r=-1,l=!0,m=!1,c=!1;const h=()=>Ss(globalThis.innerWidth||We),b=()=>{var a;(a=t.viewportStore)==null||a.set(h(),s),t.onDirty()},L=t.now??Date.now,T=new AbortController,U=[];let ne=null,be=!1;const $={signal:T.signal},p=document.createElement("section");p.id="dsh-plan",p.setAttribute("role","tabpanel"),p.setAttribute("aria-label","A2A 规划画布"),p.tabIndex=0,p.style.display="none";const H=document.createElement("div");H.className="p-grid";const v=document.createElement("div");v.className="p-world";const f=document.createElementNS("http://www.w3.org/2000/svg","svg");f.setAttribute("class","p-edges");const M=document.createElement("div");M.className="p-layer p-frames";let y;const O=a=>{var u,g;y!==void 0&&((u=He.get(y))==null||u.classList.remove("selected")),y=a,a!==void 0&&((g=He.get(a))==null||g.classList.add("selected"))},x=document.createElement("div");x.className="p-layer p-nodes",x.setAttribute("role","listbox"),x.setAttribute("aria-multiselectable","true"),x.setAttribute("aria-label","会话节点"),v.append(f,M,x);const R=document.createElement("div");R.className="p-marquee";const D=document.createElement("div");D.className="p-toolbar";const fe=document.createElement("span");fe.className="p-zoom mono",fe.textContent="100%";const Ce=(a,u,g)=>{const E=document.createElement("button");return E.type="button",E.textContent=a,E.title=u,E.addEventListener("click",g,$),E},Le=()=>{const a=document.createElement("span");return a.className="p-sep",a.setAttribute("role","separator"),a.setAttribute("aria-orientation","vertical"),a};D.append(Ce("适配","适配视图(快捷键 0)",()=>Ge()),Ce("-","缩小",()=>Re(1/1.2)),fe,Ce("+","放大",()=>Re(1.2)),Le(),Ce("建队","组成团队(G):先框选至少 2 个节点",()=>A.startCreateFromSelection()),Ce("整理成员","每队框内仅属一队的成员自动排齐(多队成员不动)",()=>et()),Ce("一键重排","全板队框+成员重排:框尺寸随内容自适应、框位行流式平铺(远端队框与多归属成员不动)",()=>gt()));const P=Ce("未入网","未入网会话(点击选择入网)",()=>A.toggleNetMenu());P.className="p-netbtn",P.setAttribute("aria-haspopup","menu"),D.append(Le(),P);const z=ds(D,e,it,a=>ce(a)),ie=Ce("节点","节点清单:本机与对等节点(未组队/未入网在此管理)",()=>j.toggle());ie.className="p-nodebtn",ie.setAttribute("aria-haspopup","dialog"),D.appendChild(ie);const re=document.createElement("span");re.setAttribute("aria-live","polite"),re.className="p-lamp";const te=document.createElement("i"),K=document.createElement("span");K.textContent="布局",re.append(te,K),re.addEventListener("click",()=>{re.classList.contains("error")&&t.onLampClick()},$),re.addEventListener("keydown",a=>{const u=a;(u.key==="Enter"||u.key===" ")&&re.classList.contains("error")&&(u.preventDefault(),t.onLampClick())},$),D.appendChild(re);const ae=document.createElement("div");ae.className="p-status";const de=document.createElement("span"),Me=document.createElement("span"),Ae=document.createElement("span");Ae.className="mut";const Ve=document.createElement("span");Ve.className="mut",ae.append(de,Me,Ae,Ve),ae.tabIndex=0,ae.setAttribute("role","button"),ae.setAttribute("aria-label","定位在途路由与联邦对端"),ae.title="定位在途与联邦(回车)",ae.addEventListener("click",()=>me(),$),ae.addEventListener("keydown",a=>{const u=a;(u.key==="Enter"||u.key===" ")&&(u.preventDefault(),me())},$);const qe=As(),De=document.createElement("div");De.className="p-notice-stack",De.setAttribute("role","log"),De.setAttribute("aria-live","polite"),p.append(H,v,R,D,ae,qe,De);let We=0,Ke=0;const xt=()=>t.viewSize?t.viewSize():{w:p.clientWidth,h:p.clientHeight},rt=()=>{const a=xt();We=a.w,Ke=a.h};function Ue(){v.style.transform=ts(s);const a=24*s.scale;H.style.backgroundSize=`${a}px ${a}px`,H.style.backgroundPosition=`${-s.x*s.scale}px ${-s.y*s.scale}px`,fe.textContent=`${Math.round(s.scale*100)}%`}function et(){ks(e),Ht(e,new Set($e.keys())),b(),Se()}function gt(){gs(e,new Set($e.keys()))&&(Ht(e,new Set($e.keys())),b(),Se())}function Se(){Ue(),e.revision!==r&&(r=e.revision,tt(),vt(),at()),Y()}const He=new Map,Ye=new Map;function tt(){const a=new Set;for(const[u,g]of e.allFrames()){a.add(u);let E=He.get(u);if(E===void 0){E=document.createElement("div"),E.className="p-frame",E.dataset.name=u;const pe=document.createElement("div");pe.className="p-frame-head",pe.dataset.frame=u,pe.tabIndex=0,pe.setAttribute("role","button"),pe.setAttribute("aria-haspopup","menu"),pe.setAttribute("aria-label",`团队框 ${u}(拖动整组,回车菜单)`);const Be=document.createElement("span");Be.className="ttl";const ot=document.createElement("span");ot.className="cnt mono";const k=document.createElement("span");k.className="route mono",pe.append(Be,ot,k),E.appendChild(pe);for(const ue of["n","s","e","w","ne","nw","se","sw"]){const le=document.createElement("div");le.className=`p-frame-handle p-h-${ue}`,le.dataset.frame=u,le.dataset.dir=ue,E.appendChild(le)}M.appendChild(E),He.set(u,E)}const B=Ls(u);E.style.setProperty("--frame-line",B.line),E.style.setProperty("--frame-bg",B.bg),E.style.left=`${g.x}px`,E.style.top=`${g.y}px`,E.style.width=`${g.w}px`,E.style.height=`${g.h}px`;const V=E.querySelector(".ttl"),W=E.querySelector(".cnt"),X=E.querySelector(".route");V.textContent!==u&&(V.textContent=u);let ee=0,q=0;for(const pe of e.allNodes())pe.memberships.find(ot=>ot.team===u)!==void 0&&(ee+=1,pe.memberships.length>1&&(q+=1));const Ee=`${ee} 成员`+(q>0?` +${q} 跨队`:"");W.textContent!==Ee&&(W.textContent=Ee);const Pe=pt(u);X.textContent!==Pe&&(X.textContent=Pe)}for(const[u,g]of[...He])a.has(u)||(g.remove(),He.delete(u))}function pt(a){const u=dt.find(g=>g.name===a);return(u==null?void 0:u.team)??a}function vt(){const a=new Set;for(const u of e.allNodes()){a.add(u.id);let g=Ye.get(u.id);if(g===void 0){g=document.createElement("div"),g.className="p-node",g.dataset.id=u.id,g.tabIndex=0;const q=document.createElement("div");q.className="nm";const Ee=document.createElement("span");Ee.className="dot";const Pe=document.createElement("span");Pe.className="nm-text",q.append(Ee,Pe);const pe=document.createElement("div");pe.className="sub mono";const Be=document.createElement("span");Be.className="prio mono",g.append(q,pe,Be),x.appendChild(g),Ye.set(u.id,g)}const E=ut(u);g.style.left=`${E.x}px`,g.style.top=`${E.y}px`,g.classList.toggle("cold",!u.live),g.classList.toggle("remote",u.remote===!0),g.classList.toggle("selected",e.isSelected(u.id)),g.setAttribute("aria-selected",String(e.isSelected(u.id)));const B=u.id.slice(5),V=Ms(u,u.remote===!0?N.get(B)??[]:[],I.get(B)),W=g.querySelector(".nm-text");W.textContent!==V.title&&(W.textContent=V.title);const X=g.querySelector(".sub");X.textContent!==V.sub&&(X.textContent=V.sub),g.title!==V.tip&&(g.title=V.tip);const ee=g.querySelector(".prio");if(u.remote===!0){const q=G.get(B),Ee=(q==null?void 0:q.link)==="linked"?"lnk-linked":(q==null?void 0:q.link)==="stranger"?"lnk-stranger":"";ee.className!==`prio mono ${Ee}`.trim()&&(ee.className=`prio mono ${Ee}`.trim());const Pe=q===void 0?"":q.verified===!0?"✓":"✗",pe=((q==null?void 0:q.link)??"peer")+Pe;ee.textContent!==pe&&(ee.textContent=pe)}else{ee.className!=="prio mono"&&(ee.className="prio mono");const q=u.memberships[0]!==void 0?`P${u.memberships[0].index}`:"";ee.textContent!==q&&(ee.textContent=q)}}for(const[u,g]of[...Ye])a.has(u)||(g.remove(),Ye.delete(u));z.refresh()}function at(){for(;f.firstChild!==null;)f.firstChild.remove();const a=e.allFrames().map(([u])=>({name:u,members:e.teamMemberIds(u).map(g=>({id:g}))}));for(const u of Bo(a,new Map(e.allFrames()),e.positions())){const g=document.createElementNS("http://www.w3.org/2000/svg","line");g.setAttribute("class","e-member"+(u.dashed?" dashed":"")),g.setAttribute("x1",String(u.x1)),g.setAttribute("y1",String(u.y1)),g.setAttribute("x2",String(u.x2)),g.setAttribute("y2",String(u.y2)),f.appendChild(g)}}const d=qo(f,e);let N=new Map;const I=new Map,G=new Map;function Y(){d.render(L())}function me(){s=un(Jo(e.contentBounds(),d.placements()),p.clientWidth||We,p.clientHeight||Ke),Ue(),b()}const ce=cs({model:e,viewSize:xt,setVp:a=>{s=a},applyViewport:Ue,markDirty:b,cardEl:a=>Ye.get(a)});function ge(a){var V;const u=a.sessions.filter(W=>W.live!==!1).length,g=a.sessions.length-u;de.textContent="";const E=document.createElement("b");E.className="ok",E.textContent=`● ${u} live`,de.appendChild(E),Me.textContent="";const B=document.createElement("b");B.className="warn",B.textContent=`● ${g} cold`,Me.appendChild(B),Ae.textContent=`${((V=a.inFlight)==null?void 0:V.length)??0} inFlight`,Ve.className="mut",Ve.textContent=`${a.teams.length} 队 · ${a.peerCount} peer`}const J=new Map,Oe=a=>{J.set(a,(J.get(a)??0)+1)},ze=a=>{const u=(J.get(a)??0)-1;u<=0?J.delete(a):J.set(a,u)};let $e=new Map;function C(a){function u(B){const V=W=>{var ee;const X=[];for(const q of W){if(!q.startsWith("peer-")&&!q.startsWith("member-")){X.push(q);continue}const Ee=(ee=e.getNode(q))==null?void 0:ee.remoteHandle;Ee!==void 0&&Ee!==""&&X.push(Ee)}return X};if(B.type==="add-member"||B.type==="remove-member"||B.type==="create-team"){const W=V(B.ids),X=B.type!=="create-team"?$e.get(B.team):void 0;return W.length>0||X!==void 0?{...B,ids:W,...X!==void 0?{fleetPeer:X}:{}}:B}return B}if(a.type==="add-member"||a.type==="remove-member"||a.type==="reorder"||a.type==="create-team"){const B=a.type==="reorder"?a.ops.map(V=>V.id):[...a.ids];for(const V of B){if(V===""||V.startsWith("peer-")||V.startsWith("member-")||e.getNode(V)!==void 0)continue;const W=_.find(q=>q.id===V);if(W===void 0)continue;const X=n==null?void 0:n.nodes[V],ee=X!==void 0?{x:X.x,y:X.y}:Ot(V);e.upsertNode({id:V,x:ee.x,y:ee.y,label:W.label,team:W.team,name:W.name,description:W.description,live:W.live!==!1,memberships:[],...W.teams!==void 0&&W.teams.length>0?{teams:W.teams}:{}})}}const g=os(e,a),E=ns(a);Oe(E),Se(),t.onCanvasAction(u(a)).then(B=>{ze(E),B||g(),Se()},()=>{ze(E),g(),w("error","操作通道异常,已回滚"),Se()})}function w(a,u){var E;for(;De.childElementCount>=3;)(E=De.firstElementChild)==null||E.remove();const g=document.createElement("div");g.className="p-notice"+(a==="error"?" error":""),g.setAttribute("role",a==="error"?"alert":"status"),g.textContent=u,De.appendChild(g),U.push(setTimeout(()=>g.remove(),4e3))}const A=is({root:p,netBtn:P,signal:$,model:e,teams:()=>dt,anchorFor:a=>(a.kind==="node"?Ye.get(a.id):He.get(a.name))??null,emit:C,notice:w});let _=[],F=new Set;const j=Es({root:p,trigger:ie,signal:$,model:e,facts:()=>({sessions:_,canvasMemberIds:F,remoteTeams:N,teams:dt}),menuItem:A.menuItem,emit:C,openNameDialog:A.openNameDialog,locate:se});function se(a){var E;const u=e.getNode(a);if(u===void 0)return;j.close();const g=((E=t.viewSize)==null?void 0:E.call(t))??{w:p.clientWidth>0?p.clientWidth:800,h:p.clientHeight>0?p.clientHeight:600};s=Et({scale:s.scale,x:u.x-g.w/(2*s.scale),y:u.y-g.h/(2*s.scale)}),Ue(),r=-1,Se()}function oe(a){const u=p.getBoundingClientRect();return{x:a.clientX-u.left,y:a.clientY-u.top}}function Q(a,u){var W;const g=oe(u),E=mt(s,g.x,g.y),B=On(new Map(e.allFrames()),E),V=a.ids.filter(X=>{const ee=e.getNode(X);return ee===void 0?!1:ee.remote!==!0?!0:ee.remoteHandle!==void 0&&ee.remoteHandle!==""});if(B!==void 0){const X=V.filter(ee=>{var q;return!((q=e.getNode(ee))!=null&&q.memberships.some(Ee=>Ee.team===B))});if(X.length>0){C({type:"add-member",team:B,ids:X});return}if(a.ids.length===1&&((W=e.getNode(a.clicked))==null?void 0:W.remote)!==!0){const ee=e.teamMemberIds(B),q=ss(e,B);q.join("\0")!==ee.join("\0")&&C({type:"reorder",team:B,ops:nn(ee,q)})}}}function ve(a){if(We===0&&rt(),A.isDialogOpen()){a.preventDefault();return}const u=a.target;if(A.isMenuOpen()){if(u!==null&&u.closest(".p-menu")!==null)return;A.closeMenu(),a.preventDefault();return}if(u!==null&&u.closest("button, input, textarea, select, .p-toolbar, .p-search, .p-lamp, .p-status, .p-legend")!==null)return;const g=oe(a);if(a.button===2){ne={x:g.x,y:g.y,target:a.target,moved:!1},a.preventDefault();try{p.setPointerCapture(a.pointerId??0)}catch{}return}const E=u!==null?u.closest(".p-node"):null,B=u!==null?u.closest(".p-frame-head"):null;if((E!==null||B!==null)&&a.button===1){o={kind:"pan",last:g,moved:!1},a.preventDefault();try{p.setPointerCapture(a.pointerId??0)}catch{}return}const V=u!==null?u.closest(".p-frame-handle"):null;if(y!==void 0){const W=He.get(y),X=u!==null&&W!==void 0&&(W.contains(u)||W===u),ee=B!==null&&B.dataset.frame===y;!X&&!ee&&O(void 0)}if(V!==null&&a.button===0){const W=V.dataset.frame??"";O(W);const X=e.getFrame(W);if(X===void 0)return;o={kind:"frame-resize",name:W,dir:V.dataset.dir??"se",startRect:{...X},origin:mt(s,g.x,g.y),moved:!1},a.preventDefault();try{p.setPointerCapture(a.pointerId??0)}catch{}return}if(E!==null){if(a.button!==0)return;const W=E.dataset.id??"",X=e.isSelected(W);!X&&!a.shiftKey&&e.setSelection([W]);const ee=a.shiftKey||X?e.isSelected(W)?e.selectedIds():[...e.selectedIds(),W]:[W];o={kind:"node",clicked:W,ids:ee,last:mt(s,g.x,g.y),moved:!1,el:E},E.classList.add("dragging")}else if(B!==null){if(a.button!==0)return;const W=B.dataset.frame??"";O(W);const X=e.beginFrameDrag(W);if(X===void 0)return;o={kind:"frame",name:W,snap:X,origin:mt(s,g.x,g.y),moved:!1}}else if(a.button===1||a.button===0&&i)o={kind:"pan",last:g,moved:!1};else if(a.button===0)o={kind:"marquee",origin:g,last:g,additive:a.shiftKey},R.style.display="block",R.style.left=`${g.x}px`,R.style.top=`${g.y}px`,R.style.width="0px",R.style.height="0px";else return;a.preventDefault();try{p.setPointerCapture(a.pointerId??0)}catch{}}function Ie(a){const u=oe(a);if(ne!==null){const g=u.x-ne.x,E=u.y-ne.y;Math.hypot(g,E)>4&&(ne.moved=!0,s=Et(Qt(s,-g,-E)),ne.x=u.x,ne.y=u.y,Ue());return}if(o.kind==="node"){const g=mt(s,u.x,u.y),E=g.x-o.last.x,B=g.y-o.last.y;if(E===0&&B===0)return;o.moved=!0,o.last=g,e.dragNodes(o.ids,E,B);const V=On(new Map(e.allFrames()),g),W=o.ids.filter(ee=>{const q=e.getNode(ee);return q===void 0?!1:q.remote!==!0||q.remoteHandle!==void 0&&q.remoteHandle!==""}),X=V!==void 0&&W.length>0;for(const[ee,q]of He)q.classList.toggle("drop-target",X&&ee===V);Se()}else if(o.kind==="frame"){const g=mt(s,u.x,u.y),E=g.x-o.origin.x,B=g.y-o.origin.y;if(!o.moved&&E===0&&B===0)return;o.moved=!0,e.applyFrameDrag(o.snap,E,B),Se()}else if(o.kind==="frame-resize"){const g=mt(s,u.x,u.y),E=g.x-o.origin.x,B=g.y-o.origin.y;if(!o.moved&&E===0&&B===0)return;o.moved=!0;const V=220,W=120,X={...o.startRect};let{x:ee,y:q,w:Ee,h:Pe}=X;o.dir.includes("e")&&(Ee=Math.max(V,X.w+E)),o.dir.includes("s")&&(Pe=Math.max(W,X.h+B)),o.dir.includes("w")&&(Ee=Math.max(V,X.w-E),ee=X.x+(X.w-Ee)),o.dir.includes("n")&&(Pe=Math.max(W,X.h-B),q=X.y+(X.h-Pe)),e.setFrame(o.name,{x:Math.round(ee),y:Math.round(q),w:Math.round(Ee),h:Math.round(Pe)}),Se()}else if(o.kind==="pan")s=Qt(s,u.x-o.last.x,u.y-o.last.y),o.last=u,o.moved=!0,Ue();else if(o.kind==="marquee"){const g=Math.min(o.origin.x,u.x),E=Math.min(o.origin.y,u.y);R.style.left=`${g}px`,R.style.top=`${E}px`,R.style.width=`${Math.abs(u.x-o.origin.x)}px`,R.style.height=`${Math.abs(u.y-o.origin.y)}px`,o.last=u}}function Z(a){var u,g;if(ne!==null){const E=ne.moved,B=ne.target,V=ne.x,W=ne.y;ne=null,E?(be=!0,b()):B!==null&&A.contextMenuAt(V,W,B);return}if(o.kind==="node"){const E=o.clicked;if(o.moved)Q(o,a),b();else if(a.shiftKey){const B=e.selectedIds();e.setSelection(B.includes(E)?B.filter(V=>V!==E):[...B,E])}else e.setSelection([E]),(u=t.onNodePick)==null||u.call(t,E);for(const B of He.values())B.classList.remove("drop-target");(g=o.el)==null||g.classList.remove("dragging"),Se()}else if(o.kind==="frame"||o.kind==="frame-resize")o.moved&&(Ht(e,new Set($e.keys()),o.name),b(),Se());else if(o.kind==="pan")o.moved&&b();else if(o.kind==="marquee"){const E=o.last,B=mt(s,Math.min(o.origin.x,E.x),Math.min(o.origin.y,E.y)),V=mt(s,Math.max(o.origin.x,E.x),Math.max(o.origin.y,E.y));e.marqueeSelect({x:B.x,y:B.y,w:V.x-B.x,h:V.y-B.y},o.additive),R.style.display="none",Se()}o={kind:"none"};try{p.releasePointerCapture(a.pointerId??0)}catch{}}function Te(a){A.isMenuOpen()&&A.closeMenu();const u=oe(a);if(a.shiftKey&&!a.ctrlKey){const g=a.deltaMode===1?16:1;s=Et(Qt(s,(a.deltaX??0)*g,(a.deltaY??0)*g))}else{const g=a.deltaMode===1?16:1,E=Math.exp(-((a.deltaY??0)*g)*.0015);s=Sn(s,E,u.x,u.y)}a.preventDefault(),Ue(),b()}function Re(a){rt(),s=Sn(s,a,We/2,Ke/2),Ue(),b()}function Ge(){rt(),s=Tn(In(e.contentBounds(),e.allNodes()),We,Ke,_n(D,ae)),Ue(),b()}function lt(a){var V,W,X,ee,q,Ee,Pe;if(A.isDialogOpen()||((W=(V=a.target)==null?void 0:V.closest)==null?void 0:W.call(V,".p-search"))!==null)return;if((a.ctrlKey||a.metaKey)&&a.key.toLowerCase()==="k"){a.preventDefault(),z.focus();return}if(a.ctrlKey||a.metaKey)return;if(A.isMenuOpen()){a.key==="Escape"&&(A.closeMenu(),a.preventDefault());return}if(a.key===" "&&a.target===p){i=!0,a.preventDefault();return}const u=((ee=(X=a.target)==null?void 0:X.closest)==null?void 0:ee.call(X,".p-frame-head"))??null;if((a.key==="Enter"||a.key===" ")&&u!==null){a.preventDefault();const pe=u.getBoundingClientRect();A.contextMenuAt(pe.left+pe.width/2,pe.top+pe.height/2,u);return}if(a.key===" "&&((Ee=(q=a.target)==null?void 0:q.classList)!=null&&Ee.contains("p-node"))){const Be=a.target.dataset.id??"",ot=e.selectedIds();e.setSelection(ot.includes(Be)?ot.filter(k=>k!==Be):[...ot,Be]),Se(),a.preventDefault();return}if(a.key==="F10"&&a.shiftKey||a.key==="ContextMenu"){a.preventDefault();const pe=document.activeElement??null,Be=((Pe=pe==null?void 0:pe.getBoundingClientRect)==null?void 0:Pe.call(pe))??{left:0,top:0,width:0,height:0};A.contextMenuAt(Be.left+Be.width/2,Be.top+Be.height/2,pe);return}if(a.key==="Delete"||a.key==="Backspace"){a.preventDefault(),Xe();return}if(a.altKey&&(a.key==="ArrowUp"||a.key==="ArrowDown")){a.preventDefault(),xe(a.key==="ArrowUp");return}if(a.key==="g"||a.key==="G"){A.startCreateFromSelection();return}if(a.key==="0"){Ge();return}if(a.key==="="||a.key==="+"){Re(1.2);return}if(a.key==="-"){Re(1/1.2);return}if(a.key==="Escape"){if(A.isMenuOpen()){A.closeMenu(),Se();return}e.setSelection([]),Se();return}const g=a.shiftKey?40:8,B={ArrowLeft:[-g,0],ArrowRight:[g,0],ArrowUp:[0,-g],ArrowDown:[0,g]}[a.key];if(B!==void 0){a.preventDefault();const pe=e.selectedIds();pe.length>0&&(e.nudge(pe,B[0],B[1]),Se(),b())}}function Xe(){var E,B,V;const a=document.activeElement,u=((E=a==null?void 0:a.closest)==null?void 0:E.call(a,".p-frame-head"))??null,g=((B=a==null?void 0:a.closest)==null?void 0:B.call(a,".p-node"))??null;if(u!==null){C({type:"remove-team",name:u.dataset.frame??""});return}if(g!==null){const W=g.dataset.id??"",X=((V=e.getNode(W))==null?void 0:V.memberships.map(ee=>ee.team))??[];if(X.length===0){w("info","该节点未加入任何团队");return}if(X.length===1){C({type:"remove-member",team:X[0],ids:[W]});return}A.openMenu(window.innerWidth/2,window.innerHeight/2,{kind:"node",id:W},"leave",g);return}w("info","焦点不在节点或团队框上")}function xe(a){var Ee,Pe;const u=document.activeElement,g=((Ee=u==null?void 0:u.closest)==null?void 0:Ee.call(u,".p-node"))??null;if(g===null)return;const E=g.dataset.id??"",B=((Pe=e.getNode(E))==null?void 0:Pe.memberships)??[];if(B.length!==1)return;const V=B[0].team,W=e.teamMemberIds(V),X=W.indexOf(E),ee=a?Math.max(0,X-1):Math.min(W.length-1,X+1);if(ee===X)return;const q=[...W];q.splice(X,1),q.splice(ee,0,E),C({type:"reorder",team:V,ops:nn(W,q)})}function nt(a){a.key===" "&&(i=!1)}p.addEventListener("pointerdown",a=>ve(a),$),p.addEventListener("pointermove",a=>Ie(a),$),p.addEventListener("pointerup",a=>Z(a),$),p.addEventListener("wheel",a=>Te(a),{...$,passive:!1}),p.addEventListener("keydown",a=>lt(a),$),p.addEventListener("keyup",a=>nt(a),$),p.addEventListener("contextmenu",a=>{var g,E;const u=a;if(((E=(g=u.target)==null?void 0:g.closest)==null?void 0:E.call(g,"input, textarea, .p-search"))==null){if(u.preventDefault(),be){be=!1;return}A.contextMenuAt(u.clientX,u.clientY,u.target)}},$);let dt=[];function _t(a){var pe,Be,ot;dt=a.teams,a.peers,d.setInFlight(a.inFlight??[]),_=a.sessions,A.setUnjoined(a.sessions.filter(k=>k.joined!==!0&&!k.id.startsWith("peer-")));const u=new Map;for(const k of a.teams)for(let ue=0;ue<k.members.length;ue++){const le=k.members[ue].id,_e=u.get(le)??[];_e.push({team:k.name,index:ue}),u.set(le,_e)}F=new Set(u.keys());const g=new Set,E=k=>{const ue=u.get(k)??[];if(J.size===0)return ue;const le=ue.filter(Ne=>!J.has(Ne.team)),_e=[];for(const[Ne]of J){const ye=e.teamMemberIds(Ne).indexOf(k);ye>=0&&_e.push({team:Ne,index:ye})}return[...le,..._e]};let B;if(n===void 0&&!e.allNodes().some(k=>k.remote!==!0)){const k=a.sessions.filter(ue=>{var le;return ue.joined===!0&&(E(ue.id).length>0||(((le=ue.teams)==null?void 0:le.length)??0)>0)}).map(ue=>ue.id);rt(),B=Fo(a.teams,k,We>0?We:void 0)}for(const k of a.sessions){if(k.joined!==!0)continue;const ue=E(k.id);if(!(ue.length===0&&(k.teams===void 0||k.teams.length===0)))if(g.add(k.id),e.getNode(k.id)!==void 0)e.upsertNode({id:k.id,x:e.getNode(k.id).x,y:e.getNode(k.id).y,label:k.label,team:k.team,name:k.name,description:k.description,live:k.live!==!1,memberships:ue,...k.teams!==void 0&&k.teams.length>0?{teams:k.teams}:{}});else{const le=n==null?void 0:n.nodes[k.id];let _e,Ne;if(le!==void 0)_e=le.x,Ne=le.y;else{const ke=(B==null?void 0:B.get(k.id))??Ot(k.id);_e=ke.x,Ne=ke.y}e.upsertNode({id:k.id,x:_e,y:Ne,label:k.label,team:k.team,name:k.name,description:k.description,live:k.live!==!1,memberships:ue,...k.teams!==void 0&&k.teams.length>0?{teams:k.teams}:{}})}}for(const k of e.nodeIds())!g.has(k)&&!k.startsWith("peer-")&&!k.startsWith("member-")&&e.removeNode(k);const V=new Set;N=Ho(a.remoteTeams??[]),I.clear();for(const k of a.peers??[])I.set(Nt(k.url),k.score),G.set(Nt(k.url),{link:k.link,verified:k.verified});if(a.peers!==void 0){const k=e.contentBounds(),ue=Uo(a.peers,k);a.peers.forEach((le,_e)=>{var fn,pn,hn,bn;const Ne=jo(le.url);V.add(Ne);const ke=n==null?void 0:n.nodes[Ne],ye=e.getNode(Ne),ht=ye!==void 0?{x:ye.x,y:ye.y}:ke!==void 0?{x:ke.x,y:ke.y}:{x:((fn=ue[_e])==null?void 0:fn.x)??200,y:((pn=ue[_e])==null?void 0:pn.y)??0},st=Nt(le.url),Ct=(bn=(hn=N.get(st))==null?void 0:hn[0])==null?void 0:bn.team;e.upsertNode({id:Ne,x:ht.x,y:ht.y,label:le.url,team:"",name:le.url,peerUrl:le.url,remoteHandle:Ct,live:!0,remote:!0,memberships:[]}),e.upsertScore(Ne,le.score)})}for(const k of e.nodeIds())k.startsWith("peer-")&&!V.has(k)&&e.removeNode(k);const W=new Set;for(const[k,ue]of N){const le=e.allNodes().find(ke=>ke.remote===!0&&Nt(ke.peerUrl??"")===k&&!ke.id.startsWith("member-")),_e=((le==null?void 0:le.x)??400)+190;let Ne=(le==null?void 0:le.y)??0;for(const ke of ue){if(!ke.team.includes("/"))continue;const ye=`member-${ke.team.replace(/[^a-z0-9-]/gi,"-")}`;if(W.has(ye))continue;W.add(ye);const ht=n==null?void 0:n.nodes[ye],st=e.getNode(ye),Ct=st!==void 0?{x:st.x,y:st.y}:ht!==void 0?{x:ht.x,y:ht.y}:{x:_e,y:Ne};Ne+=92,e.upsertNode({id:ye,x:Ct.x,y:Ct.y,label:ke.team,team:ke.team,name:ke.name!==void 0&&ke.name!==""?ke.name:ke.team,remoteHandle:ke.team,live:!0,remote:!0,memberships:[]})}}for(const k of e.nodeIds())k.startsWith("member-")&&!W.has(k)&&e.removeNode(k);const X=new Map;for(const k of e.allNodes())k.remote!==!0||k.remoteHandle===void 0||k.remoteHandle===""||(!X.has(k.remoteHandle)||k.id.startsWith("member-"))&&X.set(k.remoteHandle,k.id);for(const k of a.teams){if(J.has(k.name))continue;const ue=[];for(const Ne of k.members){const ke=X.get(Ne.id)??Ne.id;e.getNode(ke)!==void 0&&ue.push(ke)}const le=[...e.teamMemberIds(k.name)].sort().join("|"),_e=[...ue].sort().join("|");le!==_e&&e.setTeamMembers(k.name,ue)}const ee=new Map,q=$e;if($e=ee,a.peerOrg!==void 0){let k=0;const ue=new Set(a.teams.map(le=>le.name));for(const le of a.peerOrg){const _e=((Be=(pe=a.remoteTeams)==null?void 0:pe.find(ye=>ye.via===le.url))==null?void 0:Be.team.split("/")[0])??"dsh",Ne=ye=>ye.replace(/^session-/,"").slice(0,8),ke=ye=>ye.includes("/")?`member-${ye.replace(/[^a-z0-9-]/gi,"-")}`:`member-${_e}-${Ne(ye)}`;for(const ye of le.org){if(ye.name===""||ue.has(ye.name))continue;const ht=ye.members.map(ke).filter(Ct=>e.getNode(Ct)!==void 0),st=(ot=n==null?void 0:n.frames)==null?void 0:ot[ye.name];e.getFrame(ye.name)===void 0&&e.setFrame(ye.name,st!==void 0?{x:st.x,y:st.y,w:st.w,h:st.h}:{x:200+k%4*280,y:940+Math.floor(k/4)*160,w:250,h:130}),e.setTeamMembers(ye.name,ht),ee.set(ye.name,le.url),k+=1}}}for(const[k,ue]of q)ee.has(k)||e.removeFrame(k);const Ee=new Map;for(const k of e.allNodes())k.remote===!0&&k.remoteHandle!==void 0&&k.remoteHandle!==""&&Ee.set(k.remoteHandle,k.id);const Pe=qn(a.teams);for(const k of a.teams){if(e.getFrame(k.name)!==void 0||J.has(k.name))continue;const ue=n==null?void 0:n.frames[k.name];if(ue!==void 0){e.setFrame(k.name,{...ue});continue}const le=[],_e=[];for(const ke of k.members){const ye=e.getNode(Ee.get(ke.id)??ke.id);ye!==void 0&&(_e.push(ut(ye)),Pe.get(ye.id)===k.name&&le.push(ut(ye)))}const Ne=le.length>0?le:_e;Ne.length>0&&e.setFrame(k.name,dn(Ne))}for(const[k]of e.allFrames())J.has(k)||!a.teams.some(ue=>ue.name===k)&&!ee.has(k)&&e.removeFrame(k);j.refresh(),ge(a),!m&&o.kind==="none"&&e.nodeIds().length>0&&(m=!0,Ht(e,new Set($e.keys()))),l&&o.kind==="none"&&e.nodeIds().length>0&&(rt(),We>0&&Ke>0&&(l=!1,s=Tn(In(e.contentBounds(),e.allNodes()),We,Ke,_n(D,ae)))),Se()}function Ot(a){return Qn(a,e.allNodes().filter(u=>u.remote!==!0))}function to(a){const u=Jn(a);if(u===void 0)return;n=u;const g=t.viewportStore;if(g===void 0)l=!1,o.kind==="none"&&(s=Et({...u.viewport}));else if(!c&&o.kind==="none"){c=!0;const E=g.get(h());E!=null&&Number.isFinite(E.x)&&Number.isFinite(E.y)&&Number.isFinite(E.scale)?(s=Et({x:E.x,y:E.y,scale:E.scale}),l=!1):h()==="wide"&&(s=Et({...u.viewport}),l=!1)}r=-1,Se()}function no(){return To(s,e.positions(),e.frameRects())}function oo(a,u){re.classList.remove("pending","saved","error"),a==="pending"&&re.classList.add("pending"),a==="saved"&&re.classList.add("saved"),a==="error"&&re.classList.add("error"),a==="error"?(re.tabIndex=0,re.setAttribute("role","button"),re.setAttribute("aria-label","布局保存失败,按回车重试")):(re.removeAttribute("tabindex"),re.removeAttribute("role"),re.removeAttribute("aria-label"));const g=a==="pending"?"布局待保存…":a==="saved"?`布局已保存 ${u??""}`.trimEnd():a==="error"?"保存失败 · 回车重试":"布局";K.textContent=g}function so(){p.style.display="block",rt(),Ue(),p.focus()}function io(){p.style.display="none"}function ro(){T.abort();for(const a of U)clearTimeout(a)}return{root:p,reconcile:_t,activate:so,deactivate:io,adoptExternalLayout:to,snapshotDoc:no,setLamp:oo,notice:w,destroy:ro,seam:{pointerDown:ve,pointerMove:Ie,pointerUp:Z,wheel:Te,key:lt,keyUp:nt,contextMenu(a){a.preventDefault(),A.contextMenuAt(a.clientX,a.clientY,a.target)}}}}const Ts=800;function _s(t){let e,n=!1,s=!1,o=!1,i="idle";function r(h){h!==i&&(i=h,t.onLamp(h))}function l(){e!==void 0&&(e(),e=void 0)}function m(){l(),e=t.schedule(()=>{e=void 0,c(!1)},Ts)}async function c(h){if(n){s=!0;return}n=!0,l();const b=t.snapshot();let L;try{L=JSON.stringify(b)}catch{n=!1,r("error"),t.onHttpError("layout document is not JSON-serializable");return}try{const T=await t.send(b,{keepalive:h});if(T===null||typeof T!="object"||T.ok!==!0){r("error");const U=T!==null&&typeof T=="object"&&typeof T.error=="string"?T.error:"layout save refused";t.onHttpError(`layout save: ${U}`)}else JSON.stringify(t.snapshot())===L&&(t.onAdopt(T.layout),r("saved"))}catch(T){r("error"),t.onHttpError(`layout save unreachable: ${String((T==null?void 0:T.message)??T).slice(0,80)}`)}if(n=!1,i==="error"){o=!1;return}if(o){o=!1,c(!0);return}s&&(s=!1,r("pending"),m())}return{markDirty(){if(s=!1,r("pending"),n){s=!0;return}m()},retry(){i!=="error"||n||(r("pending"),c(!1))},flush(){if(n){o=!0,s=!0;return}l(),c(!0)},isBusy(){return n},dispose(){l()}}}function jn(t){return typeof t.error=="string"?t.error:void 0}function Os(t){const e=new Map;let n=0;function s(r,l){n+=1;const m=e.get(r)??Promise.resolve(),c=async()=>{try{return await l()}finally{n-=1}},h=m.then(c,c);return e.set(r,h.then(()=>{},()=>{})),h}async function o(r){let l;try{l=await t.send(r)}catch(c){const h=String((c==null?void 0:c.message)??c).slice(0,80);return t.onNotice("error",`画布不可达:${h}`),!1}if(l.status>=400)return t.onNotice("error",jn(l.body)??`HTTP ${l.status}`),!1;if(l.body.ok===!0)return!0;const m=jn(l.body);return m!==void 0?(t.onNotice("error",m),!1):!0}async function i(r,l){for(const m of l)if(!await o({...r,id:m}))return!1;return!0}return{createTeam(r,l,m=!1){return s(r,async()=>{if(!await o({action:"create",name:r}))return!1;for(let c=0;c<l.length;c++)if(!await o({action:"add-member",name:r,id:l[c]}))return m&&c===0&&await o({action:"remove",name:r}),!1;return!0})},addMembers(r,l){return s(r,()=>i({action:"add-member",name:r},l))},removeMembers(r,l){return s(r,()=>i({action:"remove-member",name:r},l))},runRosterOps(r,l){return s(r,async()=>{for(const m of l){const c=m.op==="remove"?{action:"remove-member",name:r,id:m.id}:{action:"add-member",name:r,id:m.id};if(!await o(c))return!1}return!0})},removeTeam(r){return s(r,()=>o({action:"remove",name:r}))},hasPending(){return n>0}}}const eo=document.getElementById("app"),Ps=(()=>{try{return window.sessionStorage.getItem("dsh_a2a_key")??""}catch{return""}})(),sn=window.__DSH_A2A_KEY__??Ps,Je=(t,e={})=>fetch(t,{...e,headers:{...e.headers??{},...sn!==""?{"X-API-Key":sn}:{}}});sn===""&&Je("/__dsh_a2a/owner-settings").then(t=>{if(t.status!==401)return;const e=document.createElement("div");e.className="nexus-keygate",e.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 n=document.createElement("div");n.textContent="此面板经远程面打开(密钥不随页面下发)——输入控制密钥";const s=document.createElement("input");s.type="password",s.placeholder="X-API-Key",s.setAttribute("aria-label","控制密钥");const o=document.createElement("button");o.type="button",o.textContent="进入面板";const i=document.createElement("div");i.style.color="#b00";const r=()=>{const l=s.value.trim();l!==""&&fetch("/__dsh_a2a/owner-settings",{headers:{"X-API-Key":l}}).then(m=>{if(m.status===401){i.textContent="密钥不对,再试一次";return}try{window.sessionStorage.setItem("dsh_a2a_key",l)}catch{}window.location.reload()})};o.addEventListener("click",r),s.addEventListener("keydown",l=>{l.key==="Enter"&&r()}),e.append(n,s,o,i),document.body.appendChild(e)});const It=document.createElement("div");It.className="nexus-fault";eo.appendChild(It);const{fault:rn,clear:Fs}=co({show(t){It.textContent=t,It.style.display="block"},hide(){It.style.display="none"}},t=>console.error(t));let Wt;const Hn="dsh-a2a.viewport.",Ds={get(t){try{const e=window.localStorage.getItem(Hn+t);return e===null?void 0:JSON.parse(e)}catch{return}},set(t,e){try{window.localStorage.setItem(Hn+t,JSON.stringify({x:e.x,y:e.y,scale:e.scale}))}catch{}}},ft=Is({viewportStore:Ds,onDirty:()=>Kt.markDirty(),onLampClick:()=>Kt.retry(),onNodePick:t=>{Wt==null||Wt(t)},onCanvasAction:async t=>{const e=await Rs(t);return Gt(),e}}),Kt=_s({snapshot:()=>ft.snapshotDoc(),send:(t,e)=>Je("/__dsh_a2a/canvas-layout",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"save",layout:t}),cache:"no-store",keepalive:e.keepalive}).then(async n=>await n.json()),schedule:(t,e)=>{const n=setTimeout(t,e);return()=>{clearTimeout(n)}},now:Date.now,onLamp:t=>{an=t;const e=new Date,n=String(e.getHours()).padStart(2,"0")+":"+String(e.getMinutes()).padStart(2,"0");ft.setLamp(t,n)},onAdopt:t=>{ft.adoptExternalLayout(t)},onHttpError:t=>rn(t)});window.addEventListener("pagehide",()=>Kt.flush());const Lt=Os({send:async t=>{const e=await Je("/__dsh_a2a/canvas",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),cache:"no-store"});return{status:e.status,body:await e.json()}},onNotice:(t,e)=>ft.notice(t,e)});function Rs(t){if((t.type==="add-member"||t.type==="remove-member")&&t.fleetPeer!==void 0)return(async()=>{for(const e of t.ids){const n=await Je("/__dsh_a2a/fleet-canvas-op",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({peer:t.fleetPeer,op:t.type==="add-member"?"add-member":"remove-member",name:t.team,id:e}),cache:"no-store"}).catch(()=>{}),s=n!==void 0?await n.json().catch(()=>{}):void 0;if((s==null?void 0:s.ok)!==!0)return!1}return!0})();switch(t.type){case"create-team":return Lt.createTeam(t.name,t.ids,t.created);case"add-member":return Lt.addMembers(t.team,t.ids);case"remove-member":return Lt.removeMembers(t.team,t.ids);case"remove-team":return Lt.removeTeam(t.name);case"reorder":return Lt.runRosterOps(t.team,t.ops);case"join-network":case"leave-network":return Bs(t.type==="join-network"?"join":"leave",t.id)}}async function Bs(t,e){const n=await Je(`/__dsh_a2a/${t}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:e}),cache:"no-store"}).catch(()=>{});return n!==void 0&&n.ok}let an="idle",Ut=!1,Yn,Zt=!1;async function js(){const t=await Je("/__dsh_a2a/canvas-layout",{cache:"no-store"});if(!t.ok)throw new Error(`/__dsh_a2a/canvas-layout ${t.status}`);return(await t.json()).layout??null}const zt=Lo({now:()=>Date.now(),async ownerSettingsRead(){try{return await(await Je("/__dsh_a2a/owner-settings")).json()}catch{return{ok:!1,error:"unreachable"}}},async ownerSettingsWrite(t){try{return await(await Je("/__dsh_a2a/owner-settings",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t)})).json()}catch{return{ok:!1,error:"unreachable"}}},async abandon(t,e){try{return(await Je("/__dsh_a2a/tasks/abandon",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({task_id:t,reason:e})})).ok}catch{return!1}},copy(t){var e;(e=navigator.clipboard)==null||e.writeText(t).catch(()=>{})},async canvasOp(t,e,n){try{const s=await Je("/__dsh_a2a/canvas",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({action:t,name:e,id:n})}),o=await s.json().catch(()=>({}));return s.ok&&o.ok!==!1?!0:(console.warn(`canvas ${t} ${e}: ${o.error??`HTTP ${s.status}`}`),!1)}catch{return!1}},async dispatchQuick(t,e){try{const n=await Je("/__dsh_a2a/dispatch",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({team:t,message:e})}),s=await n.json().catch(()=>({}));return{ok:n.ok&&s.ok===!0,task_id:s.task_id,reply:s.reply,error:s.error??`HTTP ${n.status}`}}catch(n){return{ok:!1,error:n instanceof Error?n.message:String(n)}}},async sessionLog(t){try{const e=await Je(`/__dsh_a2a/session-log?id=${encodeURIComponent(t)}`),n=await e.json().catch(()=>({}));return{ok:e.ok&&n.ok===!0,messages:n.messages,error:n.error??(e.ok?void 0:`HTTP ${e.status}`)}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}},async sessionLogList(){try{const t=await Je("/__dsh_a2a/session-log"),e=await t.json().catch(()=>({}));return{ok:t.ok&&e.ok===!0,sessions:e.sessions,count:typeof e.count=="number"?e.count:void 0,error:e.error??(t.ok?void 0:`HTTP ${t.status}`)}}catch(t){return{ok:!1,error:t instanceof Error?t.message:String(t)}}},async remoteSessionLog(t){try{const e=new URLSearchParams;t.team!==void 0&&e.set("team",t.team),t.peer!==void 0&&e.set("peer",t.peer),t.id!==void 0&&e.set("id",t.id),t.limit!==void 0&&e.set("limit",String(t.limit));const n=await Je(`/__dsh_a2a/remote-session-log?${e.toString()}`),s=await n.json().catch(()=>({}));return{ok:n.ok&&s.ok===!0,messages:s.messages,sessions:s.sessions,error:s.error??(n.ok?void 0:`HTTP ${n.status}`),via:s.via}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}},board:{root:ft.root,activate:()=>ft.activate(),deactivate:()=>ft.deactivate(),available:()=>Ut}});eo.appendChild(zt.root);Wt=t=>{zt.openNodeChat(t)};if(new URLSearchParams(window.location.search).get("mode")==="plan"){const t=window.setInterval(()=>{Ut&&(zt.selectTab("board"),window.clearInterval(t))},300);window.setTimeout(()=>window.clearInterval(t),3e4)}async function Gt(){var t;try{const e=await Je("/__dsh_a2a/state",{cache:"no-store"});if(!e.ok)throw new Error(`/__dsh_a2a/state ${e.status}`);const n=await e.json();if(Fs(),Ut=n.canvas!==void 0,zt.update(n),Ut)try{const c=await js(),h=JSON.stringify(c??null);h!==Yn&&(Yn=h,(an==="idle"||an==="saved")&&!Kt.isBusy()&&ft.adoptExternalLayout(c)),Zt=!0}catch(c){if(!Zt){rn(`canvas layout 获取失败:${String(c)}`);return}}else Zt=!0;const s=(n.sessions??[]).map(c=>({...c,joined:c.joined===!0})),o=((t=n.canvas)==null?void 0:t.teams)??[],i=(n.peers??[]).filter(c=>c!==null&&typeof c=="object"&&typeof c.url=="string"),r=(n.inFlight??[]).filter(c=>c!==null&&typeof c=="object"&&typeof c.team=="string"&&typeof c.peer=="string"&&Number.isFinite(c.startedAt)),l=(n.remote??[]).filter(c=>c!==null&&typeof c=="object"&&typeof c.team=="string"&&typeof c.via=="string").map(c=>({team:c.team,name:c.name,via:c.via,workspace:c.workspace,...typeof c.origin=="string"&&c.origin!==""?{origin:c.origin}:{},...Array.isArray(c.teams)&&c.teams.length>0?{teams:c.teams.filter(h=>typeof h=="string"&&h!=="")}:{}})),m=(n.peerOrg??[]).filter(c=>c!==null&&typeof c=="object").filter(c=>typeof c.url=="string"&&Array.isArray(c.org)).map(c=>({url:c.url,org:c.org.filter(h=>h!==null&&typeof h=="object").filter(h=>typeof h.team=="string"&&h.team!=="").map(h=>({name:typeof h.name=="string"?h.name:"",team:h.team,members:Array.isArray(h.members)?h.members.filter(b=>typeof b=="string"):[]}))}));ft.reconcile({sessions:s,teams:o,peerCount:i.length,peers:i,inFlight:r,remoteTeams:l,peerOrg:m})}catch(e){rn(`state 轮询失败:${String(e)}`)}}Gt();window.setInterval(()=>{document.hidden||Gt()},3e3);document.addEventListener("visibilitychange",()=>{document.hidden||Gt()});
|
|
@@ -18,8 +18,8 @@ html,body{margin:0;height:100%;background:var(--n-bg);color:var(--n-ink);
|
|
|
18
18
|
font-family:"Segoe UI",system-ui,sans-serif;}
|
|
19
19
|
#app{width:100%;height:100%;position:relative}
|
|
20
20
|
</style>
|
|
21
|
-
<script type="module" crossorigin src="./assets/index-
|
|
22
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
21
|
+
<script type="module" crossorigin src="./assets/index-CTWH6QRh.js"></script>
|
|
22
|
+
<link rel="stylesheet" crossorigin href="./assets/index-BqepxJ7E.css">
|
|
23
23
|
</head>
|
|
24
24
|
<body>
|
|
25
25
|
<div id="app"></div>
|