@nelsonlongxiang/dsh-open-a2a-net 0.6.36 → 0.6.38
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 +7 -4
- package/README_zh.md +7 -4
- package/assets/nexusDist/assets/index-C7HagaGy.css +1 -0
- package/assets/nexusDist/assets/index-NkNSeIx6.js +9 -0
- package/assets/nexusDist/index.html +2 -2
- package/cli/a2a.mjs +35 -5
- package/lib/a2a-client.js +3 -3
- package/lib/canvas-discovery.js +29 -0
- package/lib/client.js +63 -63
- package/lib/direct-forward.js +49 -27
- package/lib/faces/admin.js +30 -4
- package/lib/faces/canvas-notify.js +8 -6
- package/lib/faces/wire.js +29 -10
- package/lib/index.js +107 -24
- package/lib/origin-claim.js +31 -8
- package/lib/owner-settings.js +38 -1
- package/lib/peer-directory.js +1 -1
- package/lib/peer-link-display.js +15 -0
- package/lib/skill/references/cli.md +11 -3
- package/lib/skill/references/pitfalls.md +1 -1
- package/lib/skill/references/setup.md +9 -9
- package/lib/task-auth.js +1 -1
- package/lib/task-ledger-rows.js +220 -0
- package/lib/task-ledger.js +13 -196
- package/lib/tools/info.js +14 -5
- package/lib/types/a2a-client.d.ts +1 -0
- package/lib/types/canvas-discovery.d.ts +20 -0
- package/lib/types/direct-forward.d.ts +9 -0
- package/lib/types/faces/admin.d.ts +11 -0
- package/lib/types/faces/canvas-notify.d.ts +3 -1
- package/lib/types/faces/wire.d.ts +4 -1
- package/lib/types/index.d.ts +3 -1
- package/lib/types/origin-claim.d.ts +16 -4
- package/lib/types/owner-settings.d.ts +5 -0
- package/lib/types/peer-link-display.d.ts +13 -0
- package/lib/types/task-auth.d.ts +2 -0
- package/lib/types/task-ledger-rows.d.ts +352 -0
- package/lib/types/task-ledger.d.ts +7 -288
- package/lib/types/tools/info.d.ts +5 -0
- package/lib/types/types.d.ts +2 -1
- package/nexus-stage/src/planning-member-handles.ts +28 -1
- package/nexus-stage/src/planning-menus.ts +12 -5
- package/nexus-stage/src/planning-view.ts +18 -14
- package/nexus-stage/src/seat-name-editor.ts +31 -0
- package/nexus-stage/src/session-drag.ts +64 -0
- package/nexus-stage/src/wb-directory.ts +2 -0
- package/nexus-stage/src/workbench.css +2 -0
- package/nexus-stage/src/workbench.ts +16 -5
- package/package.json +1 -1
- package/assets/nexusDist/assets/index-DIQNDBy6.js +0 -9
- package/assets/nexusDist/assets/index-z33lHtLw.css +0 -1
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* @module nexus-stage/workbench
|
|
20
20
|
*/
|
|
21
21
|
import { createChatDrawer, type ChatTarget } from './wb-chat'
|
|
22
|
+
import { createSeatNameEditor } from './seat-name-editor'
|
|
22
23
|
import { createCliHomePicker, type CliHomeOptions } from './cli-home-picker'
|
|
23
24
|
import { createRailTabs } from './wb-rail'
|
|
24
25
|
import { DIRECTORY_FILTERS, learnLogTitle, loadLogTitles, renderDirectory, type DirFilter } from './wb-directory'
|
|
@@ -95,6 +96,7 @@ export interface SessionRow {
|
|
|
95
96
|
readonly label: string
|
|
96
97
|
readonly team: string
|
|
97
98
|
readonly name?: string
|
|
99
|
+
readonly seatName?: string
|
|
98
100
|
readonly description?: string
|
|
99
101
|
readonly workspace?: string
|
|
100
102
|
readonly joined?: boolean
|
|
@@ -207,9 +209,9 @@ export interface WorkbenchDeps {
|
|
|
207
209
|
/** gh#41 fleet planning: each tracked peer's published canvas org. */
|
|
208
210
|
peerOrg?: readonly PeerOrgRow[]
|
|
209
211
|
/** gh#34: read the owner three-key panel state (GET /__dsh_a2a/owner-settings). */
|
|
210
|
-
ownerSettingsRead?(): Promise<{ ok: boolean; teamJoinAllowlist?: string[]; teamScopeInfo?: boolean; announce?: boolean; announceRestartPending?: boolean; error?: string }>
|
|
212
|
+
ownerSettingsRead?(): Promise<{ ok: boolean; seatNames?: Record<string, string>; teamJoinAllowlist?: string[]; teamScopeInfo?: boolean; announce?: boolean; announceRestartPending?: boolean; error?: string }>
|
|
211
213
|
/** gh#34: write owner panel changes; true on success (POST the same face). */
|
|
212
|
-
ownerSettingsWrite?(changes: { teamJoinAllowlist?: string[]; teamScopeInfo?: boolean; announce?: boolean }): Promise<{ ok: boolean; restartNeeded?: boolean; error?: string }>
|
|
214
|
+
ownerSettingsWrite?(changes: { seatNames?: Record<string, string>; teamJoinAllowlist?: string[]; teamScopeInfo?: boolean; announce?: boolean }): Promise<{ ok: boolean; restartNeeded?: boolean; error?: string }>
|
|
213
215
|
/** gh#41 fleet planning: regulate a REMOTE peer's canvas team (this host
|
|
214
216
|
* signs the envelope and forwards; the peer's link gate authorizes). */
|
|
215
217
|
fleetCanvasOp?(peer: string, op: 'create' | 'add-member' | 'remove-member' | 'remove', name: string, id?: string): Promise<{ ok: boolean; members?: string[]; error?: string }>
|
|
@@ -375,8 +377,8 @@ export function createWorkbench(deps: WorkbenchDeps): Workbench {
|
|
|
375
377
|
const ownerBtn = el('button', 'wb-icon-btn wb-owner-btn')
|
|
376
378
|
ownerBtn.type = 'button'
|
|
377
379
|
ownerBtn.dataset.testid = 'wb-owner-btn'
|
|
378
|
-
ownerBtn.setAttribute('aria-label', '
|
|
379
|
-
ownerBtn.title = '
|
|
380
|
+
ownerBtn.setAttribute('aria-label', '主人设置')
|
|
381
|
+
ownerBtn.title = '主人设置:席位名 / 入网白名单 / 可见性 / 发布'
|
|
380
382
|
ownerBtn.textContent = '⚙'
|
|
381
383
|
ownerBtn.addEventListener('click', () => { ownerPanelOpen = !ownerPanelOpen; renderOwnerPanel() })
|
|
382
384
|
header.appendChild(ownerBtn)
|
|
@@ -827,15 +829,18 @@ export function createWorkbench(deps: WorkbenchDeps): Workbench {
|
|
|
827
829
|
|
|
828
830
|
// ── Inspector (overlay card over the stage; bottom sheet on narrow) ──
|
|
829
831
|
// gh#34 owner panel state + render (the gear toggles; the inspector hosts).
|
|
832
|
+
let seatEditor: HTMLElement | undefined
|
|
830
833
|
let ownerPanelOpen = false
|
|
831
|
-
let ownerState: { teamJoinAllowlist: string[]; teamScopeInfo: boolean; announce: boolean; announceRestartPending: boolean } | null = null
|
|
834
|
+
let ownerState: { seatNames: Record<string, string>; teamJoinAllowlist: string[]; teamScopeInfo: boolean; announce: boolean; announceRestartPending: boolean } | null = null
|
|
832
835
|
function renderOwnerPanel(): void {
|
|
833
836
|
renderInspector()
|
|
834
837
|
if (!ownerPanelOpen) return
|
|
835
838
|
void deps.ownerSettingsRead?.().then(result => {
|
|
836
839
|
if (!ownerPanelOpen) return
|
|
837
840
|
if (result.ok !== true) { ownerState = null; renderInspector(); return }
|
|
841
|
+
seatEditor = undefined
|
|
838
842
|
ownerState = {
|
|
843
|
+
seatNames: result.seatNames ?? {},
|
|
839
844
|
teamJoinAllowlist: result.teamJoinAllowlist ?? [],
|
|
840
845
|
teamScopeInfo: result.teamScopeInfo !== false,
|
|
841
846
|
announce: result.announce === true,
|
|
@@ -870,6 +875,12 @@ export function createWorkbench(deps: WorkbenchDeps): Workbench {
|
|
|
870
875
|
return
|
|
871
876
|
}
|
|
872
877
|
const st = ownerState
|
|
878
|
+
seatEditor ??= createSeatNameEditor(last?.sessions ?? [], st.seatNames, async seatNames => {
|
|
879
|
+
const result = await deps.ownerSettingsWrite?.({ seatNames })
|
|
880
|
+
if (result?.ok) { st.seatNames = seatNames; return { ok: true } }
|
|
881
|
+
return { ok: false, error: result?.error ?? '保存失败' }
|
|
882
|
+
})
|
|
883
|
+
card.appendChild(seatEditor)
|
|
873
884
|
// ① 入网白名单(精确团队名增删)
|
|
874
885
|
const alHead = el('div', 'wb-side-head')
|
|
875
886
|
alHead.textContent = '入网白名单(精确团队名)'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nelsonlongxiang/dsh-open-a2a-net",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.38",
|
|
4
4
|
"description": "Open A2A network plugin for DeepSeek Harness: signed agent cards, decentralized peer/zone discovery, direct routing model tools, and joinable session nodes with a sidebar control",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
var Ao=Object.defineProperty;var Lo=(e,t,n)=>t in e?Ao(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Ct=(e,t,n)=>Lo(e,typeof t!="symbol"?t+"":t,n);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.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 an=6e4;function Io(e,t,n=Date.now){let s=-an;return{fault(o){const i=n();i-s>=an&&(t(`[nexus] ${o}`),s=i),e.show(o)},clear(){e.hide(),s=-an}}}function it(e){return e.name??e.team??e.label??""}function so(e,t){var i,r;const n=(c,d)=>c!==void 0&&c.trim()!==""?{name:c,remote:d}:void 0,s=(e.sessions??[]).find(c=>c.team===t);if(s!==void 0)return n(it(s),!1);const o=(e.remote??[]).find(c=>c.team===t);return o!==void 0?n(it(o),!0):n((r=(((i=e.canvas)==null?void 0:i.teams)??[]).find(c=>c.team===t))==null?void 0:r.name,!1)}function To(e,t){const n=so(e,t);return n===void 0?t:n.remote?`${n.name}(远端)`:n.name}function qt(e,t,n,s=""){const o=so(t,n);if(e.textContent=`${s}${(o==null?void 0:o.name)??n}`,e.title=n,(o==null?void 0:o.remote)===!0){const i=e.appendChild(document.createElement("span"));i.className="wb-row-remote",i.textContent="远端",i.title="名字由对端自行发布"}}const _o=60*6e4;function Et(e){var t;return e.direction==="inbound"||e.direction===void 0&&((t=e.peer)==null?void 0:t.startsWith("local:"))===!0}function An(e){var t;return((t=e.peer)==null?void 0:t.startsWith("local:"))===!0?e.peer.slice(6):void 0}function Ft(e,t){return e.settleable!==void 0?e.settleable===!1:t-e.startedAt>=_o}function pn(e,t){const n=(e.tasks??[]).filter(r=>r.receiptExpected!==!1),s=n.filter(r=>!Et(r)&&Ft(r,t)),o=n.filter(r=>Et(r)&&Ft(r,t)),i=e.tasksDead??[];return{stale:s,owedOverdue:o,deadLetters:i.filter(r=>r.reason!=="fire-forget"),expired:i.filter(r=>r.reason==="fire-forget")}}function Ee(e,t){const n=document.createElement(e);return t!==void 0&&(n.className=t),n}function Ln(e,t){const n=Math.max(0,Math.round((t-e)/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 jt(e,t,n,s,o){const i=Ee("div",`wb-led-tile${o!==void 0?` is-${o}`:""}`);i.title=s,i.appendChild(Ee("span","wb-led-tile-v")).textContent=String(n),i.appendChild(Ee("span","wb-led-tile-k")).textContent=t,e.appendChild(i)}const hn=[{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 Oo(e,t,n){const s=Ee("div","wb-led-split"),o=Ee("div","wb-led-split-bar");o.setAttribute("role","img");const i=Ee("div","wb-led-split-legend"),r=new Set(hn.map(m=>m.key)),c=hn.map(m=>[m.tone,m.label,t[m.key]??0]);for(const[m,g]of Object.entries(t))r.has(m)||c.push(["other",m,g]);const d=[];for(const[m,g,u]of c){if(u<=0)continue;const E=Ee("span",`wb-led-seg is-${m}`);E.style.width=`${Math.max(2,u/n*100)}%`,o.appendChild(E);const M=Ee("span","wb-led-split-item");M.appendChild(Ee("i",`wb-led-swatch is-${m}`)),M.appendChild(document.createTextNode(`${g} ${u}`)),i.appendChild(M),d.push(`${g} ${u}`)}o.setAttribute("aria-label",`归档结局:${d.join(",")}`),s.append(o,i),e.appendChild(s)}function Fo(e,t){var Ae;e.replaceChildren();const{state:n,now:s}=t,o=n.tasks??[],i=n.tasksDead??[],r=n.archivedCount??0,c=pn(n,s),d=o.filter(P=>P.receiptExpected===!1),m=o.filter(P=>P.receiptExpected!==!1),g=m.filter(P=>Et(P)),u=m.filter(P=>!Et(P)),E=c.stale,M=u.filter(P=>!Ft(P,s)),J=c.stale.length,fe=Ee("div","wb-led-tiles");jt(fe,"待回执",m.length,`要回执、仍未结算的任务(含陈旧与本机欠对方的入站行)${d.length>0?`;另有免回执 ${d.length} 条不计`:""}`),jt(fe,"陈旧",J,"我方派发、要回执、已等待 ≥1h 仍未回执(可催办);本机欠对方的入站行在「待本机回执」组另计,免回执行不算陈旧",J>0?"warn":void 0),jt(fe,"死信",c.deadLetters.length,"超过 24h TTL 仍未结算(unconsumed);需清账(abandon)才能移出。免回执到期另列,不算死信",c.deadLetters.length>0?"danger":void 0),jt(fe,"已归档",r,"已离开台账并留档的任务(结算、拒绝或放弃),用于审计"),e.appendChild(fe),r>0&&n.archivedSplit!==void 0&&Oo(e,n.archivedSplit,r);const ne=(P,U)=>{const ie=Ee("div",`wb-led-card is-${U.tone}`),Re=Ee("div","wb-led-card-head");Re.appendChild(Ee("span",`wb-led-dir${U.inbound?" is-in":""}`)).textContent=U.inbound?"↙":"↗";const $e=Ee("span","wb-led-brief");$e.textContent=U.brief!==void 0&&U.brief!==""?U.brief:"(无摘要——派发未带 brief)",(U.brief===void 0||U.brief==="")&&$e.classList.add("is-missing"),Re.appendChild($e),ie.appendChild(Re);const re=Ee("div","wb-led-meta"),Ce=re.appendChild(Ee("span","wb-led-team"));U.inbound?U.sender!==void 0?qt(Ce,n,U.sender,"来自 "):Ce.textContent="来自 对端":qt(Ce,n,U.team,"发往 "),U.inbound&&qt(re.appendChild(Ee("span","wb-led-to")),n,U.team,"至 "),re.appendChild(Ee("span")).textContent=U.atText,re.appendChild(Ee("span","wb-led-task")).textContent=U.taskId;for(const Q of U.chips)re.appendChild(Ee("span","wb-led-chip")).textContent=Q;if(ie.appendChild(re),ie.title=`${U.taskId}
|
|
2
|
-
${U.team}`,U.dead!==void 0){const Q=U.dead,oe=Q.reason==="fire-forget",xe=Ee("button",`wb-btn wb-led-abandon${oe?" is-quiet":""}`);xe.type="button",xe.textContent=oe?"移出":"清账",xe.title=oe?"可选:把这条已过期的免回执记录移出台账(不是失败,不处理也无妨)":"从台账移出这条死信(abandon)",xe.addEventListener("click",le=>{le.stopPropagation(),xe.disabled=!0,t.abandon(Q.taskId,"workbench dead-letter cleanup").then(te=>{xe.disabled=!1,xe.textContent=te?"已清":"失败"})}),ie.appendChild(xe)}if(t.canOpenTeam(U.team)){ie.classList.add("is-link"),ie.setAttribute("role","button"),ie.tabIndex=0,ie.setAttribute("aria-label",`${$e.textContent},打开 ${U.team} 的对话`);const Q=()=>{t.openTeam(U.team)};ie.addEventListener("click",Q),ie.addEventListener("keydown",oe=>{(oe.key==="Enter"||oe.key===" ")&&(oe.preventDefault(),Q())})}P.appendChild(ie)},S=(P,U,ie,Re)=>{if(U===0)return null;const $e=Ee("div",`wb-led-group is-${ie}`);$e.dataset.group=P;const re=Ee("div","wb-led-group-head");return re.appendChild(Ee("span")).textContent=`${P} · ${U}`,re.appendChild(Ee("span","wb-led-group-hint")).textContent=Re,$e.appendChild(re),e.appendChild($e),$e},C=(P,U)=>{const ie=Et(P);return{brief:P.brief,team:P.team,sender:An(P),taskId:P.taskId,atText:`${Ln(P.startedAt,s)} 前${ie?"收到":"派发"}`,inbound:ie,tone:U,chips:[...P.settleable===!0?["可结算"]:[],...P.receiptExpected===!1?["无回执债"]:[],...ie?["入站"]:[],...P.status!=="pending"?[P.status]:[]]}},$=(P,U,ie)=>({brief:P.brief,team:P.team,sender:An(P),taskId:P.taskId,atText:`${Ln(P.deadAt,s)} 前${ie}`,inbound:Et(P),tone:U,dead:P,chips:P.reason!==void 0&&P.reason!==""&&P.reason!=="unspecified"&&P.reason!=="fire-forget"?[P.reason]:[]}),k=S("死信",c.deadLetters.length,"danger","需清账");if(k!==null)for(const P of[...c.deadLetters].sort((U,ie)=>ie.deadAt-U.deadAt))ne(k,$(P,"danger","死信"));const V=S("陈旧",E.length,"warn","我方派发 ≥1 小时仍无回执,可催办");if(V!==null)for(const P of[...E].sort((U,ie)=>U.startedAt-ie.startedAt))ne(V,C(P,"warn"));const y=c.owedOverdue.length,f=S("待本机回执",g.length,y>0?"warn":"quiet",y>0?`对方在等本机回执 · ${y} 条超过 1 小时`:"对方在等本机回执");if(f!==null)for(const P of[...g].sort((U,ie)=>U.startedAt-ie.startedAt))ne(f,C(P,Ft(P,s)?"warn":"quiet"));const _=S("等待回执",M.length,"quiet","1 小时内");if(_!==null)for(const P of[...M].sort((U,ie)=>ie.startedAt-U.startedAt))ne(_,C(P,"quiet"));const p=S("免回执",d.length,"muted","不等回执,24h 后自动归档");if(p!==null)for(const P of d)ne(p,C(P,"muted"));const R=S("已过期(免回执)",c.expired.length,"muted","正常记账,不是失败");if(R!==null)for(const P of[...c.expired].sort((U,ie)=>ie.deadAt-U.deadAt))ne(R,$(P,"muted","过期"));o.length+i.length===0&&(e.appendChild(Ee("div","wb-led-empty")).textContent="台账为空——没有待回执的任务");const j=n.idempotency,K=(Ae=n.reconcile)==null?void 0:Ae.state;if(j!==void 0||K!==void 0){const P=Ee("details","wb-led-forensics wb-forensics");P.appendChild(Ee("summary")).textContent="取证";const U=Ee("div","wb-led-forensics-body");j!==void 0&&(U.appendChild(Ee("div")).textContent=`幂等 claims ${j.claimsFresh??0} · replays ${j.replays??0} · conflicts ${j.conflicts??0}`),K!==void 0&&(U.appendChild(Ee("div")).textContent=`reconcile ${K}`),P.appendChild(U),e.appendChild(P)}const we=m.length+c.deadLetters.length;return{badge:we>0?String(we):"",tone:c.deadLetters.length>0?"danger":J>0||y>0?"warn":void 0}}const Lt=4e3,Po=32;function ye(e,t){const n=document.createElement(e);return t!==void 0&&(n.className=t),n}function Bt(e,t,n=""){const s=ye("button",`wb-icon-btn wb-chat-act ${n}`.trim());return s.type="button",s.setAttribute("aria-label",e),s.title=e,s.textContent=t,s}function cn(e,t){const n=Math.max(0,Math.round((t-e)/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 Ro(e){return e>=1e6?`${(e/1e6).toFixed(1)} MB`:e>=1e3?`${Math.round(e/1e3)} KB`:`${e} B`}function ln(e){const t=e.kind==="session"||e.kind==="remote"?e.team:void 0;return t!==void 0&&t!==""?t:void 0}function In(e){return e.kind==="remote"?`remote:${e.team}`:`${e.kind}:${e.id}`}function Do(e){let t=null,n=null,s=!1,o=!1;const i=new Map,r=new Map,c=new Map,d=new Map,m=new Set,g=new Map,u=new Map,E=ye("aside","wb-chat");E.setAttribute("aria-label","对话");const M=ye("div","wb-chat-head"),J=Bt("返回会话列表","‹","wb-chat-back"),fe=ye("span","wb-chat-dot"),ne=ye("div","wb-chat-titles"),S=ye("span","wb-chat-title"),C=ye("span","wb-chat-sub");ne.append(S,C);const $=Bt("刷新对话","↻","wb-chat-refresh"),k=Bt("会话详情","ⓘ","wb-chat-info-btn");k.setAttribute("aria-expanded","false");const V=Bt("关闭对话","✕","wb-chat-close");M.append(J,fe,ne,$,k,V);const y=ye("div","wb-chat-info");y.hidden=!0;const f=ye("div","wb-chat-thread");f.setAttribute("role","log"),f.setAttribute("aria-live","polite"),f.tabIndex=0;const _=ye("div","wb-chat-notice"),p=ye("div","wb-chat-log"),R=ye("div","wb-chat-sent");f.append(_,p,R);const j=ye("div","wb-chat-foot");E.append(M,y,f,j),J.addEventListener("click",()=>{(t==null?void 0:t.kind)==="peer"&&(t.picked=void 0,Oe())}),$.addEventListener("click",()=>{if(t===null)return;const l=K(t);l!==void 0&&i.delete(l),t.kind==="peer"&&t.picked===void 0&&t.url!==void 0&&c.delete(`peer:${t.url}`),xe(!0)}),k.addEventListener("click",()=>{o=!o,y.hidden=!o,k.setAttribute("aria-expanded",String(o))}),V.addEventListener("click",()=>lt()),f.addEventListener("scroll",()=>{const l=t!==null?K(t):void 0;l!==void 0&&r.set(l,f.scrollTop)}),document.addEventListener("keydown",l=>{if(l.key!=="Escape"||!E.classList.contains("is-open"))return;const A=l.target;if(A instanceof HTMLElement){if(!E.contains(A)){const L=A instanceof HTMLTextAreaElement||A instanceof HTMLInputElement||A.isContentEditable,Z=A.closest(".wb-stage-board")!==null;if(L||Z)return}lt()}});function K(l){if(l.kind==="session"||l.kind==="log")return e.sessionLog!==void 0?`local:${l.id}`:void 0;if(l.kind==="remote")return e.remoteSessionLog!==void 0?`remote:${l.team}`:void 0;if(l.picked!==void 0&&l.url!==void 0&&e.remoteSessionLog!==void 0)return`peer:${l.url}:${l.picked}`}function we(l){var A,L,Z;return l.kind==="session"||l.kind==="log"?((A=e.sessionLog)==null?void 0:A.call(e,l.id))??Promise.resolve({ok:!1,error:"sessionLog unavailable"}):l.kind==="remote"?((L=e.remoteSessionLog)==null?void 0:L.call(e,{team:l.team}))??Promise.resolve({ok:!1,error:"remoteSessionLog unavailable"}):((Z=e.remoteSessionLog)==null?void 0:Z.call(e,{peer:l.url,id:l.picked}))??Promise.resolve({ok:!1,error:"remoteSessionLog unavailable"})}function Ae(){const l=t;if(l===null)return;const A=l.kind==="log"||l.kind==="remote"||l.kind==="session"&&l.live===!1;fe.className=`wb-chat-dot ${l.kind==="peer"?"is-peer":A?"is-cold":"is-live"}`,fe.title=l.kind==="peer"?"对端主机":l.kind==="log"?"只读日志":l.kind==="remote"?"远端会话":l.live===!1?"冷会话":"在线",S.textContent=l.kind==="peer"&&l.picked!==void 0?`…${l.picked.slice(-12)}`:l.title,C.textContent=l.kind==="peer"&&l.picked!==void 0?l.title:l.sub,J.hidden=!(l.kind==="peer"&&l.picked!==void 0)}function P(l,A){const L=ye("div","wb-kv");L.appendChild(ye("span","wb-kv-k")).textContent=l,L.appendChild(ye("span","wb-kv-v")).textContent=A,y.appendChild(L)}function U(){var A,L,Z;y.replaceChildren();const l=t;l!==null&&(l.kind==="session"?(P("会话",l.id),l.team!==void 0&&P("路由",l.team),P("来源","本机会话日志")):l.kind==="log"?(P("会话",l.id),P("来源","本机会话日志(不在网络目录)")):l.kind==="remote"?(P("路由",l.team),((A=l.row)==null?void 0:A.origin)!==void 0&&P("来源",l.row.origin),((L=l.row)==null?void 0:L.via)!==void 0&&P("经",l.row.via),((Z=l.row)==null?void 0:Z.workspace)!==void 0&&P("工作区",l.row.workspace)):(P("对端",l.url??l.sub),l.picked!==void 0&&P("会话",l.picked),P("来源","经本机代理读取对端 /a2a/log")))}function ie(l){return l.kind==="log"?"只读日志 —— 此会话当前不在网络目录(可能已归档或未入网)。":l.kind==="remote"?e.remoteSessionLog!==void 0?"远端会话 —— 经本机代理从对端 /a2a/log 读取最近对话。":"远端节点的对话记录在对端机器上;本页的代理读取面未启用。":l.kind==="peer"?l.url===void 0||e.remoteSessionLog===void 0?`对端主机节点(${l.sub})—— 会话记录存放在对端机器上,本页只读本机会话日志。`:l.picked===void 0?"对端主机 —— 选择一个会话阅读(经本机代理读取对端 /a2a/log)。":"":e.sessionLog===void 0?"本页未接入会话日志读取,只显示从这里发出的消息。":""}function Re(){return f.scrollHeight-f.scrollTop-f.clientHeight<=Po}function $e(l){const A=()=>{f.scrollTop=f.scrollHeight};A(),requestAnimationFrame(A)}function re(l,A){const L=ye("div",`wb-chat-empty${A==="error"?" is-error":""}`);return L.textContent=l,L}function Ce(l,A){const L=l==="user",Z=ye("div",`wb-msg ${L?"wb-msg-user":"wb-msg-assistant"}`),B=ye("span","wb-msg-who");B.textContent=L?"问":"答";const he=ye("div","wb-msg-text");return he.textContent=A,Z.append(B,he),Z}function Q(l){if(p.replaceChildren(),l===void 0){p.appendChild(re("读取中…"));return}if(l.ok!==!0||l.messages===void 0){p.appendChild(re(`无法读取(${l.error??"未知错误"})`,"error"));return}if(l.messages.length===0){p.appendChild(re("暂无对话记录"));return}for(const A of l.messages)p.appendChild(Ce(A.role,A.text))}function oe(l,A){if(p.replaceChildren(),A===void 0){p.appendChild(re("读取中…"));return}if(A.ok!==!0||A.sessions===void 0){p.appendChild(re(`无法读取(${A.error??"未知错误"})`,"error"));return}if(A.sessions.length===0){p.appendChild(re("对端没有可读会话"));return}const L=ye("div","wb-chat-sessions"),Z=e.now();for(const B of A.sessions){const he=ye("button","wb-chat-session");he.type="button",he.appendChild(ye("span","wb-chat-session-id")).textContent=`…${B.id.slice(-12)}`;const ge=[B.mtimeMs!==void 0?cn(B.mtimeMs,Z):"",Ro(B.sizeBytes)].filter(Boolean).join(" · ");he.appendChild(ye("span","wb-chat-session-meta")).textContent=ge,he.title=B.id,he.addEventListener("click",()=>{(t==null?void 0:t.kind)!=="peer"||t.url!==l||(t.picked=B.id,Oe())}),L.appendChild(he)}p.appendChild(L)}function xe(l=!1){const A=t;if(A===null)return;if(_.textContent=ie(A),_.hidden=_.textContent==="",A.kind==="peer"&&A.picked===void 0){if(A.url===void 0||e.remoteSessionLog===void 0){p.replaceChildren();return}const B=A.url,he=`peer:${B}`;if(!l&&c.has(he)){oe(B,c.get(he));return}c.set(he,void 0),oe(B,void 0),e.remoteSessionLog({peer:B}).then(ge=>{c.set(he,ge),(t==null?void 0:t.kind)==="peer"&&t.url===B&&t.picked===void 0&&oe(B,ge)},ge=>{const pe={ok:!1,error:ge instanceof Error?ge.message:String(ge)};c.set(he,pe),(t==null?void 0:t.kind)==="peer"&&t.url===B&&t.picked===void 0&&oe(B,pe)});return}const L=K(A);if(L===void 0){p.replaceChildren(),ze(!0);return}const Z=()=>{const B=r.get(L);B===void 0||l?$e():(f.scrollTop=B,requestAnimationFrame(()=>{t!==null&&K(t)===L&&(f.scrollTop=B)}))};if(!l&&i.has(L)&&i.get(L)!==void 0){Q(i.get(L)),ze(!0),Z();return}l&&r.delete(L),i.set(L,void 0),Q(void 0),ze(!0),we(A).then(B=>{var he;i.set(L,B),(B==null?void 0:B.ok)===!0&&B.messages!==void 0&&((he=e.onTranscript)==null||he.call(e,A,B.messages)),!(t===null||K(t)!==L)&&(Q(B),ze(),Z())},B=>{const he={ok:!1,error:B instanceof Error?B.message:String(B)};i.set(L,he),t!==null&&K(t)===L&&Q(he)})}function le(l){return((n==null?void 0:n.tasks)??[]).filter(A=>A.team===l)}function te(l){return((n==null?void 0:n.tasksDead)??[]).filter(A=>A.team===l)}let Ne="";function je(l){return l.reason==="fire-forget"?{text:"已过期(免回执)",tone:"muted",hint:"免回执消息到 24h TTL 归档,属正常记账"}:{text:"死信",tone:"danger",hint:l.reason!==void 0&&l.reason!=="unspecified"?`${l.reason}:超过 24h TTL 仍未结算,需在台账清账`:"超过 24h TTL 仍未结算,需在台账清账"}}function qe(l,A){const L=l.direction==="inbound";if(l.receiptExpected===!1)return{text:L?"来信 · 无需回执":"已送达 · 无回执",tone:"muted",hint:"免回执消息:不等回执,24h 后自动归档"};const Z=Ft(l,A),B=L?Z?"待本机回执 · 超 1 小时":"待本机回执":Z?"陈旧":"待回执",he=l.status!=="pending"?` · ${l.status}`:"";return{text:`${B}${he}`,tone:Z?"warn":"wait",hint:`${L?"对方等待本机回执;":""}${L?"收到":"派发"}于 ${cn(l.startedAt,A)}`}}function Ke(l,A){const L=`结算于 ${cn(l.resolvedAt,A)}`;if(l.receiptExpected===!1&&l.endedBy==="abandoned")return l.late===!0?{text:"已移出(免回执) · 回执迟到",tone:"warn",hint:`${L};免回执消息本机移出后对方回执才到,结局不改写`}:{text:"已移出(免回执)",tone:"muted",hint:`${L};免回执消息,本机移出台账,不是失败`};if(l.endedBy==="abandoned"||l.endedBy==="cancelled"){const ge=l.endedBy==="cancelled"?"撤回":"放弃";return l.late===!0?{text:`已${ge} · 回执迟到`,tone:"warn",hint:`${L};本机${ge}之后对方回执才到,结局不改写`}:{text:`已${ge}`,tone:"muted",hint:`${L};本机${ge},未等到回执`}}if(l.endedBy==="echo")return{text:"已结算 · 内容回显",tone:"ok",hint:`${L};对方回了内容但未带正式回执,按内容回显结算`};if(l.endedBy===void 0&&l.outcome==="abandoned")return{text:"已放弃(本机或对方)",tone:"muted",hint:`${L};本机放弃或撤回,或对方回执报告放弃`};const Z=l.summary!==void 0&&l.summary!==""?` · ${l.summary}`:"";if(l.outcome==="abandoned")return{text:"已回执 · 对方放弃",tone:"warn",hint:`${L};对方回执报告放弃${Z}`};const B=hn.find(ge=>ge.key===l.outcome),he=(B==null?void 0:B.tone)==="completed"?"ok":(B==null?void 0:B.tone)==="failed"?"danger":(B==null?void 0:B.tone)==="rejected"?"warn":"muted";return l.outcome==="unclassified"?{text:"已回执",tone:"ok",hint:`${L};回执未带结论${Z}`}:{text:`已回执 · ${(B==null?void 0:B.label)??l.outcome}`,tone:he,hint:`${L}${Z}`}}function ct(l,A,L){const Z=te(A).find(ge=>ge.taskId===l);if(Z!==void 0)return je(Z);const B=le(A).find(ge=>ge.taskId===l);if(B!==void 0)return qe(B,L);const he=((n==null?void 0:n.archived)??[]).find(ge=>ge.taskId===l&&ge.team===A);return he!==void 0?Ke(he,L):m.has(l)?{text:"已离开台账",tone:"muted",hint:"已结算、放弃或撤回之一;主机未给出这条的结局(旧主机,或已超出最近 64 条归档)"}:{text:"已派发",tone:"muted",hint:"异步送达;回执到达后进台账"}}function xt(l){const A=e.now(),L=d.get(l)??[],Z=new Set(L.map(ae=>ae.taskId).filter(ae=>ae!==void 0)),B=ae=>ae!==void 0&&ae!==""?ae:"(无摘要)",he=le(l).filter(ae=>!Z.has(ae.taskId)).map(ae=>({at:ae.startedAt,side:ae.direction==="inbound"?"theirs":"mine",text:B(ae.brief),status:qe(ae,A),taskId:ae.taskId})),ge=te(l).filter(ae=>!Z.has(ae.taskId)).map(ae=>{var Te;const Be=ae.direction??g.get(ae.taskId)??(((Te=ae.peer)==null?void 0:Te.startsWith("local:"))===!0?"inbound":void 0);return{at:ae.startedAt,side:Be==="inbound"?"theirs":Be==="outbound"?"mine":"system",text:B(ae.brief),status:je(ae),taskId:ae.taskId}}),pe=L.map(ae=>({at:ae.at,side:"mine",text:ae.text,status:ae.state==="sending"?{text:"发送中…",tone:"muted"}:ae.state==="failed"?{text:`失败:${ae.error??"未知原因"}`,tone:"danger"}:ae.taskId!==void 0?ct(ae.taskId,l,A):{text:"已派发",tone:"muted"},taskId:ae.taskId}));return[...he,...ge,...pe].sort((ae,Be)=>ae.at-Be.at)}function ze(l=!1){const A=t,L=A!==null?ln(A):void 0,Z=L!==void 0?xt(L):[],B=JSON.stringify([L??"",...Z.map(pe=>[pe.taskId??"",pe.side,pe.text,pe.status.text])]);if(!l&&B===Ne)return;Ne=B;const he=Re();if(R.replaceChildren(),Z.length===0)return;const ge=ye("div","wb-chat-divider");ge.textContent="台账往来 · 异步送达,回执进台账",R.appendChild(ge);for(const pe of Z){const ae=pe.side==="mine"?"wb-msg wb-msg-user wb-msg-out":pe.side==="theirs"?"wb-msg wb-msg-assistant wb-msg-in":"wb-msg wb-msg-ledger",Be=ye("div",ae);Be.appendChild(ye("span","wb-msg-who")).textContent=pe.side==="mine"?"我":pe.side==="theirs"?"对方":"台账记录",Be.appendChild(ye("div","wb-msg-text")).textContent=pe.text;const Te=ye("div","wb-msg-meta");pe.taskId!==void 0&&(Te.appendChild(ye("span","wb-msg-task")).textContent=pe.taskId);const Ye=ye("span",`wb-msg-status is-${pe.status.tone}`);Ye.textContent=pe.status.text,pe.status.hint!==void 0&&(Ye.title=pe.status.hint),Te.appendChild(Ye),Be.appendChild(Te),R.appendChild(Be)}he&&$e()}function Ve(l){const A=l.text.value.length;l.note.classList.remove("is-error"),l.note.textContent=A>Lt*.9?`${A}/${Lt}`:"Enter 发送 · Shift+Enter 换行",A>Lt&&l.note.classList.add("is-error"),l.submit.disabled=l.text.value.trim()===""||A>Lt}function bt(l){l.style.height="auto",l.style.height=`${Math.min(l.scrollHeight,160)}px`}function Nt(l){const A=ye("form","wb-dispatch-form wb-chat-composer"),L=document.createElement("textarea");L.className="wb-dispatch-text",L.rows=1,L.placeholder="发一句话任务给这个节点…",L.setAttribute("aria-label","发送消息");const Z=ye("button","wb-dispatch-submit");Z.type="submit",Z.textContent="发送",Z.setAttribute("aria-label","发送");const B=ye("div","wb-dispatch-note");B.setAttribute("aria-live","polite");const he=ye("div","wb-chat-composer-row");he.append(L,Z),A.append(he,B);const ge={team:l,form:A,text:L,note:B,submit:Z};return L.addEventListener("input",()=>{bt(L),Ve(ge)}),L.addEventListener("keydown",pe=>{pe.key!=="Enter"||pe.shiftKey||pe.ctrlKey||pe.altKey||pe.metaKey||pe.isComposing||(pe.preventDefault(),A.requestSubmit())}),A.addEventListener("submit",pe=>{pe.preventDefault();const ae=L.value.trim();if(ae===""||ae.length>Lt||e.dispatchQuick===void 0)return;const Be={text:ae,at:e.now(),state:"sending"},Te=d.get(l)??[];Te.push(Be),d.set(l,Te),L.value="",bt(L),Ve(ge),L.focus({preventScroll:!0}),ze(),$e(),e.dispatchQuick(l,ae).then(Ye=>Ye,Ye=>({ok:!1,error:Ye instanceof Error?Ye.message:String(Ye)})).then(Ye=>{Ye.ok===!0?(Be.state="sent",Be.taskId=Ye.task_id,B.classList.remove("is-error"),B.textContent=`已派发${Ye.task_id!==void 0?` · ${Ye.task_id}`:""} · 回执将入台账`):(Be.state="failed",Be.error=Ye.error??"未知原因",L.value===""&&(L.value=ae,bt(L)),B.classList.add("is-error"),B.textContent=`失败:${Be.error}`,Z.disabled=L.value.trim()===""),t!==null&&ln(t)===l&&ze()})}),Ve(ge),ge}function Le(){const l=t;if(j.replaceChildren(),l===null)return;const A=ln(l);if(A!==void 0&&e.dispatchQuick!==void 0){let Z=u.get(A);Z===void 0&&(Z=Nt(A),u.set(A,Z)),j.appendChild(Z.form),s&&(s=!1,Z.text.focus({preventScroll:!0}));return}s=!1;const L=ye("div","wb-chat-readonly");L.textContent=l.kind==="log"?"只读日志:此会话不在网络目录,不能从这里派发。":l.kind==="peer"?"对端主机:选择会话阅读;要派发请打开它的远端会话节点。":"此节点没有可派发的路由。",j.appendChild(L)}function Oe(){Ae(),U(),xe(),Le()}function et(l){const A=t!==null&&In(t)===In(l);t=l,A||(s=!0),Oe(),E.classList.add("is-open")}function lt(){t=null,E.classList.remove("is-open")}function Mt(l){n=l;for(const L of(l==null?void 0:l.tasks)??[])m.add(L.taskId),g.set(L.taskId,L.direction==="inbound"?"inbound":"outbound");const A=t;if(A!==null){if(A.kind==="session"&&l!==null){const L=(l.sessions??[]).find(Z=>Z.id===A.id);L!==void 0&&(A.title=it(L),A.live=L.live)}Ae(),ze()}}return{root:E,open:et,close:lt,isOpen:()=>t!==null,update:Mt}}function Ho(e,t){const n=document.createElement("form");n.className="wb-cli-home";const s=document.createElement("button");s.type="button",s.textContent="指定 home",s.className="wb-member-submit";const o=document.createElement("select");o.className="wb-member-pick",o.setAttribute("aria-label","选择 CLI home 主机"),o.hidden=!0;const i=document.createElement("button");i.type="submit",i.textContent="确认 home",i.className="wb-member-submit",i.hidden=!0,i.disabled=!0;const r=document.createElement("div");r.className="wb-hint",r.setAttribute("role","status"),r.setAttribute("aria-live","polite"),r.textContent="home 未确定;点击指定 home 现读已链接主机名片。";let c=!1;return s.addEventListener("click",async()=>{var d;if(!c){c=!0,s.disabled=!0,i.disabled=!0,r.textContent="正在现读主机名片…";try{const m=await e();if(!m.ok)throw Error(m.error??"候选读取失败");if(m.held){s.hidden=!0,o.hidden=!0,i.hidden=!0,o.replaceChildren(),r.textContent="本机持有,无需指定";return}o.replaceChildren(new Option("请选择 home 主机…","",!0,!0));for(const u of m.homes??[])o.appendChild(new Option(u,u));o.hidden=!1,i.hidden=!1,s.textContent="刷新候选";const g=((d=m.homes)==null?void 0:d.length)??0;r.textContent=(m.unreadable?"有 "+m.unreadable+" 台对端名片读不到;":"")+(g>1?"多台已链接主机列出该句柄,请显式选择。":g===1?"找到 1 台已链接主机;仍需你显式确认。":"当前没有已链接且列出该句柄的可选主机。")}catch(m){r.textContent="读取失败:"+String(m),o.hidden=!0,i.hidden=!0}finally{c=!1,s.disabled=!1}}}),o.addEventListener("change",()=>{i.disabled=c||o.value===""}),n.addEventListener("submit",async d=>{if(d.preventDefault(),!(c||o.value==="")){c=!0,s.disabled=!0,o.disabled=!0,i.disabled=!0;try{r.textContent=await t(o.value)?"home 已指定:"+o.value:"指定失败:主机可能已离线或不再列出该句柄,请刷新后重选。"}catch(m){r.textContent="指定失败:"+String(m)}finally{c=!1,s.disabled=!1,o.disabled=!1,i.disabled=o.value===""}}}),n.append(s,o,i,r),n}const io="dsh-a2a.rail.tab";function jo(){try{return window.localStorage.getItem(io)}catch{return null}}function Bo(e){try{window.localStorage.setItem(io,e)}catch{}}function Yo(e,t={}){var ne;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,c=new Map,d=new Set;for(const S of e){const C=document.createElement("button");C.type="button",C.className="wb-tab",C.id=`wb-tab-${S.key}`,C.dataset.sec=S.key,C.setAttribute("role","tab"),C.setAttribute("aria-controls",`wb-panel-${S.key}`);const $=document.createElement("span");$.className="wb-tab-label",$.textContent=S.label;const k=document.createElement("span");k.className="wb-tab-badge",C.append($,k),C.addEventListener("click",()=>M(S.key)),s.appendChild(C);const V=document.createElement("section");V.className="wb-tabpanel",V.id=`wb-panel-${S.key}`,V.dataset.sec=S.key,V.setAttribute("role","tabpanel"),V.setAttribute("aria-labelledby",C.id),V.tabIndex=-1,o.appendChild(V),i.set(S.key,C),r.set(S.key,V),c.set(S.key,k)}const m=()=>e.map(S=>S.key).filter(S=>!d.has(S)),g=jo();let u=((ne=e.find(S=>S.key===g))==null?void 0:ne.key)??e[0].key;s.addEventListener("keydown",S=>{const C=m(),$=C.indexOf(u);let k;S.key==="ArrowRight"?k=C[($+1)%C.length]:S.key==="ArrowLeft"?k=C[($-1+C.length)%C.length]:S.key==="Home"?k=C[0]:S.key==="End"&&(k=C[C.length-1]),k!==void 0&&(S.preventDefault(),M(k,{focus:!0}))});function E(){for(const S of e){const C=S.key===u,$=i.get(S.key);$.setAttribute("aria-selected",String(C)),$.tabIndex=C?0:-1,$.classList.toggle("is-active",C),$.hidden=d.has(S.key),r.get(S.key).hidden=!C}}function M(S,C={}){var k;if(d.has(S))return;const $=S!==u;u=S,Bo(S),E(),C.focus===!0&&i.get(S).focus(),$&&((k=t.onChange)==null||k.call(t,S))}function J(S,C,$){const k=c.get(S);k.textContent=C,k.className=`wb-tab-badge${$!==void 0?` is-${$}`:""}`}function fe(S,C){C?d.add(S):d.delete(S),d.has(u)&&(u=m()[0]??e[0].key),E()}return E(),{root:n,panel:S=>r.get(S),select:M,selected:()=>u,setBadge:J,setHidden:fe}}const Wo=[{key:"all",label:"全部",hint:"不过滤:目录全部条目"},{key:"local",label:"本机",hint:"本机会话节点(现场 + 冷启动)"},{key:"canvas",label:"队",hint:"画布队(人类手工分配的组队)"},{key:"remote",label:"远端",hint:"远端会话队(来自对端卡片)"},{key:"logs",label:"日志",hint:"本机日志:不在网络目录里的会话档案"}];function nt(e,t){const n=document.createElement(e);return t!==void 0&&(n.className=t),n}function Yt(...e){const t=[];for(const n of e)n!==void 0&&(typeof n=="string"?t.push(n):t.push(...n));return t.join(" ").toLowerCase()}function Ko(e,t){const n=Math.max(0,Math.round((t-e)/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 Tn(e){return e>=1e6?`${(e/1e6).toFixed(1)} MB`:e>=1e3?`${Math.round(e/1e3)} KB`:`${e} B`}function Xo(e,t){const n=new Date(t);n.setHours(0,0,0,0);const s=n.getTime();return e>=s?"今天":e>=s-864e5?"昨天":"更早"}function Uo(e,t){var $,k,V;e.replaceChildren();const{state:n,search:s,filter:o}=t,i=s!==""||o!=="all",r=(y,f)=>(o==="all"||o===y)&&(s===""||f.includes(s)),c=(y,f,_)=>{const p=nt("div","wb-dir-group"),R=nt("div","wb-dir-head");return R.appendChild(nt("span","wb-dir-head-label")).textContent=`${y} · ${f}`,_!==void 0&&(R.appendChild(nt("span","wb-dir-head-note")).textContent=_),p.appendChild(R),e.appendChild(p),p},d=(y,f,_,p,R,j,K)=>{const we=nt("button","wb-item");we.type="button",we.appendChild(nt("span",`wb-dot ${f}`)).textContent=_;const Ae=nt("span","wb-item-text");return Ae.appendChild(nt("span","wb-item-label")).textContent=p,R!==""&&(Ae.appendChild(nt("span","wb-item-sub")).textContent=R),we.appendChild(Ae),K!==void 0&&(we.title=K),we.addEventListener("click",j),y.appendChild(we),we},m=(y,f)=>{if(f===void 0||f.length===0)return;const _=nt("span","wb-item-badge"),p=f.map(R=>R.slice(R.lastIndexOf("/")+1));_.textContent=`▤ ${p.slice(0,2).join(" ")}${p.length>2?` +${p.length-2}`:""}`,_.title=`画布队:${f.join(" · ")}`,y.appendChild(_)},g=(n.sessions??[]).filter(y=>r("local",Yt(it(y),y.team,y.label,y.id,y.canvasTeams))),u=g.filter(y=>y.live===!0),E=g.filter(y=>y.live!==!0);if(g.length>0){const y=c("本机会话",g.length,E.length>0?`${u.length} 在线 · ${E.length} 冷`:void 0);for(const f of[...u,...E]){const _=f.live===!0,p=f.nodePromptMissing===!0,R=d(y,_?"wb-dot-live":"wb-dot-cold",_?"●":"○",it(f),_?f.team:`冷 · ${f.team}`,()=>t.openChat({kind:"session",id:f.id,title:it(f),sub:f.team,team:f.team,live:f.live}),f.id);if(p){R.classList.add("is-node-prompt-missing");const j=nt("span","wb-node-warning");j.textContent="本会话的组装不含节点段",($=R.querySelector(".wb-item-text"))==null||$.appendChild(j)}m(R,f.canvasTeams)}}const M=(((k=n.canvas)==null?void 0:k.teams)??[]).filter(y=>r("canvas",Yt(y.name,y.team,y.members.map(f=>f.team??f.id))));if(M.length>0){const y=c("画布队",M.length);for(const f of M){const _=f.members.filter(p=>p.remote===!0).length;d(y,"wb-dot-canvas","▤",f.name,`${f.members.length} 成员${_>0?` · ${_} 远端`:""}`,()=>t.selectCanvas(f),f.team)}}const J=(n.remote??[]).filter(y=>r("remote",Yt(it(y),y.team,y.origin,y.workspace,y.canvasTeams)));if(J.length>0){const y=c("远端节点",J.length);for(const f of J){const _=d(y,"wb-dot-remote","◇",it(f),f.origin!==void 0&&f.origin!==""?f.origin:f.team,()=>t.openChat({kind:"remote",team:f.team,title:it(f),sub:f.team,row:f}),f.team);if(f.unreachable===!0){_.classList.add("is-unreachable");const p=nt("span","wb-unreachable-note");p.textContent="对端未应答(显示的是最后已知状态)",(V=_.querySelector(".wb-item-text"))==null||V.appendChild(p)}m(_,f.canvasTeams)}}const fe=new Set((n.sessions??[]).map(y=>y.id)),ne=t.logs.filter(y=>!fe.has(y.id)&&r("logs",Yt(y.id,t.titles.get(y.id))));if(ne.length>0){const y=t.logTotal!==void 0&&t.logTotal>t.logs.length,f=c("本机日志",ne.length,y?`显示 ${t.logs.length} / 共 ${t.logTotal}`:void 0);let _="";for(const p of[...ne].sort((R,j)=>j.mtimeMs-R.mtimeMs)){const R=Xo(p.mtimeMs,t.now);R!==_&&(_=R,f.appendChild(nt("div","wb-dir-day")).textContent=R);const j=t.titles.get(p.id),K=d(f,"wb-dot-log","❐",j??`会话 …${p.id.slice(-12)}`,`${Ko(p.mtimeMs,t.now)} · ${Tn(p.sizeBytes)}`,()=>t.openChat({kind:"log",id:p.id,title:j??`…${p.id.slice(-12)}`,sub:"本机日志"}),`${p.id}
|
|
3
|
-
${new Date(p.mtimeMs).toLocaleString()} · ${Tn(p.sizeBytes)}`);j===void 0&&K.classList.add("is-untitled")}}g.length+M.length+J.length+ne.length===0&&(e.appendChild(nt("div","wb-dir-empty")).textContent=i?"无匹配条目":"目录为空");const S=n.sessions??[];return`${S.filter(y=>y.live===!0).length}/${S.length}`}const ro="dsh-a2a.logtitles",qo=300,_n=60;function zo(){try{const e=window.localStorage.getItem(ro),t=e===null?null:JSON.parse(e);if(t!==null&&typeof t=="object")return new Map(Object.entries(t).filter(n=>typeof n[1]=="string"))}catch{}return new Map}function Jo(e,t,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>_n?`${o.slice(0,_n-1)}…`:o;if(e.get(t)===i)return!1;for(e.delete(t),e.set(t,i);e.size>qo;)e.delete(e.keys().next().value);try{window.localStorage.setItem(ro,JSON.stringify(Object.fromEntries(e)))}catch{}return!0}function ut(e){return e.name??e.team??e.label??""}function It(e,t){const n=Math.max(0,Math.round((t-e)/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 T(e,t){const n=document.createElement(e);return t!==void 0&&(n.className=t),n}function On(e,t,n){const s=T("div","wb-kv");s.appendChild(T("span","wb-kv-k")).textContent=t,s.appendChild(T("span","wb-kv-v")).textContent=n,e.appendChild(s)}function Vo(e){try{return new URL(e).host}catch{return e}}const Go=[{key:"directory",label:"目录"},{key:"hosts",label:"主机"},{key:"ledger",label:"台账"},{key:"activity",label:"活动"},{key:"plan",label:"规划"}];function Qo(e){const t=e.board;let n="data",s,o=null,i="",r="all",c=null;const d=new Map;let m=null,g=[],u;const E=zo();let M=!1;const J=T("div","wb");J.setAttribute("data-testid","wb-root");const fe=T("header","wb-header"),ne=T("button","wb-icon-btn wb-menu");ne.type="button",ne.dataset.testid="wb-menu",ne.setAttribute("aria-label","打开目录抽屉"),ne.textContent="☰",ne.addEventListener("click",()=>J.classList.toggle("is-rail-open")),fe.appendChild(ne);const S=T("div","wb-title");S.appendChild(T("span","wb-title-main")).textContent="A2A 工作台";const C=T("span","wb-badge");S.appendChild(C),fe.appendChild(S);const $=T("button","wb-icon-btn wb-owner-btn");$.type="button",$.dataset.testid="wb-owner-btn",$.setAttribute("aria-label","主人设置(三键面板)"),$.title="主人设置:入网白名单 / 可见性 / 发布",$.textContent="⚙",$.addEventListener("click",()=>{l=!l,L()}),fe.appendChild($);const k=T("div","wb-header-stats");fe.appendChild(k);const V=T("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",()=>{J.classList.toggle("is-rail-collapsed"),n==="canvas"&&t!==void 0&&t.activate()}),fe.appendChild(V);const y=T("div","wb-body"),f=Yo(Go),_=f.root,p=T("div","wb-directory"),R=T("div","wb-dir-tools"),j=document.createElement("input");j.className="wb-search",j.type="search",j.placeholder="搜索:名称 / 队 / 会话 / 节点",j.setAttribute("aria-label","统一搜索目录"),j.addEventListener("input",()=>{i=j.value.trim().toLowerCase(),Ke()}),R.appendChild(j);const K=T("div","wb-filters");for(const x of Wo){const w=T("button","wb-filter");w.type="button",w.textContent=x.label,w.dataset.filter=x.key,w.title=x.hint,w.addEventListener("click",()=>{r=x.key,Ke()}),K.appendChild(w)}R.appendChild(K),f.panel("directory").appendChild(R),f.panel("directory").appendChild(p);const we=T("section","wb-pane"),Ae=T("section","wb-pane"),P=T("section","wb-pane"),U=T("section","wb-pane"),ie=[["ledger",we],["activity",Ae],["plan",P],["hosts",U]],Re=T("main","wb-stage"),$e=T("section","wb-stage-board");t!==void 0&&($e.appendChild(t.root),Re.appendChild($e));const re=T("div","wb-data"),Ce=T("aside","wb-inspector"),Q=T("div","wb-inspector-head");Q.appendChild(T("span","wb-inspector-title")).textContent="详情";const oe=T("button","wb-icon-btn");oe.type="button",oe.setAttribute("aria-label","关闭详情"),oe.textContent="✕",oe.addEventListener("click",()=>qe(void 0)),Q.appendChild(oe),Ce.appendChild(Q);const xe=T("div","wb-inspector-body");Ce.appendChild(xe);const le=Do({now:e.now,sessionLog:e.sessionLog,remoteSessionLog:e.remoteSessionLog,dispatchQuick:e.dispatchQuick,onTranscript:(x,w)=>{x.kind!=="log"&&x.kind!=="session"||Jo(E,x.id,w)&&Ke()}});Re.appendChild(re),y.appendChild(_),y.appendChild(Re),y.appendChild(Ce),y.appendChild(le.root),J.appendChild(fe),J.appendChild(y);function te(x){for(const[w,D]of ie){const N=x==="canvas"?f.panel(w):re;f.setHidden(w,x!=="canvas"),D.parentElement!==N&&N.appendChild(D)}}function Ne(){const w=t!==void 0&&t.available()?"canvas":"data";J.dataset.mode=w,$e.classList.toggle("is-hidden",w!=="canvas"),re.classList.toggle("is-hidden",w==="canvas"),te(w),w!==n&&(t!==void 0&&(w==="canvas"?t.activate():t.deactivate()),n=w)}function je(x){for(;x.firstChild!==null;)x.removeChild(x.firstChild);return x}function qe(x){s=x,((x==null?void 0:x.kind)!=="canvas"||(c==null?void 0:c.name)!==x.row.name)&&(c=null),(x==null?void 0:x.kind)!=="canvas"&&(m=null),B(),J.classList.remove("is-rail-open")}function Ke(){for(let w=0;w<K.children.length;w++){const D=K.children[w];D.classList.toggle("is-active",D.dataset.filter===r)}if(o===null){p.replaceChildren(T("div","wb-muted")),p.firstElementChild.textContent="载入中…",f.setBadge("directory","");return}const x=Uo(p,{state:o,logs:g,logTotal:u,titles:E,search:i,filter:r,now:e.now(),openChat:pe,selectCanvas:w=>qe({kind:"canvas",row:w})});f.setBadge("directory",x)}function ct(){const x=je(U);if(o===null){f.setBadge("hosts","");return}const w=e.now(),D=[...o.peers??[]].sort((N,I)=>{const H=X=>X.link==="linked"?0:1;return H(N)-H(I)||(I.score??0)-(N.score??0)});if(f.setBadge("hosts",D.length>0?`${D.filter(N=>N.link==="linked").length}/${D.length}`:""),D.length===0){x.appendChild(T("div","wb-nodelist-empty")).textContent="暂无 tracked peer——配 peers 种子或等 referral 到达";return}for(const N of D){const I=Vo(N.url),H=T("div","wb-host-row"),X=T("span","wb-host-lamp"),se=N.lastContactAt,ee=se===void 0?void 0:w-se,ve=N.lastContactOk;ee===void 0?X.classList.add("is-unknown"):ve===!1&&ee<=5*6e4?X.classList.add("is-fail"):ee<=6e4?X.classList.add("is-live"):ee<=5*6e4?X.classList.add("is-warm"):X.classList.add("is-cold"),X.title=se===void 0?"尚无接触记录":`最近接触 ${It(se,w)}${ve===!1?"(失败)":ve===!0?"(成功)":""}`,H.appendChild(X),H.appendChild(T("span","wb-host-name")).textContent=N.name!==void 0&&N.name!==""?N.name:I;const De=T("span",`wb-host-badge ${N.link==="linked"?"is-linked":"is-stranger"}`);De.textContent=`${N.link==="linked"?"linked":"stranger"} ${N.verified===!0?"✓":"✗"}`,De.title=N.link==="linked"?`已建立运营者链接(互种或 canvas 引用);${N.verified===!0?"验签有效":"尚未持有验签通过的卡片"}`:"无运营者关系(验签 ≠ 关系)",H.appendChild(De),N.version!==void 0&&N.version!==""&&(H.appendChild(T("span","wb-host-ver")).textContent=N.version),H.appendChild(T("span","wb-host-url mono")).textContent=I,H.setAttribute("role","button"),H.tabIndex=0,H.title=`${N.url} · score ${String(N.score??0)}`;const q=()=>{pe({kind:"peer",id:`peer-${I}`,title:N.name!==void 0&&N.name!==""?N.name:I,sub:I,url:N.url})};H.addEventListener("click",q),H.addEventListener("keydown",He=>{(He.key==="Enter"||He.key===" ")&&(He.preventDefault(),q())}),x.appendChild(H)}}function xt(){if(o===null){we.replaceChildren(),f.setBadge("ledger","");return}const x=o,w=N=>{const I=(x.sessions??[]).find(X=>X.team===N);if(I!==void 0)return{kind:"session",id:I.id,title:ut(I),sub:I.team,team:I.team,live:I.live};const H=(x.remote??[]).find(X=>X.team===N);if(H!==void 0)return{kind:"remote",team:H.team,title:ut(H),sub:H.team,row:H}},D=Fo(we,{state:x,now:e.now(),abandon:(N,I)=>e.abandon(N,I),canOpenTeam:N=>w(N)!==void 0,openTeam:N=>{const I=w(N);return I===void 0?!1:(pe(I),!0)}});f.setBadge("ledger",D.badge,D.tone)}function ze(x,w,D){qt(x.appendChild(T("span","wb-row-team")),w,D)}function Ve(){var X;const x=je(Ae);if(o===null)return;const w=e.now(),D=o.inFlight??[];f.setBadge("activity",D.length>0?String(D.length):"",D.length>0?"accent":void 0);const N=T("div","wb-pane-head");if(N.textContent=`在途 ${D.length} · 活动 ${((X=o.activity)==null?void 0:X.length)??0}`,x.appendChild(N),D.length>0){const se=T("div","wb-pane-subhead");se.textContent="在途路由",x.appendChild(se);for(const ee of D){const ve=T("div","wb-row");ve.appendChild(T("span","wb-row-dir")).textContent="→",ze(ve,o,ee.team),ve.appendChild(T("span","wb-row-meta")).textContent=`${ee.peer} · ${It(ee.startedAt,w)}`,x.appendChild(ve)}}const I=T("div","wb-pane-subhead");I.textContent="活动环(最新在前)",x.appendChild(I);const H=o.activity??[];if(H.length===0){x.appendChild(T("div","wb-muted")).textContent="暂无活动";return}for(const se of H){const ee=T("div","wb-row"),ve=T("span","wb-row-dir");ve.textContent=se.dir==="fwd"?"⇢":se.dir==="out"?"→":"←",se.ok!==!0&&ve.classList.add("is-fail"),ee.appendChild(ve),ze(ee,o,se.team),ee.appendChild(T("span","wb-row-meta")).textContent=`${se.peer} · ${It(se.ts,w)}`,ee.appendChild(T("span","wb-row-badges")).textContent=se.ok===!0?"":"失败",x.appendChild(ee)}}function bt(x){var X,se;const w=e.now(),D=[],N=pn(x,w);N.deadLetters.length>0&&D.push({severity:"high",text:`清账 ${N.deadLetters.length} 条死信(目标早已离开或死信化,无回执可期)`});for(const ee of N.stale){const ve=ee.brief===void 0||ee.brief===""?"":`「${ee.brief}」`;D.push({severity:"normal",text:`催办 ${ee.taskId} → ${To(x,ee.team)}(等待 ${It(ee.startedAt,w)} 无回执)${ve}`,brief:`a2a_route 催收回执:task ${ee.taskId}(team ${ee.team})${ve===""?"":`原任务「${ee.brief}」`}已派发 ${It(ee.startedAt,w)},请回报结果或回执。`})}const I=(x.sessions??[]).filter(ee=>ee.live!==!0).map(ee=>ut(ee));if(I.length>0){const ee=I.slice(0,3).join("、")+(I.length>3?` 等 ${I.length} 个`:"");D.push({severity:"normal",text:`冷会话 ${I.length} 个(${ee}):在 GUI 打开即可唤醒加入面`})}for(const ee of((X=x.reconcile)==null?void 0:X.rows)??[])if(ee.needsRepair===!0){const ve=(x.sessions??[]).find(q=>q.id===ee.id),De=ve!==void 0?`${ut(ve)}(${ee.id})`:ee.id;D.push({severity:"high",text:`reconcile 需修复:${De} ${ee.error}`})}const H=((se=x.idempotency)==null?void 0:se.conflicts)??0;return H>0&&D.push({severity:"high",text:`幂等冲突 ${H} 例:人工核查 UNIQUE-ization 流量`}),D}function Nt(){const x=je(P);if(o===null)return;const w=bt(o);f.setBadge("plan",w.length>0?String(w.length):"",w.some(I=>I.severity==="high")?"danger":void 0);const D=T("div","wb-pane-head");D.textContent=w.length===0?"网络健康——无待办行动":`待办行动 ${w.length}`,x.appendChild(D);for(const I of w){const H=T("div",`wb-action${I.severity==="high"?" wb-action-high":""}`);if(H.appendChild(T("span","wb-action-text")).textContent=I.text,I.brief!==void 0){const X=T("button","wb-btn");X.type="button",X.textContent="复制催办",X.addEventListener("click",()=>e.copy(I.brief??"")),H.appendChild(X)}x.appendChild(H)}const N=T("div","wb-pane-subhead");N.textContent="派单起草(复制后在任一会话粘贴执行)",x.appendChild(N),x.appendChild(Le)}const Le=T("div","wb-draft"),Oe=document.createElement("select");Oe.className="wb-select";const et=document.createElement("textarea");et.className="wb-textarea",et.rows=3,et.placeholder="任务正文:目标、验收、期限…";const lt=T("button","wb-btn wb-btn-primary");lt.type="button",lt.textContent="复制任务书",lt.addEventListener("click",()=>{const x=Oe.value,w=et.value.trim();x===""||w===""||e.copy(`a2a_route 派单 → ${x}:
|
|
5
|
-
${w}`)}),Le.appendChild(Oe),Le.appendChild(et),Le.appendChild(lt);function Mt(){var I;const x=Oe.value;je(Oe);const w=document.createElement("option");if(w.value="",w.textContent="选择目标队…",Oe.appendChild(w),o===null)return;const D=o,N=new Map;for(const H of D.sessions??[])H.team!==void 0&&H.team!==""&&N.set(H.team,`${ut(H)}(会话队)`);for(const H of((I=D.canvas)==null?void 0:I.teams)??[])N.set(H.team,`${H.name}(canvas 队)`);for(const H of D.remote??[])N.set(H.team,`${ut(H)}(远端)`);for(const[H,X]of N){const se=document.createElement("option");se.value=H,se.textContent=`${X} · ${H}`,Oe.appendChild(se)}x!==""&&N.has(x)&&(Oe.value=x)}let l=!1,A=null;function L(){var x;B(),l&&((x=e.ownerSettingsRead)==null||x.call(e).then(w=>{if(l){if(w.ok!==!0){A=null,B();return}A={teamJoinAllowlist:w.teamJoinAllowlist??[],teamScopeInfo:w.teamScopeInfo!==!1,announce:w.announce===!0,announceRestartPending:w.announceRestartPending===!0},B()}}))}function Z(x){const w=T("div","wb-card"),D=T("div","wb-inspector-head");D.appendChild(T("span","wb-inspector-title")).textContent="主人设置";const N=T("button","wb-icon-btn");if(N.type="button",N.setAttribute("aria-label","关闭主人设置"),N.textContent="✕",N.addEventListener("click",()=>{l=!1,B()}),D.appendChild(N),w.appendChild(D),e.ownerSettingsRead===void 0){const be=T("div","wb-hint");be.textContent="此宿主未提供主人设置面(旧版本)——升级后可用。",w.appendChild(be),x.appendChild(w);return}if(A===null){const be=T("div","wb-hint");be.textContent="读取中…",w.appendChild(be),x.appendChild(w);return}const I=A,H=T("div","wb-side-head");H.textContent="入网白名单(精确团队名)",w.appendChild(H);for(const be of I.teamJoinAllowlist){const Xe=T("div","wb-member-row");Xe.appendChild(T("span","wb-member-label")).textContent=be;const ft=T("button","wb-member-remove");ft.type="button",ft.textContent="移除",ft.addEventListener("click",()=>{var St;(St=e.ownerSettingsWrite)==null||St.call(e,{teamJoinAllowlist:I.teamJoinAllowlist.filter(Dt=>Dt!==be)}).then(()=>L())}),Xe.appendChild(ft),w.appendChild(Xe)}const X=T("div","wb-member-add"),se=T("input","wb-member-manual");se.type="text",se.placeholder="dsh/团队名(精确,无通配)",se.setAttribute("aria-label","新增白名单团队名");const ee=T("button","wb-member-submit");ee.type="button",ee.textContent="加入";const ve=()=>{var Xe;const be=se.value.trim();be===""||I.teamJoinAllowlist.includes(be)||(Xe=e.ownerSettingsWrite)==null||Xe.call(e,{teamJoinAllowlist:[...I.teamJoinAllowlist,be]}).then(()=>L())};ee.addEventListener("click",ve),se.addEventListener("keydown",be=>{be.key==="Enter"&&ve()}),X.append(se,ee),w.appendChild(X);const De=T("div","wb-side-head");De.textContent="目录可见性(teamScopeInfo)",w.appendChild(De);const q=T("div","wb-member-row"),He=T("button","wb-member-submit");He.type="button",He.textContent=I.teamScopeInfo?"已开:仅显示已加入团队(点击放开为全舰队可见)":"已关:全舰队可见(点击收窄为已加入团队)",He.addEventListener("click",()=>{var be;(be=e.ownerSettingsWrite)==null||be.call(e,{teamScopeInfo:!I.teamScopeInfo}).then(()=>L())}),q.appendChild(He),w.appendChild(q);const Ge=T("div","wb-hint");Ge.textContent="精度说明:teamScopeInfo 只管「目录显示范围」。关上它不会解锁任何通信准入——会话入网(S3)与目标级路由(F5)规则原样生效。",w.appendChild(Ge);const Ze=T("div","wb-side-head");Ze.textContent="节点发布(announce)",w.appendChild(Ze);const dt=T("div","wb-member-row"),Je=T("button","wb-member-submit");if(Je.type="button",Je.textContent=I.announce?"已开:本节点发布签名卡(点击关闭)":"已关:本节点不发布(点击开启——重启宿主后生效)",Je.addEventListener("click",()=>{var be;(be=e.ownerSettingsWrite)==null||be.call(e,{announce:!I.announce}).then(()=>L())}),dt.appendChild(Je),w.appendChild(dt),I.announceRestartPending){const be=T("div","wb-hint");be.textContent="有 announce 变更待生效:重启宿主后按新配置发布。",w.appendChild(be)}x.appendChild(w)}function B(){var N;const x=je(xe);if(l){Ce.classList.add("is-open"),Z(x);return}if(Ce.classList.toggle("is-open",s!==void 0),s===void 0)return;const w=s,D=T("div","wb-card");if(w.kind==="canvas"){const I=(((N=o==null?void 0:o.canvas)==null?void 0:N.teams)??[]).find(q=>q.name===w.row.name)??w.row;On(D,"Canvas 队",I.name),On(D,"路由队",I.team);const H=T("div","wb-side-head");if(H.textContent=`成员 · ${I.members.length}`,D.appendChild(H),I.members.length===0){const q=T("div","wb-muted");q.textContent="空队——用下方表单添加成员",D.appendChild(q)}for(const q of I.members){const He=T("div","wb-member-row"),Ge=q.cliHeld===!0?"本机持有,无需指定":q.remote===!0?q.cliHome===null?"◇ 远端 · home 未确定":"◇ 远端":q.live===!0?"● 现场":q.joined===!0?"○ 冷启":"· 未入网";He.appendChild(T("span","wb-member-dot")).textContent=Ge;const Ze=T("span","wb-member-label"),dt=((o==null?void 0:o.sessions)??[]).find(be=>be.id===q.id);Ze.textContent=q.remote===!0?q.id:dt!==void 0?ut(dt):q.id,Ze.title=q.cliHeld===!0?"本机持有,无需指定":q.cliHome!==void 0?q.cliHome??"home 未确定":q.team??q.id,He.appendChild(Ze);const Je=T("button","wb-member-remove");if(Je.type="button",Je.textContent="移除",Je.addEventListener("click",async()=>{Je.disabled=!0,await e.canvasOp("remove-member",I.name,q.id)||(Je.disabled=!1)}),He.appendChild(Je),D.appendChild(He),q.cliHomeCleared===!0){const be=T("div","wb-hint");be.textContent="本机落户已清除旧 home 钉;户口离线后也不会恢复旧钉。",D.appendChild(be)}if(q.cliHome===null&&q.cliHeld!==!0&&e.cliHomeOptions!==void 0){const be=JSON.stringify([I.name,q.id]);let Xe=d.get(be);Xe===void 0&&(Xe=Ho(()=>e.cliHomeOptions(I.name,q.id),ft=>e.canvasOp("add-member",I.name,q.id,ft)),d.set(be,Xe)),D.appendChild(Xe)}}if((c==null?void 0:c.name)!==I.name){const q=T("form","wb-member-add"),He=document.createElement("select");He.className="wb-member-pick",He.setAttribute("aria-label","选择成员");const Ge=document.createElement("input");Ge.type="text",Ge.className="wb-member-manual",Ge.placeholder="或输入远端句柄 zone/id8",Ge.setAttribute("aria-label","远端成员句柄");const Ze=T("button","wb-member-submit");Ze.type="submit",Ze.textContent="添加",q.appendChild(He),q.appendChild(Ge),q.appendChild(Ze),q.addEventListener("submit",async dt=>{dt.preventDefault();const Je=Ge.value.trim(),be=Je!==""?Je:He.value;if(be==="")return;Ze.disabled=!0;const Xe=await e.canvasOp("add-member",I.name,be);Ze.disabled=!1,Xe&&(Ge.value="")}),c={name:I.name,form:q,pick:He,manual:Ge}}const X=c.pick,se=X.value;je(X),X.appendChild(new Option("本机会话(现场/冷启动)…","",!0,!0));const ee=new Set(I.members.map(q=>q.id));for(const q of(o==null?void 0:o.sessions)??[])ee.has(q.id)||X.appendChild(new Option(`${ut(q)} — 本机`,q.id));let ve=!1;for(const q of(o==null?void 0:o.remote)??[])q.team.includes("/")&&(ee.has(q.team)||(ve||(X.appendChild(new Option("远端会话队(目录卡片)…","",!0,!1)),ve=!0),X.appendChild(new Option(`${ut(q)} — 远端`,q.team))));ve||X.appendChild(new Option("(暂无可拉入的远端会话队——见下方说明)","",!0,!1)),se!==""&&Array.from(X.options).some(q=>q.value===se)&&(X.value=se),D.appendChild(c.form);const De=T("div","wb-hint");De.textContent="成员由人类在此手工分配(agent 不可自组队)。远端成员走对端目录路由,不做本机冷唤醒;地址由目录在派发时重解析。远端下拉只列 zone/id8 会话句柄——若为空,说明目录里还没有已链接对端的会话队(未链接的对端只给最小卡);此时可在输入框手输句柄(如 dsh/xxxxxxxx)先把人拉进来,句柄本身即链接手势。",D.appendChild(De),e.dispatchQuick!==void 0&&D.appendChild(ge(I.team))}x.appendChild(D)}function he(x){const w=T("form","wb-dispatch-form"),D=document.createElement("textarea");D.className="wb-dispatch-text",D.placeholder="一句话任务…(≤4000 字符,异步送达,回执进台账)",D.setAttribute("aria-label","快派消息");const N=T("button","wb-dispatch-submit");N.type="submit",N.textContent="发送";const I=T("div","wb-dispatch-note");return w.appendChild(D),w.appendChild(N),w.appendChild(I),D.addEventListener("keydown",H=>{H.key!=="Enter"||H.shiftKey||H.ctrlKey||H.altKey||H.metaKey||H.isComposing||(H.preventDefault(),N.disabled||w.requestSubmit())}),w.addEventListener("submit",async H=>{var ee;H.preventDefault();const X=D.value.trim();if(X===""||N.disabled)return;N.disabled=!0,I.textContent="派发中…";let se;try{se=await(((ee=e.dispatchQuick)==null?void 0:ee.call(e,x,X))??Promise.resolve({ok:!1,error:"dispatch unavailable"}))}catch(ve){se={ok:!1,error:ve instanceof Error?ve.message:String(ve)}}N.disabled=!1,se.ok===!0&&(D.value=""),D.focus({preventScroll:!0}),I.textContent=se.ok===!0?`已派发${se.task_id!==void 0?` · ${se.task_id}`:""} · 回执将入台账(待回执)`:`失败:${se.error??"未知原因"}`}),{form:w,text:D,note:I}}function ge(x){const w=T("div","wb-dispatch"),D=T("div","wb-side-head");return D.textContent="快派",w.appendChild(D),(m==null?void 0:m.team)!==x&&(m={team:x,...he(x)}),w.appendChild(m.form),w}function pe(x){le.open(x),J.classList.remove("is-rail-open")}function ae(x){if(o===null)return;const w=(o.sessions??[]).find(N=>N.id===x);if(w!==void 0){pe({kind:"session",id:x,title:ut(w),sub:w.team,team:w.team,live:w.live});return}if(x.startsWith("peer-")){const N=x.slice(5),I=(o.peers??[]).find(H=>H.url.includes(N));pe({kind:"peer",id:x,title:I!==void 0?I.url:N,sub:N,url:I==null?void 0:I.url});return}g.find(N=>N.id===x)!==void 0&&pe({kind:"log",id:x,title:`…${x.slice(-12)}`,sub:"档案"})}function Be(){var ee,ve;C.textContent=(o==null?void 0:o.version)!==void 0?`v${o.version}`:"",C.hidden=(o==null?void 0:o.version)===void 0;const x=je(k);if(o===null)return;const w=[],D=pn(o,e.now()),N=D.deadLetters.length;N>0&&w.push({text:`死信 ${N}`,tone:"danger",title:"超过 24h TTL 仍未结算的任务(unconsumed),需在台账清账",tab:"ledger",group:"死信"});const I=D.stale.length;I>0&&w.push({text:`陈旧 ${I}`,tone:"warn",title:"我方派发、要回执、已等待 ≥1h 仍未回执(可催办;免回执行不算)",tab:"ledger",group:"陈旧"});const H=D.owedOverdue.length;H>0&&w.push({text:`欠回执 ${H}`,tone:"warn",title:"对方投递给本机、已等待本机回执超过 1 小时",tab:"ledger",group:"待本机回执"});const X=((ee=o.idempotency)==null?void 0:ee.conflicts)??0;X>0&&w.push({text:`幂等冲突 ${X}`,tone:"danger",title:"同一幂等键对应了不同载荷,需人工核查",tab:"ledger",group:"取证"});const se=(((ve=o.reconcile)==null?void 0:ve.rows)??[]).filter(De=>De.needsRepair===!0).length;if(se>0&&w.push({text:`需修复 ${se}`,tone:"danger",title:"reconcile 无法自动恢复的会话,见行动计划",tab:"plan"}),w.length===0){x.appendChild(T("span","wb-header-ok")).textContent="● 无异常";return}for(const De of w){const q=T("button",`wb-alert wb-alert-${De.tone}`);q.type="button",q.textContent=De.text,q.title=`${De.title}(点击查看)`,q.addEventListener("click",()=>Te(De.tab,De.group)),x.appendChild(q)}}function Te(x,w){var I;const D=ie.find(([H])=>H===x)[1];n==="canvas"&&(J.classList.add("is-rail-open"),f.select(x,{focus:!1}));const N=w===void 0?D:w==="取证"?D.querySelector("details.wb-led-forensics"):Array.from(D.querySelectorAll(".wb-led-group")).find(H=>H.dataset.group===w)??null;N!==null&&(N instanceof HTMLDetailsElement&&(N.open=!0),(I=N.scrollIntoView)==null||I.call(N,{block:"start",behavior:"smooth"}))}function Ye(x){var D;const w=new Set((((D=x==null?void 0:x.canvas)==null?void 0:D.teams)??[]).flatMap(N=>N.members.filter(I=>I.cliHome===null&&I.cliHeld!==!0).map(I=>JSON.stringify([N.name,I.id]))));for(const N of d.keys())w.has(N)||d.delete(N);o=x,e.sessionLogList!==void 0&&!M&&(M=!0,e.sessionLogList().then(N=>{g=N.ok&&N.sessions!==void 0?N.sessions:[],u=N.ok?N.count:void 0}).catch(()=>{}).finally(()=>{M=!1,Ke()})),Be(),Ke(),Mt(),ct(),xt(),le.update(x),Ve(),Nt(),B(),Ne()}function Rt(x){if(x==="board"){Ne();return}f.select(x)}return Ye(null),{root:J,update:Ye,mode:()=>n,selectTab:Rt,openNodeChat:ae}}const pt=1e6,wn=.25,xn=3,ao=256,co=96;function $t(e){const t=typeof e=="number"?e:Number.NaN;if(Number.isFinite(t))return Math.max(-pt,Math.min(pt,Math.round(t)))}function lo(e){if(e===null||typeof e!="object")return;const t=e,n=$t(t.x),s=$t(t.y);return n===void 0||s===void 0?void 0:{x:n,y:s}}function Zo(e){const t=lo(e);if(t===void 0)return;const n=e,s=$t(n.w),o=$t(n.h);if(!(s===void 0||o===void 0||s<=0||o<=0))return{...t,w:Math.min(s,pt),h:Math.min(o,pt)}}const uo=e=>e!==""&&!e.includes("/")&&(e.startsWith("roster:")?e.length>7&&e.length<=47:e.length<=40);function mo(e){if(e===null||typeof e!="object")return;const t=e;if(t.version!==1)return;const n=t.viewport;if(n===null||typeof n!="object")return;const s=n,o=$t(s.x),i=$t(s.y),r=s.scale,c=typeof r=="number"?r:Number.NaN;if(o===void 0||i===void 0||!Number.isFinite(c))return;const d=Math.max(wn,Math.min(xn,c)),m={};if(t.nodes!==null&&typeof t.nodes=="object")for(const[u,E]of Object.entries(t.nodes)){if(typeof u!="string"||u===""||u.length>128)continue;const M=lo(E);if(M!==void 0&&(m[u]=M),Object.keys(m).length>=ao)break}const g={};if(t.frames!==null&&typeof t.frames=="object")for(const[u,E]of Object.entries(t.frames)){if(!uo(u))continue;const M=Zo(E);if(M!==void 0&&(g[u]=M),Object.keys(g).length>=co)break}return{version:1,viewport:{x:o,y:i,scale:d},nodes:m,frames:g}}function es(e,t,n){const s=r=>Math.max(-pt,Math.min(pt,Math.round(r))),o={};for(const[r,c]of t)if(!(typeof r!="string"||r===""||r.length>128)&&(o[r]={x:s(c.x),y:s(c.y)},Object.keys(o).length>=ao))break;const i={};for(const[r,c]of n){if(!uo(r))continue;const d=s(c.w),m=s(c.h);if(!(d<=0||m<=0)&&(i[r]={x:s(c.x),y:s(c.y),w:Math.min(d,pt),h:Math.min(m,pt)},Object.keys(i).length>=co))break}return{version:1,viewport:{x:s(e.x),y:s(e.y),scale:Math.max(wn,Math.min(xn,e.scale))},nodes:o,frames:i}}function fo(e){let t=2166136261;for(let n=0;n<e.length;n++)t^=e.charCodeAt(n),t=Math.imul(t,16777619)>>>0;return t>>>0}const We=172,Pe=56,yt=[150,290,430],st=16;function ts(e){const t=fo(e),n=Math.floor(t/st)%yt.length,o=t%st/st*Math.PI*2+n*(Math.PI/st),i=yt[n];return{x:Math.round(Math.cos(o)*i),y:Math.round(Math.sin(o)*i*.6)}}function po(e){const t=new Map;for(const n of e)for(const s of n.members)t.has(s.id)||t.set(s.id,n.name);return t}const Fn=64,Pn=24,Rn=20,ns=4,Dn=24,Hn=44,os=24;function ss(e,t,n=Number.POSITIVE_INFINITY){const s=new Set(t),o=po(e),i=e.map(u=>[...new Set(u.members.map(E=>E.id))].filter(E=>s.has(E)&&o.get(E)===u.name));i.push(t.filter(u=>!o.has(u)));const r=new Map;let c=0,d=0,m=0,g=0;for(const u of i){if(u.length===0)continue;const E=Math.min(3,Math.max(u.length>1?2:1,Math.ceil(Math.sqrt(u.length)))),M=Math.ceil(u.length/E),J=Math.max(260,E*We+(E-1)*Pn+Dn*2),fe=Math.max(160,M*Pe+(M-1)*Rn+Hn+os);g>0&&(g%ns===0||c+J>n)&&(c=0,d+=m+Fn,m=0),u.forEach((ne,S)=>{const C=S%E,$=Math.floor(S/E);r.set(ne,{x:c+Dn+We/2+C*(We+Pn),y:d+Hn+Pe/2+$*(Pe+Rn)})}),c+=J+Fn,m=Math.max(m,fe),g+=1}return r}const Wt=12;function ho(e,t){const n=d=>t.every(m=>Math.abs(m.x-d.x)>=We+Wt||Math.abs(m.y-d.y)>=Pe+Wt),s=ts(e);if(n(s))return s;const o=fo(e),i=st*yt.length,r=Math.floor(o/st)%yt.length*st+o%st;for(let d=1;d<i;d++){const m=(r+d)%i,g=Math.floor(m/st),u=m%st/st*Math.PI*2+g*(Math.PI/st),E=yt[g],M={x:Math.round(Math.cos(u)*E),y:Math.round(Math.sin(u)*E*.6)};if(n(M))return M}const c=yt[yt.length-1];for(let d=0;;d++)for(let m=0;m<6;m++){const g={x:Math.round(-c+m*(We+Wt)),y:Math.round(c*.6+Pe*2+d*(Pe+Wt))};if(n(g))return g}}function at(e){return{x:e.x-We/2,y:e.y-Pe/2,w:We,h:Pe}}function Cn(e){if(e.length===0)return{x:0,y:0,w:260,h:160};let t=Number.POSITIVE_INFINITY,n=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY,o=Number.NEGATIVE_INFINITY;for(const g of e)t=Math.min(t,g.x),n=Math.min(n,g.y),s=Math.max(s,g.x+g.w),o=Math.max(o,g.y+g.h);const i=24,r=44,c=24,d=Math.max(260,Math.round(s-t+i*2)),m=Math.max(160,Math.round(o-n+r+c));return{x:Math.round(t-i),y:Math.round(n-r),w:d,h:m}}class kn{constructor(){Ct(this,"revisionCounter",0);Ct(this,"nodes",new Map);Ct(this,"frames",new Map);Ct(this,"selection",new Set);Ct(this,"viewport",{x:0,y:0,scale:1})}get revision(){return this.revisionCounter}getNode(t){return this.nodes.get(t)}allNodes(){return[...this.nodes.values()]}nodeIds(){return[...this.nodes.keys()]}getFrame(t){return this.frames.get(t)}allFrames(){return[...this.frames.entries()]}isSelected(t){return this.selection.has(t)}selectedIds(){return[...this.selection]}bump(){this.revisionCounter+=1}dragNodes(t,n,s){let o=!1;for(const i of t){const r=this.nodes.get(i);r!==void 0&&(r.x+=n,r.y+=s,o=!0)}o&&this.bump()}beginFrameDrag(t){const n=this.frames.get(t);if(n!==void 0)return{name:t,rect:{...n}}}applyFrameDrag(t,n,s){const o=this.frames.get(t.name);o!==void 0&&(o.x=t.rect.x+n,o.y=t.rect.y+s,this.bump())}nudge(t,n,s){this.dragNodes(t,n,s)}marqueeSelect(t,n){n||this.selection.clear();for(const s of this.nodes.values()){const o=at(s);o.x<t.x+t.w&&o.x+o.w>t.x&&o.y<t.y+t.h&&o.y+o.h>t.y&&this.selection.add(s.id)}this.bump()}setSelection(t){this.selection=new Set(t),this.bump()}upsertNode(t){const n=this.nodes.get(t.id);if(n===void 0){this.nodes.set(t.id,t),this.bump();return}n.label=t.label,n.name=t.name,n.description=t.description,n.live=t.live,n.memberships=t.memberships,this.bump()}removeNode(t){this.nodes.delete(t)&&(this.selection.delete(t),this.bump())}setFrame(t,n){this.frames.set(t,n),this.bump()}removeFrame(t){this.frames.delete(t)&&this.bump()}upsertScore(t,n){const s=this.nodes.get(t);s===void 0||s.score===n||(s.score=n,this.bump())}positions(){const t=new Map;for(const[n,s]of this.nodes)t.set(n,{x:s.x,y:s.y});return t}frameRects(){const t=new Map;for(const[n,s]of this.frames)t.set(n,{...s});return t}teamMemberIds(t){const n=[];for(const s of this.nodes.values()){const o=s.memberships.find(i=>i.team===t);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(t,n){for(const s of this.nodes.values()){const o=s.memberships.filter(r=>r.team!==t),i=n.indexOf(s.id);i>=0&&o.push({team:t,index:i}),s.memberships=o}this.bump()}contentBounds(){let t=Number.POSITIVE_INFINITY,n=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY,o=Number.NEGATIVE_INFINITY;const i=r=>{t=Math.min(t,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(at(r));for(const r of this.frames.values())i(r);return t===Number.POSITIVE_INFINITY?null:{minX:t,minY:n,maxX:s,maxY:o}}static fromState(t){const n=new kn,s=mo(t.layout),o=new Map;for(const i of t.teams)for(let r=0;r<i.members.length;r++){const c=i.members[r].id,d=o.get(c)??[];d.push({team:i.name,index:r}),o.set(c,d)}for(const i of t.sessions){if(i.joined!==!0)continue;const r=s==null?void 0:s.nodes[i.id];let c,d;if(r!==void 0&&typeof r.x=="number"&&typeof r.y=="number")c=r.x,d=r.y;else{const m=ho(i.id,[...n.nodes.values()]);c=m.x,d=m.y}n.nodes.set(i.id,{id:i.id,x:c,y:d,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 t.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 c=[];for(const d of i.members){const m=n.nodes.get(d.id);m!==void 0&&c.push(at(m))}c.length>0&&n.frames.set(i.name,Cn(c))}return n.viewport=s!==void 0?{...s.viewport}:{x:0,y:0,scale:1},n}}const is=24,bo=-13,rs=bo+is;function as(e,t,n){const s=[],o=new Set;for(const i of e){const r=t.get(i.name);if(r===void 0)continue;const c=r.x+r.w/2,d=r.y+rs;for(const m of i.members){const g=n.get(m.id);if(g===void 0)continue;const u=o.has(m.id);o.add(m.id),s.push({x1:c,y1:d,x2:g.x,y2:g.y-Pe/2,dashed:u,team:i.name,id:m.id})}}return s}function cs(e,t){for(;e.firstChild!==null;)e.firstChild.remove();const n=t.allFrames().map(([s])=>({name:s,members:t.teamMemberIds(s).map(o=>({id:o}))}));for(const s of as(n,new Map(t.allFrames()),t.positions())){const o=document.createElementNS("http://www.w3.org/2000/svg","line");o.setAttribute("class","e-member"+(s.dashed?" dashed":"")),o.setAttribute("x1",String(s.x1)),o.setAttribute("y1",String(s.y1)),o.setAttribute("x2",String(s.x2)),o.setAttribute("y2",String(s.y2)),e.appendChild(o)}}function ls(e){return`peer-${rt(e).replace(/[^A-Za-z0-9.:\[\]-]/g,"-")}`}function rt(e){try{return new URL(e).host}catch{return e}}function ds(e){const t=new Map;for(const n of e){const s=n.via!==void 0&&n.via!==""?rt(n.via):"",o=t.get(s)??[];o.push(n),t.set(s,o)}return t}const us=140,ms=200,fs=90,ps=20,Kt=60;function hs(e,t){const n=t!==null?t.maxX+us:ms,s=t!==null?t.minY:0;return e.map((o,i)=>({url:o.url,score:o.score,x:n,y:s+i*fs}))}function bs(e,t,n,s){const o=new Map;for(const r of e){if(!t.has(r.team))continue;const c=`${r.team}\0${r.peer}`,d=o.get(c);d===void 0?o.set(c,{team:r.team,peer:r.peer,startedAt:r.startedAt,count:1}):(d.startedAt=Math.min(d.startedAt,r.startedAt),d.count+=1)}const i=[];for(const r of o.values()){const c=t.get(r.team);if(c===void 0)continue;const d=n.find(g=>{try{return new URL(g.url).host===r.peer}catch{return!1}});if(d===void 0)continue;const m=Math.max(0,Math.round((s-r.startedAt)/1e3));i.push({x1:c.x,y1:c.y,x2:d.x,y2:d.y,label:`a2a_route · ${r.peer} · ${m}s`+(r.count>1?` ×${r.count}`:"")})}return i}function gs(e,t){const n=t!==null?{x:t.maxX+ps,y:e.length>0?(e[0].y+e[e.length-1].y)/2:(t.minY+t.maxY)/2}:{x:-80,y:0};return e.map((s,o)=>({x1:n.x,y1:n.y,x2:s.x,y2:s.y,label:o===0?"gns referral":""}))}function vs(e,t){if(e===null&&t.length===0)return null;let n=e!==null?e.minX:Number.POSITIVE_INFINITY,s=e!==null?e.minY:Number.POSITIVE_INFINITY,o=e!==null?e.maxX:Number.NEGATIVE_INFINITY,i=e!==null?e.maxY:Number.NEGATIVE_INFINITY;for(const r of t)n=Math.min(n,r.x-Kt),s=Math.min(s,r.y-Kt),o=Math.max(o,r.x+Kt),i=Math.max(i,r.y+Kt);return{minX:n,minY:s,maxX:o,maxY:i}}const ys=11;function ws(e,t){let n=[],s=[],o=[];function i(c){for(const g of n)g.remove();n=[];const d=t.allNodes().filter(g=>g.remote===!0).map(g=>({url:g.peerUrl??g.id.slice(5),score:g.score,x:g.x,y:g.y}));s=d;const m=t.contentBounds();if(m!==null){const g=new Map;for(const[u,E]of t.allFrames())g.set(u,{name:u,x:E.x+E.w/2,y:E.y+ys});for(const u of bs(o,g,d,c))n.push(...r(u,"e-activity",u.label));for(const u of gs(d,m))n.push(...r(u,"e-federal",u.label))}}function r(c,d,m){const g=document.createElementNS("http://www.w3.org/2000/svg","line");g.setAttribute("class",d),g.setAttribute("x1",String(c.x1)),g.setAttribute("y1",String(c.y1)),g.setAttribute("x2",String(c.x2)),g.setAttribute("y2",String(c.y2)),e.appendChild(g);const u=[g];if(m!==""){const E=document.createElementNS("http://www.w3.org/2000/svg","text");E.setAttribute("class","edge-label mono"),E.setAttribute("x",String((c.x1+c.x2)/2+14)),E.setAttribute("y",String((c.y1+c.y2)/2+18)),E.textContent=m,e.appendChild(E),u.push(E)}return u}return{render:i,flyTo(c){return c(),s},placements:()=>s,setInFlight:c=>{o=c}}}function xs(e,t){const n=new Map,s=new Set;for(const o of e){if(o.joined!==!0)continue;const i=o.team.lastIndexOf("/");if(i<=0||o.team.slice(i+1)!==o.id.replace(/^session-/,"").slice(0,8))continue;const r=o.team;t.has(r)||s.has(r)||(n.has(r)?(n.delete(r),s.add(r)):n.set(r,o.id))}return n}function Cs(e,t,n,s){var r;const o=t.get(e);return o!==void 0?o:e.includes("/")?`member-${e.replace(/[^a-z0-9-]/gi,"-")}`:`member-${((r=n==null?void 0:n.find(c=>c.via===s))==null?void 0:r.team.split("/")[0])??"dsh"}-${e.replace(/^session-/,"").slice(0,8)}`}const jn={x:0,y:0,scale:1};function Qt(e){return Math.max(wn,Math.min(xn,e))}function kt(e){const t=Number.isFinite(e.scale)?e.scale:1,n=Number.isFinite(e.x)?e.x:0,s=Number.isFinite(e.y)?e.y:0;return{x:n,y:s,scale:Qt(t)}}function mt(e,t,n){return{x:e.x+t/e.scale,y:e.y+n/e.scale}}function dn(e,t,n){return{x:e.x+t/e.scale,y:e.y+n/e.scale,scale:e.scale}}function Bn(e,t,n,s){const o=Qt(e.scale*t);return o===e.scale?e:{x:e.x+n/e.scale-n/o,y:e.y+s/e.scale-s/o,scale:o}}const ks=680,Es=.8,$s=.6,Yn=16;function En(e,t,n,s=Number.POSITIVE_INFINITY){if(e===null||t<=0||n<=0)return jn;const o=e.maxX-e.minX,i=e.maxY-e.minY;if(!(o>0)||!(i>0))return jn;const r=.9*Math.min(t/o,n/i),c=Math.min(s,r),d=t<ks?Es:$s;if(r<d){const g=Qt(Math.min(s,d));return{x:e.minX-Yn/g,y:e.minY-Yn/g,scale:g}}const m=Qt(c);return{x:(e.minX+e.maxX)/2-t/(2*m),y:(e.minY+e.maxY)/2-n/(2*m),scale:m}}function Ns(e){return`translate(${-e.x*e.scale}px, ${-e.y*e.scale}px) scale(${e.scale})`}function Wn(e,t){let n=e===null?null:{...e,minY:e.minY+bo};for(const s of t){if(s.remote!==!0)continue;const o=at(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 Kn(e,t,n,s){const o=s>0&&s<n/2?s:0,i=En(e,t,n-o,1);return o===0||e===null?i:{...i,y:i.y-o/i.scale}}function Xn(...e){const t=Math.max(0,...e.map(n=>n.offsetHeight>0?n.offsetTop+n.offsetHeight:0));return t>0?t+8:0}function Pt(e){return e.type==="join-network"||e.type==="leave-network"?"$network":e.type==="create-team"||e.type==="remove-team"?e.name:e.team}function Ms(e,t){if(t.type==="create-team"){const o=t.ids.map(i=>e.getNode(i)).filter(i=>i!==void 0).map(i=>at(i));return o.length>0&&e.setFrame(t.name,Cn(o)),e.setTeamMembers(t.name,t.ids),()=>{e.setTeamMembers(t.name,e.teamMemberIds(t.name).filter(i=>!t.ids.includes(i))),e.removeFrame(t.name)}}if(t.type==="add-member"){const o=e.teamMemberIds(t.team),i=t.ids.filter(r=>!o.includes(r));return e.setTeamMembers(t.team,[...o,...i]),()=>{e.setTeamMembers(t.team,e.teamMemberIds(t.team).filter(r=>!i.includes(r)))}}if(t.type==="remove-member"){const o=e.teamMemberIds(t.team);return e.setTeamMembers(t.team,o.filter(i=>!t.ids.includes(i))),()=>{const i=e.teamMemberIds(t.team);e.setTeamMembers(t.team,[...i,...t.ids.filter(r=>!i.includes(r))])}}if(t.type==="remove-team"){const o=e.teamMemberIds(t.name),i=e.getFrame(t.name),r=i!==void 0?{...i}:void 0;return e.setTeamMembers(t.name,[]),e.removeFrame(t.name),()=>{r!==void 0&&e.setFrame(t.name,r),e.setTeamMembers(t.name,o)}}if(t.type==="join-network"||t.type==="leave-network")return()=>{};const n=e.teamMemberIds(t.team);let s=[...n];for(const o of t.ops)o.op==="remove"?s=s.filter(i=>i!==o.id):s.push(o.id);return e.setTeamMembers(t.team,s),()=>{let o=e.teamMemberIds(t.team);for(let i=0;i<n.length;i++){const r=n[i];o[i]!==r&&o.includes(r)&&(o=o.filter(c=>c!==r),o.push(r))}e.setTeamMembers(t.team,o)}}function Un(e,t,n,s,o){if(n||s(),!(t.type==="remove-team"&&n||t.type==="create-team"&&!n&&t.created===!0)||o===void 0||e.getFrame(Pt(t))!==void 0)return o;const r={...o.frames};return delete r[Pt(t)],{...o,frames:r}}function bn(e,t){const n=[...e],s=[];for(let o=0;o<t.length;o++){const i=t[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(e,t){return e.teamMemberIds(t).map(n=>{var s;return{id:n,y:((s=e.getNode(n))==null?void 0:s.y)??0}}).sort((n,s)=>n.y-s.y).map(n=>n.id)}function un(e,t){let n,s=Number.POSITIVE_INFINITY;for(const[o,i]of e){if(t.x<i.x||t.x>i.x+i.w||t.y<i.y||t.y>i.y+i.h)continue;const r=i.w*i.h;r<s&&(n=o,s=r)}return n}const qn=[9133302,3900150,1357990,16096779,15485081,8702998];function As(e){let t=0;for(let c=0;c<e.length;c++)t=(t*31+e.charCodeAt(c)&268435455)>>>0;const n=qn[t%qn.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)`}}const Zt="roster:",go=e=>e.startsWith(Zt)?e.slice(Zt.length):void 0,_t=e=>Zt+e,en=e=>{const t=go(e);return t===void 0?e:`网络队 · roster · ${t}`};function Ls(e,t){return e.flatMap(n=>{if(t===""||!n.team.startsWith(t+"/")||!Array.isArray(n.members))return[];const s=n.team.slice(t.length+1);return s===""||s.length>40||s.includes("/")||s.startsWith(Zt)||s.includes("*")?[]:[{name:_t(s),team:n.team,kind:"roster",members:n.members.filter(o=>typeof o=="string"&&o!=="").map(o=>({id:o}))}]})}function Is(e){const{root:t,netBtn:n,signal:s,model:o}=e,i=y=>e.isRoster(y)?en(y):y;function r(){return o.selectedIds().map(y=>{var f;return{id:y,y:((f=o.getNode(y))==null?void 0:f.y)??0}}).sort((y,f)=>y.y-f.y).map(y=>y.id)}function c(){if(d!==null)return;const y=r().filter(f=>{const _=o.getNode(f);return _===void 0?!1:_.remote!==!0||_.remoteHandle!==void 0&&_.remoteHandle!==""});if(y.length<2){e.notice("info","框选至少 2 个会话节点");return}m(y)}let d=null;function m(y){const f=document.createElement("div");f.className="p-dialog";const _=document.createElement("div");_.className="p-dialog-panel",_.setAttribute("role","dialog"),_.setAttribute("aria-modal","true"),_.setAttribute("aria-labelledby","p-dialog-title");const p=document.createElement("div");p.id="p-dialog-title",p.className="p-dialog-title",p.textContent=`组建团队(${y.length} 个节点,自上而下即优先级)`;const R={value:"canvas"},j=document.createElement("div");j.className="p-dialog-kind",j.setAttribute("role","radiogroup"),j.setAttribute("aria-label","团队类型");const K=document.createElement("div");K.className="p-dialog-hint";const we={canvas:"canvas 队:画布上的协作组,可以加入远端成员。",roster:"roster 网络队:只收本机已入网的会话;队名会写进属主的精确允许名单。"},Ae=["canvas","roster"].map(le=>{const te=document.createElement("button");return te.type="button",te.dataset.kind=le,te.setAttribute("role","radio"),te.textContent=le==="canvas"?"canvas 队":"roster 网络队",te.addEventListener("click",()=>P(le)),j.appendChild(te),te});function P(le){R.value=le;for(const te of Ae){const Ne=te.dataset.kind===le;te.setAttribute("aria-checked",String(Ne)),te.tabIndex=Ne?0:-1}K.textContent=we[le],ie.textContent=""}j.addEventListener("keydown",le=>{var Ne;const te=le;["ArrowLeft","ArrowRight","ArrowUp","ArrowDown"].includes(te.key)&&(te.preventDefault(),P(R.value==="canvas"?"roster":"canvas"),(Ne=Ae.find(je=>je.dataset.kind===R.value))==null||Ne.focus())});const U=document.createElement("input");U.className="p-dialog-input",U.maxLength=40,U.setAttribute("aria-label","团队名");const ie=document.createElement("div");ie.className="p-dialog-err",ie.setAttribute("aria-live","polite");const Re=document.createElement("div");Re.className="p-dialog-row";const $e=document.createElement("button");$e.type="button",$e.textContent="组建";const re=document.createElement("button");re.type="button",re.textContent="取消",Re.append($e,re),P("canvas"),_.append(p,j,K,U,ie,Re),f.appendChild(_),t.appendChild(f);const Ce=document.activeElement,Q=()=>{f.remove(),d=null,Ce==null||Ce.focus()},oe=()=>{const le=U.value.trim();return le===""||le.length>40||le.includes("/")||le.startsWith("roster:")||R.value==="roster"&&le.includes("*")||/^\d+$/.test(le)?"队名需 1..40 字,不含“/”、通配符或保留前缀,不为纯数字":R.value==="roster"&&o.getFrame(le)!==void 0?"同名 canvas 队已存在,不能创建 roster 队":R.value==="roster"&&o.getFrame(_t(le))!==void 0&&!e.isRoster(_t(le))?"roster 框名已被 canvas 或镜像队占用":R.value==="canvas"&&o.getFrame(_t(le))!==void 0?"同名 roster 队已存在,不能创建 canvas 队":R.value==="roster"&&y.some(te=>{var Ne;return((Ne=o.getNode(te))==null?void 0:Ne.remote)===!0||!e.joined(te)})?"roster 仅接受本机已入网的会话":null},xe=()=>{const le=oe();if(le!==null){ie.textContent=le,U.focus();return}const te=R.value==="roster"?_t(U.value.trim()):U.value.trim();if(Q(),o.getFrame(te)!==void 0){e.notice("info",`已加入现有团队「${R.value==="roster"?en(te):te}」`),e.emit({type:"add-member",team:te,ids:y});return}e.emit({type:"create-team",name:te,ids:y,created:!0,...R.value==="roster"?{roster:!0}:{}})};$e.addEventListener("click",xe),re.addEventListener("click",Q),U.addEventListener("keydown",le=>{const te=le;te.key==="Enter"&&(te.preventDefault(),xe()),te.key==="Escape"&&(te.preventDefault(),Q())}),f.addEventListener("keydown",le=>{const te=le;if(te.key==="Escape"){te.preventDefault(),te.stopPropagation(),Q();return}if(te.key!=="Tab")return;te.preventDefault();const Ne=Array.from(_.querySelectorAll('input, select, button:not([tabindex="-1"])')),je=Ne.indexOf(document.activeElement),qe=te.shiftKey?Ne[(je-1+Ne.length)%Ne.length]:Ne[(je+1)%Ne.length];qe==null||qe.focus()},s),d={wrap:f,restoreFocus:Ce},U.focus()}let g=null,u="root",E=null,M=null,J=[];function fe(){M==null||M.remove(),M=null}function ne(){var _;if(M!==null){fe();return}if(J.length===0)return;const y=document.createElement("div");y.className="p-menu p-netmenu",y.setAttribute("role","menu"),y.setAttribute("aria-label","未入网会话");for(const p of J)y.appendChild(C(`${p.name!==void 0&&p.name!==""?p.name:p.label} — 入网`,!0,()=>{fe(),e.emit({type:"join-network",id:p.id})}));M=y,t.appendChild(y);const f=n.getBoundingClientRect();y.style.left=`${String(Math.min(f.left,window.innerWidth-220))}px`,y.style.top=`${String(Math.max(8,f.top-(J.length*30+10)))}px`,y.addEventListener("keydown",p=>{p.key==="Escape"&&(p.stopPropagation(),fe(),n.focus())}),(_=y.querySelector("button"))==null||_.focus(),document.addEventListener("pointerdown",p=>{if(M===null)return;const R=p.target;R!==null&&(R.closest(".p-netmenu")!==null||R===n||n.contains(R))||fe()},s)}function S(){g==null||g.remove(),g=null,u="root",E!==null&&E.isConnected?E.focus():t.focus(),E=null}function C(y,f,_){const p=document.createElement("button");return p.type="button",p.setAttribute("role","menuitem"),p.textContent=y,f?p.addEventListener("click",()=>{S(),_()}):(p.disabled=!0,p.setAttribute("aria-disabled","true")),p}function $(y,f,_,p="root",R){var Ae,P,U,ie,Re,$e,re;R!==void 0&&(E=R),E===null&&(E=e.anchorFor(_)),g==null||g.remove(),u=p;const j=document.createElement("div");j.className="p-menu",j.setAttribute("role","menu"),j.setAttribute("aria-label","团队操作");let K=[];if(_.kind==="frame")K=[C(`解散团队「${i(_.name)}」`,!0,()=>e.emit({type:"remove-team",name:_.name}))];else{const Ce=_.id;if(p==="root"){const Q=C("组成团队…",o.selectedIds().length>=2,()=>m(r()));Q.title="先框选或 Shift 加选至少 2 个节点",K.push(Q),e.teams().length>0&&(K.push(C("加入团队 ▸",!0,()=>$(y,f,_,"join"))),(((Ae=o.getNode(Ce))==null?void 0:Ae.memberships.map(xe=>xe.team))??[]).length>0&&(K.push(C("置顶路由 ▸",!0,()=>$(y,f,_,"promote"))),K.push(C("离队 ▸",!0,()=>$(y,f,_,"leave"))))),((P=o.getNode(Ce))==null?void 0:P.remote)!==!0&&K.push(C("退网",!0,()=>e.emit({type:"leave-network",id:Ce})))}else{K.push(C("‹ 返回",!0,()=>$(y,f,_,"root")));for(const Q of e.teams())if(p==="join"){const oe=((U=o.getNode(Ce))==null?void 0:U.memberships.some(te=>te.team===Q.name))??!0,xe=!e.isRoster(Q.name)||e.joined(Ce)&&((ie=o.getNode(Ce))==null?void 0:ie.remote)!==!0,le=C(oe?`${i(Q.name)}(已加入)`:i(Q.name),!oe&&xe,()=>e.emit({type:"add-member",team:Q.name,ids:[Ce]}));xe||(le.title="roster 只接受本机已入网会话"),K.push(le)}else if(p==="leave"){const oe=((Re=o.getNode(Ce))==null?void 0:Re.memberships.some(xe=>xe.team===Q.name))??!1;K.push(C(i(Q.name),oe,()=>e.emit({type:"remove-member",team:Q.name,ids:[Ce]})))}else{const oe=(($e=o.getNode(Ce))==null?void 0:$e.memberships.some(xe=>xe.team===Q.name))??!1;if(e.isRoster(Q.name))continue;K.push(C(i(Q.name),oe,()=>{const xe=o.teamMemberIds(Q.name),le=[Ce,...xe.filter(te=>te!==Ce)];e.emit({type:"reorder",team:Q.name,ops:bn(xe,le)})}))}}}j.append(...K),j.style.left=`${Math.min(y,window.innerWidth-200)}px`;const we=K.length*30+8;j.style.top=`${Math.max(8,Math.min(f,window.innerHeight-we-8))}px`,j.addEventListener("keydown",Ce=>{var le,te,Ne,je;const Q=Ce,oe=Array.from(j.querySelectorAll("[role=menuitem]")),xe=oe.indexOf(document.activeElement);Q.key==="ArrowDown"?(Q.preventDefault(),(le=oe[(xe+1+oe.length)%oe.length])==null||le.focus()):Q.key==="ArrowUp"?(Q.preventDefault(),(te=oe[(xe-1+oe.length)%oe.length])==null||te.focus()):Q.key==="Home"?(Q.preventDefault(),(Ne=oe[0])==null||Ne.focus()):Q.key==="End"?(Q.preventDefault(),(je=oe[oe.length-1])==null||je.focus()):Q.key==="Escape"&&(Q.preventDefault(),Q.stopPropagation(),u!=="root"?$(y,f,_,"root"):S())}),t.appendChild(j),g=j,(re=K[0])==null||re.focus()}function k(y,f,_){if(d!==null)return;const p=(_==null?void 0:_.closest(".p-node"))??null;if(p!==null){const K=o.getNode(p.dataset.id??"");if((K==null?void 0:K.remote)===!0&&(K.remoteHandle===void 0||K.remoteHandle===""))return}const R=p,j=(_==null?void 0:_.closest(".p-frame-head"))??null;if(R!==null){const K=R.dataset.id??"";o.isSelected(K)||o.setSelection([K]),E=R,$(y,f,{kind:"node",id:K})}else j!==null&&(E=j,$(y,f,{kind:"frame",name:j.dataset.frame??""}))}function V(y){J=y,n.textContent=`未入网${J.length>0?`(${String(J.length)})`:""}`,n.disabled=J.length===0,n.setAttribute("aria-disabled",String(J.length===0)),J.length===0&&fe()}return{menuItem:C,isMenuOpen:()=>g!==null,isDialogOpen:()=>d!==null,closeMenu:S,openMenu:$,contextMenuAt:k,openNameDialog:m,startCreateFromSelection:c,toggleNetMenu:ne,setUnjoined:V}}function Ts(e,t){const n=t.trim().toLowerCase();return n===""?[]:e.filter(s=>s.name.toLowerCase().includes(n)||s.team.toLowerCase().includes(n)||(s.host??"").toLowerCase().includes(n)).slice(0,8)}function _s(e,t){return e.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:t(n);return{id:n.id,name:o,team:n.team,...n.remote===!0?{host:s}:{}}})}function Os(e,t=1200){e!==void 0&&(e.classList.add("pulse"),setTimeout(()=>e.classList.remove("pulse"),t))}function Fs(e){return t=>{const n=e.model.getNode(t);if(n===void 0)return;const s=e.viewSize();e.setVp(En({minX:n.x,minY:n.y,maxX:n.x+We,maxY:n.y+Pe},s.w,s.h,1)),e.applyViewport(),e.markDirty(),Os(e.cardEl(t))}}function Ps(e,t,n,s){const o=Rs({onPick:s});return e.appendChild(o.root),{...o,refresh:()=>o.setIndex(_s(t,n))}}function Rs(e){const t=document.createElement("div");t.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 c=()=>{s.style.display="none",s.textContent=""},d=()=>{if(s.textContent="",i.length===0){c();return}i.forEach((u,E)=>{const M=document.createElement("div");M.className="p-search-hit"+(E===r?" active":""),M.dataset.id=u.id,M.textContent=u.name===u.team?u.name:`${u.name} · ${u.team}`,M.addEventListener("mousedown",J=>{J.preventDefault(),e.onPick(u.id),m()}),s.appendChild(M)}),s.style.display="block"},m=()=>{n.value="",i=[],c()},g=()=>{i=Ts(o,n.value),r=0,d()};return n.addEventListener("input",g),n.addEventListener("keydown",u=>{if(u.key==="Escape"){m(),n.blur(),u.stopPropagation();return}if(u.key==="ArrowDown"||u.key==="ArrowUp"){if(i.length===0)return;u.preventDefault(),r=(r+(u.key==="ArrowDown"?1:i.length-1))%i.length,d();return}u.key==="Enter"&&i.length>0&&(u.preventDefault(),e.onPick(i[r].id),m())}),t.append(n,s),{root:t,setIndex(u){o=u,n.value!==""&&g()},focus(){n.focus(),n.select()},clear(){m()}}}const Xt=28,zn=16,Jn=14,Vn=48,Ds=4,Hs=180,js=90,Bs=1600;function Ys(e){const t=e.wrapWidth??Bs,n=e.frames.map(d=>{const m=Math.max(d.soleIds.length,1),g=Math.min(Ds,Math.max(1,Math.ceil(Math.sqrt(m)))),u=Math.ceil(m/g),E=Math.max(Hs,Xt*2+g*We+(g-1)*zn),M=Math.max(js,Xt*2+u*Pe+(u-1)*Jn);return{name:d.name,w:E,h:M,rows:u,perRow:g,soleIds:d.soleIds}}),s=[],o=[];let i=0,r=0,c=0;for(const d of n){i>0&&i+d.w>t&&(i=0,r+=c+Vn,c=0);const m={x:i,y:r,w:d.w,h:d.h};s.push({name:d.name,rect:m});const g=m.x+Xt+We/2;let u=m.y+Xt+Pe/2;d.soleIds.forEach((E,M)=>{const J=M%d.perRow;M>0&&J===0&&(u+=Pe+Jn),o.push({id:E,x:g+J*(We+zn),y:u})}),i+=d.w+Vn,c=Math.max(c,d.h)}return{frames:s,seats:o}}function Ws(e,t){const n=[];for(const[o,i]of e.allFrames()){if(t.has(o))continue;const r=e.teamMemberIds(o).map(c=>e.getNode(c)).filter(c=>c!==void 0).filter(c=>c.memberships.length===1).map(c=>c.id);n.push({name:o,rect:i,soleIds:r})}if(n.length===0)return!1;const s=Ys({frames:n});for(const o of s.frames)e.setFrame(o.name,o.rect);for(const o of s.seats){const i=e.getNode(o.id);i!==void 0&&e.dragNodes([o.id],o.x-i.x,o.y-i.y)}return!0}function Ks(e,t){if(e===void 0)return;const n=rt(e);return{text:t?`同步中… · ${n}`:`镜像 · ${n}`,title:t?`已把改动交给属主 ${n},等待它确认`:`这个团队属于 ${n},这里显示的是它的镜像;拖入或移出成员会经中继交给 ${n} 执行`,syncing:t}}const Xs=1e4;function Us(e=Date.now){const t=(s,o)=>`${s}\0${o}`,n=new Map;return{fork(s,o){return n.set(t(o,s.name),{url:o,name:s.name}),{...s,fleetPeer:o}},settled(s,o){if(s.type!=="remove-team"||s.name===void 0||s.fleetPeer===void 0)return;const i=n.get(t(s.fleetPeer,s.name));i!==void 0&&(o?i.acceptedAt=e():n.delete(t(s.fleetPeer,s.name)))},hides(s,o){return n.has(t(o,s))},sweep(s){var o;for(const[i,r]of n)(!(((o=s.find(d=>d.url===r.url))==null?void 0:o.org.some(d=>d.name===r.name))===!0)||r.acceptedAt!==void 0&&e()-r.acceptedAt>Xs)&&n.delete(i)}}}const wt=24,qs=200,zt=(e,t)=>e.x<t.x+t.w&&t.x<e.x+e.w&&e.y<t.y+t.h&&t.y<e.y+e.h;function zs(e,t){const n=t.x+t.w+wt-e.x,s=t.x-wt-(e.x+e.w),o=t.y+t.h+wt-e.y,i=t.y-wt-(e.y+e.h),r=Math.abs(n)<=Math.abs(s)?n:s,c=Math.abs(o)<=Math.abs(i)?o:i;return Math.abs(r)<=Math.abs(c)?{dx:r,dy:0}:{dx:0,dy:c}}function Js(e,t,n,s){const o=e.beginFrameDrag(t);o!==void 0&&e.applyFrameDrag(o,n,s)}function Vs(e,t,n){let s=!1;for(let o=0;o<qs;o++){const i=e.allFrames();let r;for(let S=0;S<i.length&&r===void 0;S++)for(let C=S+1;C<i.length;C++){const[$,k]=i[S],[V,y]=i[C];if(!(t.has($)&&t.has(V))&&zt(k,y)){r=[$,k,V,y];break}}if(r===void 0)return s;const[c,d,m,g]=r,u=S=>t.has(S)?2:S===n?1:0,[E,M,J]=u(c)<u(m)?[c,d,g]:[m,g,d],{dx:fe,dy:ne}=zs(M,J);Js(e,E,fe,ne),s=!0}return s}const ht=28,Jt=16,tn=14;function Gs(e){const t=[];for(let n=e.y+ht;n+Pe<=e.y+e.h-ht;n+=Pe+tn)for(let s=e.x+ht;s+We<=e.x+e.w-ht;s+=We+Jt)t.push({x:s+We/2,y:n+Pe/2});return t}function Qs(e){let t=!1;const n=e.allFrames(),s=new Map(n);for(const o of e.allNodes()){const i=new Set(o.memberships.map(ne=>ne.team)),r=n.find(([ne,S])=>!i.has(ne)&&zt(at(o),S));if(r===void 0)continue;const c=r[1],d=ne=>{const S=at(ne);return n.every(([C,$])=>i.has(C)||!zt(S,$))&&e.allNodes().every(C=>C.id===o.id||!zt(S,at(C)))},g=o.memberships.map(ne=>s.get(ne.team)).filter(ne=>ne!==void 0).flatMap(Gs).find(d),u={x:c.x+c.w+wt+We/2,y:o.y},E={x:o.x,y:c.y+c.h+wt+Pe/2},M=Math.max(...n.map(([,ne])=>ne.x+ne.w))+wt+We/2,J=Array.from({length:2*e.allNodes().length+1},(ne,S)=>({x:M,y:c.y+Pe/2+S*(Pe+tn)})),fe=g??[u,E,...J].find(d)??J[J.length-1];e.dragNodes([o.id],fe.x-o.x,fe.y-o.y),t=!0}return t}function Ut(e,t,n){const s=Vs(e,t,n),o=Qs(e);return s||o}function Zs(e){for(const[t,n]of e.allFrames()){const s=e.teamMemberIds(t).map(m=>e.getNode(m)).filter(m=>m!==void 0).filter(m=>m.memberships.length===1);if(s.length===0)continue;const o=Math.max(1,Math.floor((n.w-2*ht+Jt)/(We+Jt))),i=Math.ceil(s.length/o),r=ht*2+i*Pe+(i-1)*tn;r>n.h&&e.setFrame(t,{...n,h:Math.min(r,n.h+400)});const c=n.x+ht+We/2;let d=n.y+ht+Pe/2;s.forEach((m,g)=>{const u=g%o;g>0&&u===0&&(d+=Pe+tn);const E=c+u*(We+Jt);e.dragNodes([m.id],E-m.x,d-m.y)})}}const ei=30;function ti(e){const t=[],n=()=>({nodes:new Map(e.allNodes().map(i=>[i.id,{x:i.x,y:i.y}])),frames:new Map(e.allFrames().map(([i,r])=>[i,{...r}]))}),s=i=>e.allNodes().some(r=>{const c=i.nodes.get(r.id);return c!==void 0&&(c.x!==r.x||c.y!==r.y)})||e.allFrames().some(([r,c])=>{const d=i.frames.get(r);return d!==void 0&&(d.x!==c.x||d.y!==c.y||d.w!==c.w||d.h!==c.h)}),o=i=>{for(const r of e.allNodes()){const c=i.nodes.get(r.id);c!==void 0&&(c.x!==r.x||c.y!==r.y)&&e.dragNodes([r.id],c.x-r.x,c.y-r.y)}for(const[r,c]of e.allFrames()){const d=i.frames.get(r);d!==void 0&&(d.x!==c.x||d.y!==c.y||d.w!==c.w||d.h!==c.h)&&e.setFrame(r,{...d})}};return{capture:n,commit(i){s(i)&&(t.push(i),t.length>ei&&t.shift())},undo(){const i=t.pop();return i===void 0?!1:(o(i),!0)},revert(i){return s(i)?(o(i),!0):!1},get depth(){return t.length}}}function ni(e){const{root:t,trigger:n,signal:s,model:o}=e;let i=null,r="",c=null;function d(){c==null||c.remove(),c=null}function m(){d(),i==null||i.remove(),i=null}function g(){if(i!==null){m();return}const C=document.createElement("div");C.className="p-menu p-nodelist",C.setAttribute("role","dialog"),C.setAttribute("aria-label","节点清单"),i=C,t.appendChild(C);const $=n.getBoundingClientRect();C.style.left=`${String(Math.min($.left,window.innerWidth-340))}px`,C.style.top=`${String(Math.max(8,$.top-320))}px`,C.addEventListener("keydown",k=>{k.key==="Escape"&&(k.stopPropagation(),m(),n.focus())}),u()}function u(){var _;const C=i;if(C===null)return;d(),C.textContent="";const $=document.createElement("div");$.className="p-nodelist-head";const k=document.createElement("span");k.className="p-nodelist-title",k.textContent="节点";const V=document.createElement("select");V.className="p-nodesel",V.setAttribute("aria-label","选择 host 或对等节点");const y=document.createElement("option");y.value="",y.textContent="本机",V.appendChild(y);for(const[p,R]of e.facts().remoteTeams){if(p==="")continue;const j=document.createElement("option");j.value=p,j.textContent=((_=R[0])==null?void 0:_.origin)!==void 0&&R[0].origin!==""?`${R[0].origin}(${p})`:p,V.appendChild(j)}r!==""&&!e.facts().remoteTeams.has(r)&&(r=""),V.value=r,V.addEventListener("change",()=>{r=V.value,u()}),$.append(k,V);const f=document.createElement("div");f.className="p-nodelist-body",C.append($,f),r===""?ne(f):S(f,e.facts().remoteTeams.get(r)??[])}function E(C,$){const k=document.createElement("span");return k.className="p-nodedot"+($!==!0?" off":C===!1?" cold":""),k}function M(C,$){const k=document.createElement("button");return k.type="button",k.className="p-listbtn",k.textContent=C,k.addEventListener("click",V=>{V.stopPropagation(),$()}),k}function J(C,$){const k=document.createElement("div");if(k.className="p-nodelist-group",k.textContent=C,$!==void 0){const V=document.createElement("span");V.className="p-nodelist-note",V.textContent=$,k.appendChild(V)}return k}function fe(C,$){var y,f;d();const k=document.createElement("div");k.className="p-menu",k.setAttribute("role","menu"),k.setAttribute("aria-label","加入团队");for(const _ of e.facts().teams){const p=((y=o.getNode($))==null?void 0:y.memberships.some(R=>R.team===_.name))??!1;k.appendChild(e.menuItem(p?`${_.name}(已加入)`:_.name,!p,()=>{m(),e.emit({type:"add-member",team:_.name,ids:[$]})}))}k.appendChild(e.menuItem("新团队…",!0,()=>{m(),e.openNameDialog([$])})),c=k,t.appendChild(k);const V=C.getBoundingClientRect();k.style.left=`${String(Math.min(V.right+4,window.innerWidth-180))}px`,k.style.top=`${String(Math.max(8,V.top-60))}px`,k.addEventListener("keydown",_=>{_.key==="Escape"&&(_.stopPropagation(),d(),C.focus())}),(f=k.querySelector("button"))==null||f.focus()}function ne(C){var f,_;const $=new Set(e.facts().canvasMemberIds);for(const p of e.facts().sessions)p.teams!==void 0&&p.teams.length>0&&$.add(p.id);const k=e.facts().sessions.filter(p=>p.joined===!0&&!$.has(p.id)),V=e.facts().sessions.filter(p=>p.joined!==!0),y=e.facts().sessions.filter(p=>p.joined===!0&&$.has(p.id));C.appendChild(J(`未组队 (${String(k.length)})`,"无网络能力"));for(const p of k){const R=document.createElement("div");R.className="p-noderow";const j=document.createElement("span");j.className="p-nodename",j.textContent=p.name!==void 0&&p.name!==""?p.name:p.label,j.title=p.team;const K=document.createElement("span");K.className="p-nonet",K.textContent="无网络能力";const we=M("入队▸",()=>fe(we,p.id));R.append(E(p.live,!0),j,K,we,M("退网",()=>{m(),e.emit({type:"leave-network",id:p.id})})),C.appendChild(R)}C.appendChild(J(`未入网 (${String(V.length)})`));for(const p of V){const R=document.createElement("div");R.className="p-noderow";const j=document.createElement("span");j.className="p-nodename",j.textContent=p.name!==void 0&&p.name!==""?p.name:p.label,j.title=p.id,R.append(E(p.live,!1),j,M("入网",()=>{m(),e.emit({type:"join-network",id:p.id})})),C.appendChild(R)}C.appendChild(J(`已组队 (${String(y.length)})`,"画布展示"));for(const p of y){const R=document.createElement("div");R.className="p-noderow";const j=document.createElement("span");j.className="p-nodename",j.textContent=p.name!==void 0&&p.name!==""?p.name:p.label,j.title=p.team;const K=((f=o.getNode(p.id))==null?void 0:f.memberships.length)??0,we=((_=p.teams)==null?void 0:_.length)??0,Ae=document.createElement("span");Ae.className="p-teamcount",Ae.textContent=`队×${String(Math.max(K,0)+we)}`,R.append(E(p.live,!0),j,Ae,M("定位",()=>{e.locate(p.id)})),C.appendChild(R)}if(e.facts().sessions.length===0){const p=document.createElement("div");p.className="p-nodelist-empty",p.textContent="无会话节点",C.appendChild(p)}}function S(C,$){var y;const k=$.filter(f=>f.teams===void 0||f.teams.length===0),V=$.filter(f=>f.teams!==void 0&&f.teams.length>0);C.appendChild(J(`未组队 (${String(k.length)})`,"无网络能力 · 只读"));for(const f of k){const _=document.createElement("div");_.className="p-noderow";const p=document.createElement("span");p.className="p-nodename",p.textContent=f.name!==void 0&&f.name!==""?f.name:f.team,p.title=f.team;const R=document.createElement("span");R.className="p-nonet",R.textContent="无网络能力",_.append(E(!0,!0),p,R),C.appendChild(_)}C.appendChild(J(`已组队 (${String(V.length)})`,"只读"));for(const f of V){const _=document.createElement("div");_.className="p-noderow";const p=document.createElement("span");p.className="p-nodename",p.textContent=f.name!==void 0&&f.name!==""?f.name:f.team,p.title=f.team;const R=document.createElement("span");R.className="p-teamcount",R.textContent=`队×${String(((y=f.teams)==null?void 0:y.length)??0)}`,_.append(E(!0,!0),p,R),C.appendChild(_)}if($.length===0){const f=document.createElement("div");f.className="p-nodelist-empty",f.textContent="该节点未发布会话",C.appendChild(f)}}return document.addEventListener("pointerdown",C=>{if(i===null)return;const $=C.target;if($===null){m();return}$.closest(".p-nodelist")!==null||$.closest(".p-menu")!==null||$===n||n.contains($)||m()},s),{toggle:g,close:m,refresh:()=>{i!==null&&u()}}}function oi(e){let t=e;const n=t.search(/\|| ```|^```/);return n>=0&&(t=t.slice(0,n)),t.replace(/\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/(^|\s)#{1,6}\s+/g,"$1").replace(/\*\*|__|`/g,"").replace(/\s+/g," ").trim()}function si(e,t){const n=e.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(t!==void 0?`score ${t} · `:"")+`${e.length} 远端团队`+(s!==""?`:${s}${o}`:"")}function ii(e,t,n){if(e.id.startsWith("member-"))return{title:e.name!==void 0&&e.name!==""?e.name:e.team,sub:e.team,tip:e.team};if(e.remote===!0){const d=e.id.slice(5),m=t.length===1&&t[0].name!==void 0&&t[0].name!==""?t[0].name:void 0,g=si(t,n);return m!==void 0?{title:m,sub:`${d} · ${g}`,tip:`${m}
|
|
6
|
-
${d}
|
|
7
|
-
${g}`}:{title:d,sub:g,tip:`${d}
|
|
8
|
-
${g}`}}const s=it(e),o=e.team+(e.name!==void 0&&e.name!==""?" · "+e.name:""),i=oi(e.description??""),r=i!==""?i:o===s?"":e.team,c=(e.memberships.length>1?` · 跨队×${e.memberships.length}`:"")+(e.teams!==void 0&&e.teams.length>0?` · 网络队×${e.teams.length}`:"");return{title:s,sub:r+c,tip:i!==""?`${o}
|
|
9
|
-
${i}`:o}}function ri(e){if((e==null?void 0:e.status)===void 0)return"";const t=e.status==="running"?"工作中":"空闲";return typeof e.queued=="number"&&e.queued>0?`${t} · 排队 ${String(e.queued)}`:t}function ai(e){const t=document.createElement("div");t.className="p-node",t.dataset.id=e,t.tabIndex=0;const n=document.createElement("div");n.className="nm";const s=document.createElement("span");s.className="dot";const o=document.createElement("span");o.className="nm-text",n.append(s,o);const i=document.createElement("div");i.className="sub mono";const r=document.createElement("span");r.className="prio mono";const c=document.createElement("span");c.className="work";const d=document.createElement("div");return d.className="sub-row",d.append(i,c),t.append(n,d,r),t}function ci(e,t,n){if(t.remote===!0){const s=(n==null?void 0:n.link)==="linked"?"lnk-linked":(n==null?void 0:n.link)==="stranger"?"lnk-stranger":"";e.className!==`prio mono ${s}`.trim()&&(e.className=`prio mono ${s}`.trim());const o=n===void 0?"":n.verified===!0?"✓":"✗",i=(t.id.startsWith("member-")?"成员":(n==null?void 0:n.link)??"peer")+o;e.textContent!==i&&(e.textContent=i)}else{e.className!=="prio mono"&&(e.className="prio mono");const s=t.memberships[0]!==void 0?`P${t.memberships[0].index}`:"";e.textContent!==s&&(e.textContent=s)}}const Gn="dsh-a2a.board.legend";function li(){const e=document.createElement("details");e.className="p-legend";const t=document.createElement("summary");t.textContent="图例",t.title="边的含义(点击展开 / 收起)";const n=document.createElement("div");n.className="p-legend-rows";const s=(o,i,r)=>{const c=document.createElement("span"),d=document.createElement("i");o&&(d.className="dashed"),r!==void 0&&(d.style.borderTopColor=r),c.append(d,document.createTextNode(i)),n.appendChild(c)};s(!1,"成员边(星形,框→成员)"),s(!0,"跨队多属(虚线)"),s(!0,"roster 网络队框(双线边框)"),s(!1,"活动边(inFlight 路由,瞬时)","var(--accent)"),s(!0,"联邦线(→peer)","var(--federal)"),e.append(t,n);try{e.open=window.localStorage.getItem(Gn)==="open"}catch{}return e.addEventListener("toggle",()=>{try{window.localStorage.setItem(Gn,e.open?"open":"closed")}catch{}}),e}const Vt="对端未应答(显示的是最后已知状态)";function Qn(e){const t=new Set;for(const s of e.remoteTeams??[])s.unreachable===!0&&s.via&&t.add(rt(s.via));for(const s of e.peerOrg??[])s.unreachable===!0&&t.add(rt(s.url));const n=new Set;for(const s of e.remoteTeams??[])s.via&&t.has(rt(s.via))&&n.add(`member-${s.team.replace(/[^a-z0-9-]/gi,"-")}`);return{hosts:t,members:n}}function di(e,t){e.classList.toggle("is-unreachable",t);const n=e.querySelector(".p-frame-unreachable");if(t&&n===null){const s=document.createElement("span");s.className="p-frame-unreachable",s.textContent=Vt,e.appendChild(s)}else t||n==null||n.remove()}function ui(e){return e<680?"narrow":e<1024?"medium":"wide"}function mi(e){const t=new kn;let n,s={...t.viewport},o={kind:"none"},i=!1,r=-1,c=!0,d=!1;const m=ti(t);let g,u=!1;const E=()=>ui(globalThis.innerWidth||Ke),M=()=>{var a;(a=e.viewportStore)==null||a.set(E(),s),e.onDirty()},J=e.now??Date.now,fe=new AbortController,ne=[];let S=null,C=!1;const $={signal:fe.signal},k=document.createElement("section");k.id="dsh-plan",k.setAttribute("role","tabpanel"),k.setAttribute("aria-label","A2A 规划画布"),k.tabIndex=0,k.style.display="none";const V=document.createElement("div");V.className="p-grid";const y=document.createElement("div");y.className="p-world";const f=document.createElementNS("http://www.w3.org/2000/svg","svg");f.setAttribute("class","p-edges");const _=document.createElement("div");_.className="p-layer p-frames";let p;const R=a=>{var h,v;p!==void 0&&((h=Oe.get(p))==null||h.classList.remove("selected")),p=a,a!==void 0&&((v=Oe.get(a))==null||v.classList.add("selected"))},j=document.createElement("div");j.className="p-layer p-nodes",j.setAttribute("role","listbox"),j.setAttribute("aria-multiselectable","true"),j.setAttribute("aria-label","会话节点"),y.append(f,_,j);const K=document.createElement("div");K.className="p-marquee";const we=document.createElement("div");we.className="p-toolbar";const Ae=document.createElement("span");Ae.className="p-zoom mono",Ae.textContent="100%";const P=(a,h,v)=>{const F=document.createElement("button");return F.type="button",F.textContent=a,F.title=h,F.addEventListener("click",v,$),F},U=()=>{const a=document.createElement("span");return a.className="p-sep",a.setAttribute("role","separator"),a.setAttribute("aria-orientation","vertical"),a};we.append(P("适配","适配视图(快捷键 0)",()=>St()),P("-","缩小",()=>Xe(1/1.2)),Ae,P("+","放大",()=>Xe(1.2)),U(),P("建队","组成团队(G):先框选至少 2 个节点",()=>X.startCreateFromSelection()),P("整理成员","每队框内仅属一队的成员自动排齐(多队成员不动)",()=>bt()),P("一键重排","全板队框+成员重排:框尺寸随内容自适应、框位行流式平铺(远端队框与多归属成员不动)",()=>Nt()),P("撤销","撤销上一次布局改动:拖动、缩放、整理、重排、载入时避让(Ctrl+Z;入队离队不撤销)",()=>ft()));const ie=P("未入网","未入网会话(点击选择入网)",()=>X.toggleNetMenu());ie.className="p-netbtn",ie.setAttribute("aria-haspopup","menu"),we.append(U(),ie);const Re=Ps(we,t,it,a=>ae(a)),$e=P("节点","节点清单:本机与对等节点(未组队/未入网在此管理)",()=>ve.toggle());$e.className="p-nodebtn",$e.setAttribute("aria-haspopup","dialog"),we.appendChild($e);const re=document.createElement("span");re.setAttribute("aria-live","polite"),re.className="p-lamp";const Ce=document.createElement("i"),Q=document.createElement("span");Q.textContent="布局",re.append(Ce,Q),re.addEventListener("click",()=>{re.classList.contains("error")&&e.onLampClick()},$),re.addEventListener("keydown",a=>{const h=a;(h.key==="Enter"||h.key===" ")&&re.classList.contains("error")&&(h.preventDefault(),e.onLampClick())},$),we.appendChild(re);const oe=document.createElement("div");oe.className="p-status";const xe=document.createElement("span"),le=document.createElement("span"),te=document.createElement("span");te.className="mut";const Ne=document.createElement("span");Ne.className="mut",oe.append(xe,le,te,Ne),oe.tabIndex=0,oe.setAttribute("role","button"),oe.setAttribute("aria-label","定位在途路由与联邦对端"),oe.title="定位在途与联邦(回车)",oe.addEventListener("click",()=>pe(),$),oe.addEventListener("keydown",a=>{const h=a;(h.key==="Enter"||h.key===" ")&&(h.preventDefault(),pe())},$);const je=li(),qe=document.createElement("div");qe.className="p-notice-stack",qe.setAttribute("role","log"),qe.setAttribute("aria-live","polite"),k.append(V,y,K,we,oe,je,qe);let Ke=0,ct=0;const xt=()=>e.viewSize?e.viewSize():{w:k.clientWidth,h:k.clientHeight},ze=()=>{const a=xt();Ke=a.w,ct=a.h};function Ve(){y.style.transform=Ns(s);const a=24*s.scale;V.style.backgroundSize=`${a}px ${a}px`,V.style.backgroundPosition=`${-s.x*s.scale}px ${-s.y*s.scale}px`,Ae.textContent=`${Math.round(s.scale*100)}%`}function bt(){const a=m.capture();Zs(t),Ut(t,new Set(x.keys())),m.commit(a),M(),Le()}function Nt(){const a=m.capture();Ws(t,new Set(x.keys()))&&(Ut(t,new Set(x.keys())),m.commit(a),M(),Le())}function Le(){Ve(),t.revision!==r&&(r=t.revision,lt(),Mt(),cs(f,t)),ge()}const Oe=new Map,et=new Map;function lt(){var h;const a=new Set;for(const[v,F]of t.allFrames()){a.add(v);let O=Oe.get(v);if(O===void 0){O=document.createElement("div"),O.className="p-frame",O.dataset.name=v;const ke=document.createElement("div");ke.className="p-frame-head",ke.dataset.frame=v,ke.tabIndex=0,ke.setAttribute("role","button"),ke.setAttribute("aria-haspopup","menu"),ke.setAttribute("aria-label",`团队框 ${v}(拖动整组,回车菜单)`);const Qe=document.createElement("span");Qe.className="ttl";const tt=document.createElement("span");tt.className="cnt mono";const gt=document.createElement("span");gt.className="route mono",ke.append(Qe,tt,gt),O.appendChild(ke);for(const At of["n","s","e","w","ne","nw","se","sw"]){const vt=document.createElement("div");vt.className=`p-frame-handle p-h-${At}`,vt.dataset.frame=v,vt.dataset.dir=At,O.appendChild(vt)}_.appendChild(O),Oe.set(v,O)}const ue=As(v);O.style.setProperty("--frame-line",ue.line),O.style.setProperty("--frame-bg",ue.bg),O.style.left=`${F.x}px`,O.style.top=`${F.y}px`,O.style.width=`${F.w}px`,O.style.height=`${F.h}px`;const Y=O.querySelector(".ttl"),W=O.querySelector(".cnt"),z=O.querySelector(".route"),ce=w.has(v),Ie=ce?en(v):v;Y.textContent!==Ie&&(Y.textContent=Ie),O.classList.toggle("is-roster",ce);let _e=0,Me=0;for(const ke of t.allNodes())ke.memberships.find(tt=>tt.team===v)!==void 0&&(_e+=1,ke.memberships.length>1&&(Me+=1));const b=`${_e} 成员`+(Me>0?` +${Me} 跨队`:"");W.textContent!==b&&(W.textContent=b);const G=Ks(x.get(v),Te.has(v)),de=G!==void 0&&D.hosts.has(rt(x.get(v))),Fe=(G==null?void 0:G.text)??((h=Ht.find(ke=>ke.name===v))==null?void 0:h.team)??v;z.textContent!==Fe&&(z.textContent=Fe),z.title=`${(G==null?void 0:G.title)??""}${de?` · ${Vt}`:""}`,di(O,de),O.classList.toggle("is-mirror",G!==void 0),O.classList.toggle("is-syncing",(G==null?void 0:G.syncing)===!0);const Se=`团队框 ${v}${G!==void 0?`(${G.text})`:""}${de?`(${Vt})`:""}(拖动整组,回车菜单)`,me=O.querySelector(".p-frame-head");me.getAttribute("aria-label")!==Se&&me.setAttribute("aria-label",Se)}for(const[v,F]of[...Oe])a.has(v)||(F.remove(),Oe.delete(v))}function Mt(){const a=new Set;for(const h of t.allNodes()){a.add(h.id);let v=et.get(h.id);v===void 0&&(v=ai(h.id),j.appendChild(v),et.set(h.id,v));const F=at(h);v.style.left=`${F.x}px`,v.style.top=`${F.y}px`,v.classList.toggle("cold",!h.live),v.classList.toggle("remote",h.remote===!0);const O=h.live&&h.remote!==!0?L.get(h.id):void 0;v.classList.toggle("is-working",(O==null?void 0:O.status)==="running");const ue=ri(O),Y=v.querySelector(".work");Y.textContent!==ue&&(Y.textContent=ue),v.classList.toggle("selected",t.isSelected(h.id)),v.setAttribute("aria-selected",String(t.isSelected(h.id)));const W=h.id.slice(5),z=ii(h,h.remote===!0?A.get(W)??[]:[],Z.get(W)),ce=h.remote===!0&&(h.id.startsWith("member-")?D.members.has(h.id):D.hosts.has(W));v.classList.toggle("is-unreachable",ce);const Ie=v.querySelector(".nm-text");Ie.textContent!==z.title&&(Ie.textContent=z.title);const _e=v.querySelector(".sub"),Me=ce?`未应答 · ${z.sub}`:z.sub;_e.textContent!==Me&&(_e.textContent=Me);const b=ce?`${z.tip} · ${Vt}`:z.tip;v.title!==b&&(v.title=b);const G=h.id.startsWith("member-")?he.get(h.remoteHandle??""):W;ci(v.querySelector(".prio"),h,h.remote===!0&&G!==void 0?B.get(G):void 0)}for(const[h,v]of[...et])a.has(h)||(v.remove(),et.delete(h));Re.refresh()}const l=ws(f,t);let A=new Map,L=new Map;const Z=new Map,B=new Map;let he=new Map;function ge(){l.render(J())}function pe(){s=En(vs(t.contentBounds(),l.placements()),k.clientWidth||Ke,k.clientHeight||ct),Ve(),M()}const ae=Fs({model:t,viewSize:xt,setVp:a=>{s=a},applyViewport:Ve,markDirty:M,cardEl:a=>et.get(a)});function Be(a){var F;const h=a.sessions.filter(O=>O.live!==!1).length,v=(O,ue,Y)=>{const W=document.createElement("b");W.className=ue,W.textContent=Y,O.replaceChildren(W)};v(xe,"ok",`● ${h} live`),v(le,"warn",`● ${a.sessions.length-h} cold`),te.textContent=`${((F=a.inFlight)==null?void 0:F.length)??0} inFlight`,Ne.className="mut",Ne.textContent=`${a.teams.length} 队 · ${a.peerCount} peer`}const Te=new Map,Ye=a=>{Te.set(a,(Te.get(a)??0)+1),r=-1},Rt=a=>{r=-1;const h=(Te.get(a)??0)-1;h<=0?Te.delete(a):Te.set(a,h)};let x=new Map,w=new Set,D=Qn({});const N=Us(e.now);function I(a){const h=a.type==="create-team"&&a.roster===!0||w.has(Pt(a));if(h&&a.type==="remove-team"&&!window.confirm(`解散网络队「${en(a.name)}」并撤回成员与白名单?`))return;if(h&&a.type==="reorder"){H("error","roster 队不支持置顶路由");return}if(h&&(a.type==="create-team"||a.type==="add-member")&&a.ids.some(Y=>{var W;return((W=t.getNode(Y))==null?void 0:W.remote)===!0||!se.some(z=>z.id===Y&&z.joined===!0)})){H("error","roster 只接受本机已入网会话,远端或未入网成员未写入");return}function v(Y){const W=z=>{var Ie;const ce=[];for(const _e of z){if(!_e.startsWith("peer-")&&!_e.startsWith("member-")){ce.push(_e);continue}const Me=(Ie=t.getNode(_e))==null?void 0:Ie.remoteHandle;Me!==void 0&&Me!==""&&ce.push(Me)}return ce};if(Y.type==="add-member"||Y.type==="remove-member"||Y.type==="create-team"){const z=W(Y.ids),ce=Y.type!=="create-team"?x.get(Y.team):void 0;return z.length>0||ce!==void 0?{...Y,ids:z,...ce!==void 0?{fleetPeer:ce}:{}}:Y}return Y.type==="remove-team"&&x.has(Y.name)?N.fork(Y,x.get(Y.name)):Y}if(a.type==="add-member"||a.type==="remove-member"||a.type==="reorder"||a.type==="create-team"){const Y=a.type==="reorder"?a.ops.map(W=>W.id):[...a.ids];for(const W of Y){if(W===""||W.startsWith("peer-")||W.startsWith("member-")||t.getNode(W)!==void 0)continue;const z=se.find(_e=>_e.id===W);if(z===void 0)continue;const ce=n==null?void 0:n.nodes[W],Ie=ce!==void 0?{x:ce.x,y:ce.y}:Nn(W);t.upsertNode({id:W,x:Ie.x,y:Ie.y,label:z.label,team:z.team,name:z.name,description:z.description,live:z.live!==!1,memberships:[],...z.teams!==void 0&&z.teams.length>0?{teams:z.teams}:{}})}}h&&a.type==="create-team"&&w.add(a.name);const F=Ms(t,a),O=Pt(a);Ye(O),Le();const ue=v(h?{...a,roster:!0}:a);e.onCanvasAction(ue).then(Y=>{Rt(O),!Y&&a.type==="create-team"&&h&&w.delete(O),n=Un(t,a,Y,F,n),M(),N.settled(ue,Y),Le()},()=>{Rt(O),a.type==="create-team"&&h&&w.delete(O),n=Un(t,a,!1,F,n),M(),N.settled(ue,!1),H("error","操作通道异常,已回滚"),Le()})}function H(a,h){var F;for(;qe.childElementCount>=3;)(F=qe.firstElementChild)==null||F.remove();const v=document.createElement("div");v.className="p-notice"+(a==="error"?" error":""),v.setAttribute("role",a==="error"?"alert":"status"),v.textContent=h,qe.appendChild(v),ne.push(setTimeout(()=>v.remove(),4e3))}const X=Is({root:k,netBtn:ie,signal:$,model:t,teams:()=>Ht,joined:a=>se.some(h=>h.id===a&&h.joined===!0),isRoster:a=>w.has(a),anchorFor:a=>(a.kind==="node"?et.get(a.id):Oe.get(a.name))??null,emit:I,notice:H});let se=[],ee=new Set;const ve=ni({root:k,trigger:$e,signal:$,model:t,facts:()=>({sessions:se,canvasMemberIds:ee,remoteTeams:A,teams:Ht}),menuItem:X.menuItem,emit:I,openNameDialog:X.openNameDialog,locate:De});function De(a){var F;const h=t.getNode(a);if(h===void 0)return;ve.close();const v=((F=e.viewSize)==null?void 0:F.call(e))??{w:k.clientWidth>0?k.clientWidth:800,h:k.clientHeight>0?k.clientHeight:600};s=kt({scale:s.scale,x:h.x-v.w/(2*s.scale),y:h.y-v.h/(2*s.scale)}),Ve(),r=-1,Le()}function q(a){const h=k.getBoundingClientRect();return{x:a.clientX-h.left,y:a.clientY-h.top}}function He(a,h){var Y;const v=q(h),F=mt(s,v.x,v.y),O=un(new Map(t.allFrames()),F),ue=a.ids.filter(W=>{const z=t.getNode(W);return z===void 0?!1:z.remote!==!0?!0:z.remoteHandle!==void 0&&z.remoteHandle!==""});if(O!==void 0){const W=ue.filter(z=>{var ce;return!((ce=t.getNode(z))!=null&&ce.memberships.some(Ie=>Ie.team===O))});if(W.length>0){I({type:"add-member",team:O,ids:W});return}if(a.ids.length===1&&((Y=t.getNode(a.clicked))==null?void 0:Y.remote)!==!0){const z=t.teamMemberIds(O),ce=Ss(t,O);ce.join("\0")!==z.join("\0")&&I({type:"reorder",team:O,ops:bn(z,ce)})}}if(a.rosterOrigin!==void 0&&O!==a.rosterOrigin){const W=a.ids.filter(z=>t.teamMemberIds(a.rosterOrigin).includes(z));W.length>0&&I({type:"remove-member",team:a.rosterOrigin,ids:W})}}function Ge(a){if(Ke===0&&ze(),X.isDialogOpen()){a.preventDefault();return}const h=a.target;if(X.isMenuOpen()){if(h!==null&&h.closest(".p-menu")!==null)return;X.closeMenu(),a.preventDefault();return}if(h!==null&&h.closest("button, input, textarea, select, .p-toolbar, .p-search, .p-lamp, .p-status, .p-legend")!==null)return;g=m.capture();const v=q(a);if(a.button===2){S={x:v.x,y:v.y,target:a.target,moved:!1},a.preventDefault();try{k.setPointerCapture(a.pointerId??0)}catch{}return}const F=h!==null?h.closest(".p-node"):null,O=h!==null?h.closest(".p-frame-head"):null;if((F!==null||O!==null)&&a.button===1){o={kind:"pan",last:v,moved:!1},a.preventDefault();try{k.setPointerCapture(a.pointerId??0)}catch{}return}const ue=h!==null?h.closest(".p-frame-handle"):null;if(p!==void 0){const Y=Oe.get(p),W=h!==null&&Y!==void 0&&(Y.contains(h)||Y===h),z=O!==null&&O.dataset.frame===p;!W&&!z&&R(void 0)}if(ue!==null&&a.button===0){const Y=ue.dataset.frame??"";R(Y);const W=t.getFrame(Y);if(W===void 0)return;o={kind:"frame-resize",name:Y,dir:ue.dataset.dir??"se",startRect:{...W},origin:mt(s,v.x,v.y),moved:!1},a.preventDefault();try{k.setPointerCapture(a.pointerId??0)}catch{}return}if(F!==null){if(a.button!==0)return;const Y=F.dataset.id??"",W=t.isSelected(Y);!W&&!a.shiftKey&&t.setSelection([Y]);const z=a.shiftKey||W?t.isSelected(Y)?t.selectedIds():[...t.selectedIds(),Y]:[Y],ce=un(new Map(t.allFrames()),mt(s,v.x,v.y));o={kind:"node",clicked:Y,ids:z,...ce&&w.has(ce)&&t.teamMemberIds(ce).includes(Y)?{rosterOrigin:ce}:{},last:mt(s,v.x,v.y),moved:!1,el:F},F.classList.add("dragging")}else if(O!==null){if(a.button!==0)return;const Y=O.dataset.frame??"";R(Y);const W=t.beginFrameDrag(Y);if(W===void 0)return;o={kind:"frame",name:Y,snap:W,origin:mt(s,v.x,v.y),moved:!1}}else if(a.button===1||a.button===0&&i)o={kind:"pan",last:v,moved:!1};else if(a.button===0)o={kind:"marquee",origin:v,last:v,additive:a.shiftKey},K.style.display="block",K.style.left=`${v.x}px`,K.style.top=`${v.y}px`,K.style.width="0px",K.style.height="0px";else return;a.preventDefault();try{k.setPointerCapture(a.pointerId??0)}catch{}}function Ze(a){const h=q(a);if(S!==null){const v=h.x-S.x,F=h.y-S.y;Math.hypot(v,F)>4&&(S.moved=!0,s=kt(dn(s,-v,-F)),S.x=h.x,S.y=h.y,Ve());return}if(o.kind==="node"){const v=mt(s,h.x,h.y),F=v.x-o.last.x,O=v.y-o.last.y;if(F===0&&O===0)return;o.moved=!0,o.last=v,t.dragNodes(o.ids,F,O);const ue=un(new Map(t.allFrames()),v),Y=o.ids.filter(z=>{const ce=t.getNode(z);return ce===void 0?!1:ce.remote!==!0||ce.remoteHandle!==void 0&&ce.remoteHandle!==""}),W=ue!==void 0&&Y.length>0;for(const[z,ce]of Oe)ce.classList.toggle("drop-target",W&&z===ue);Le()}else if(o.kind==="frame"){const v=mt(s,h.x,h.y),F=v.x-o.origin.x,O=v.y-o.origin.y;if(!o.moved&&F===0&&O===0)return;o.moved=!0,t.applyFrameDrag(o.snap,F,O),Le()}else if(o.kind==="frame-resize"){const v=mt(s,h.x,h.y),F=v.x-o.origin.x,O=v.y-o.origin.y;if(!o.moved&&F===0&&O===0)return;o.moved=!0;const ue=220,Y=120,W={...o.startRect};let{x:z,y:ce,w:Ie,h:_e}=W;o.dir.includes("e")&&(Ie=Math.max(ue,W.w+F)),o.dir.includes("s")&&(_e=Math.max(Y,W.h+O)),o.dir.includes("w")&&(Ie=Math.max(ue,W.w-F),z=W.x+(W.w-Ie)),o.dir.includes("n")&&(_e=Math.max(Y,W.h-O),ce=W.y+(W.h-_e)),t.setFrame(o.name,{x:Math.round(z),y:Math.round(ce),w:Math.round(Ie),h:Math.round(_e)}),Le()}else if(o.kind==="pan")s=dn(s,h.x-o.last.x,h.y-o.last.y),o.last=h,o.moved=!0,Ve();else if(o.kind==="marquee"){const v=Math.min(o.origin.x,h.x),F=Math.min(o.origin.y,h.y);K.style.left=`${v}px`,K.style.top=`${F}px`,K.style.width=`${Math.abs(h.x-o.origin.x)}px`,K.style.height=`${Math.abs(h.y-o.origin.y)}px`,o.last=h}}function dt(a){var h,v;if(S!==null){const F=S.moved,O=S.target,ue=S.x,Y=S.y;S=null,F?(C=!0,M()):O!==null&&X.contextMenuAt(ue,Y,O);return}if(o.kind==="node"){const F=o.clicked;if(o.moved)He(o,a),M();else if(a.shiftKey){const O=t.selectedIds();t.setSelection(O.includes(F)?O.filter(ue=>ue!==F):[...O,F])}else t.setSelection([F]),(h=e.onNodePick)==null||h.call(e,F);for(const O of Oe.values())O.classList.remove("drop-target");(v=o.el)==null||v.classList.remove("dragging"),Le()}else if(o.kind==="frame"||o.kind==="frame-resize")o.moved&&(Ut(t,new Set(x.keys()),o.name),M(),Le());else if(o.kind==="pan")o.moved&&M();else if(o.kind==="marquee"){const F=o.last,O=mt(s,Math.min(o.origin.x,F.x),Math.min(o.origin.y,F.y)),ue=mt(s,Math.max(o.origin.x,F.x),Math.max(o.origin.y,F.y));t.marqueeSelect({x:O.x,y:O.y,w:ue.x-O.x,h:ue.y-O.y},o.additive),K.style.display="none",Le()}o={kind:"none"},g!==void 0&&(m.commit(g),g=void 0);try{k.releasePointerCapture(a.pointerId??0)}catch{}}function Je(a){var v;for(const F of Oe.values())F.classList.remove("drop-target");o.kind==="node"&&((v=o.el)==null||v.classList.remove("dragging"));const h=o.kind==="pan"&&o.moved||(S==null?void 0:S.moved)===!0;K.style.display="none",S=null,o={kind:"none"},g!==void 0&&m.revert(g)&&Le(),h&&M(),g=void 0;try{k.releasePointerCapture(a.pointerId??0)}catch{}}function be(a){X.isMenuOpen()&&X.closeMenu();const h=q(a);if(a.shiftKey&&!a.ctrlKey){const v=a.deltaMode===1?16:1;s=kt(dn(s,(a.deltaX??0)*v,(a.deltaY??0)*v))}else{const v=a.deltaMode===1?16:1,F=Math.exp(-((a.deltaY??0)*v)*.0015);s=Bn(s,F,h.x,h.y)}a.preventDefault(),Ve(),M()}function Xe(a){ze(),s=Bn(s,a,Ke/2,ct/2),Ve(),M()}function ft(){m.undo()?(M(),Le()):H("info","没有可撤销的布局改动")}function St(){ze(),s=Kn(Wn(t.contentBounds(),t.allNodes()),Ke,ct,Xn(we,oe)),Ve(),M()}function Dt(a){var ue,Y,W,z,ce,Ie,_e;if(X.isDialogOpen()||((Y=(ue=a.target)==null?void 0:ue.closest)==null?void 0:Y.call(ue,".p-search"))!==null)return;if((a.ctrlKey||a.metaKey)&&a.key.toLowerCase()==="k"){a.preventDefault(),Re.focus();return}if((a.ctrlKey||a.metaKey)&&!a.shiftKey&&a.key.toLowerCase()==="z"){a.preventDefault(),ft();return}if(a.ctrlKey||a.metaKey)return;if(X.isMenuOpen()){a.key==="Escape"&&(X.closeMenu(),a.preventDefault());return}if(a.key===" "&&a.target===k){i=!0,a.preventDefault();return}const h=((z=(W=a.target)==null?void 0:W.closest)==null?void 0:z.call(W,".p-frame-head"))??null;if((a.key==="Enter"||a.key===" ")&&h!==null){a.preventDefault();const Me=h.getBoundingClientRect();X.contextMenuAt(Me.left+Me.width/2,Me.top+Me.height/2,h);return}if(a.key===" "&&((Ie=(ce=a.target)==null?void 0:ce.classList)!=null&&Ie.contains("p-node"))){const b=a.target.dataset.id??"",G=t.selectedIds();t.setSelection(G.includes(b)?G.filter(de=>de!==b):[...G,b]),Le(),a.preventDefault();return}if(a.key==="F10"&&a.shiftKey||a.key==="ContextMenu"){a.preventDefault();const Me=document.activeElement??null,b=((_e=Me==null?void 0:Me.getBoundingClientRect)==null?void 0:_e.call(Me))??{left:0,top:0,width:0,height:0};X.contextMenuAt(b.left+b.width/2,b.top+b.height/2,Me);return}if(a.key==="Delete"||a.key==="Backspace"){a.preventDefault(),yo();return}if(a.altKey&&(a.key==="ArrowUp"||a.key==="ArrowDown")){a.preventDefault(),wo(a.key==="ArrowUp");return}if(a.key==="g"||a.key==="G"){X.startCreateFromSelection();return}if(a.key==="0"){St();return}if(a.key==="="||a.key==="+"){Xe(1.2);return}if(a.key==="-"){Xe(1/1.2);return}if(a.key==="Escape"){if(X.isMenuOpen()){X.closeMenu(),Le();return}t.setSelection([]),Le();return}const v=a.shiftKey?40:8,O={ArrowLeft:[-v,0],ArrowRight:[v,0],ArrowUp:[0,-v],ArrowDown:[0,v]}[a.key];if(O!==void 0){a.preventDefault();const Me=t.selectedIds();if(Me.length>0){const b=m.capture();t.nudge(Me,O[0],O[1]),m.commit(b),Le(),M()}}}function yo(){var F,O,ue;const a=document.activeElement,h=((F=a==null?void 0:a.closest)==null?void 0:F.call(a,".p-frame-head"))??null,v=((O=a==null?void 0:a.closest)==null?void 0:O.call(a,".p-node"))??null;if(h!==null){I({type:"remove-team",name:h.dataset.frame??""});return}if(v!==null){const Y=v.dataset.id??"",W=((ue=t.getNode(Y))==null?void 0:ue.memberships.map(z=>z.team))??[];if(W.length===0){H("info","该节点未加入任何团队");return}if(W.length===1){I({type:"remove-member",team:W[0],ids:[Y]});return}X.openMenu(window.innerWidth/2,window.innerHeight/2,{kind:"node",id:Y},"leave",v);return}H("info","焦点不在节点或团队框上")}function wo(a){var Ie,_e;const h=document.activeElement,v=((Ie=h==null?void 0:h.closest)==null?void 0:Ie.call(h,".p-node"))??null;if(v===null)return;const F=v.dataset.id??"",O=((_e=t.getNode(F))==null?void 0:_e.memberships)??[];if(O.length!==1)return;const ue=O[0].team,Y=t.teamMemberIds(ue),W=Y.indexOf(F),z=a?Math.max(0,W-1):Math.min(Y.length-1,W+1);if(z===W)return;const ce=[...Y];ce.splice(W,1),ce.splice(z,0,F),I({type:"reorder",team:ue,ops:bn(Y,ce)})}function $n(a){a.key===" "&&(i=!1)}k.addEventListener("pointerdown",a=>Ge(a),$),k.addEventListener("pointermove",a=>Ze(a),$),k.addEventListener("pointerup",a=>dt(a),$),k.addEventListener("pointercancel",a=>Je(a),$),k.addEventListener("wheel",a=>be(a),{...$,passive:!1}),k.addEventListener("keydown",a=>Dt(a),$),k.addEventListener("keyup",a=>$n(a),$),k.addEventListener("contextmenu",a=>{var v,F;const h=a;if(((F=(v=h.target)==null?void 0:v.closest)==null?void 0:F.call(v,"input, textarea, .p-search"))==null){if(h.preventDefault(),C){C=!1;return}X.contextMenuAt(h.clientX,h.clientY,h.target)}},$);let Ht=[];function xo(a){var Me;Ht=a.teams,w=new Set([...a.teams.filter(b=>b.kind==="roster").map(b=>b.name),...[...w].filter(b=>Te.has(b))]),a.peers,l.setInFlight(a.inFlight??[]),se=a.sessions,X.setUnjoined(a.sessions.filter(b=>b.joined!==!0&&!b.id.startsWith("peer-")));const h=new Map;for(const b of a.teams)for(let G=0;G<b.members.length;G++){const de=b.members[G].id,Fe=h.get(de)??[];Fe.push({team:b.name,index:G}),h.set(de,Fe)}ee=new Set(h.keys());const v=new Set,F=b=>{const G=h.get(b)??[];if(Te.size===0)return G;const de=G.filter(Se=>!Te.has(Se.team)),Fe=[];for(const[Se]of Te){const ke=t.teamMemberIds(Se).indexOf(b);ke>=0&&Fe.push({team:Se,index:ke})}return[...de,...Fe]};let O;if(n===void 0&&!t.allNodes().some(b=>b.remote!==!0)){const b=a.sessions.filter(G=>{var de;return G.joined===!0&&(F(G.id).length>0||(((de=G.teams)==null?void 0:de.length)??0)>0)}).map(G=>G.id);ze(),O=ss(a.teams,b,Ke>0?Ke:void 0)}for(const b of a.sessions){if(b.joined!==!0)continue;const G=F(b.id);if(!(G.length===0&&(b.teams===void 0||b.teams.length===0)))if(v.add(b.id),t.getNode(b.id)!==void 0)t.upsertNode({id:b.id,x:t.getNode(b.id).x,y:t.getNode(b.id).y,label:b.label,team:b.team,name:b.name,description:b.description,live:b.live!==!1,memberships:G,...b.teams!==void 0&&b.teams.length>0?{teams:b.teams}:{}});else{const de=n==null?void 0:n.nodes[b.id];let Fe,Se;if(de!==void 0)Fe=de.x,Se=de.y;else{const me=(O==null?void 0:O.get(b.id))??Nn(b.id);Fe=me.x,Se=me.y}t.upsertNode({id:b.id,x:Fe,y:Se,label:b.label,team:b.team,name:b.name,description:b.description,live:b.live!==!1,memberships:G,...b.teams!==void 0&&b.teams.length>0?{teams:b.teams}:{}})}}for(const b of t.nodeIds())!v.has(b)&&!b.startsWith("peer-")&&!b.startsWith("member-")&&t.removeNode(b);const ue=new Set;A=ds(a.remoteTeams??[]),he=new Map([...A].flatMap(([b,G])=>G.map(de=>[de.team,b]))),L=new Map(a.sessions.map(b=>[b.id,{status:b.status,queued:b.queued}])),D=Qn(a),Z.clear();for(const b of a.peers??[])Z.set(rt(b.url),b.score),B.set(rt(b.url),{link:b.link,verified:b.verified});if(a.peers!==void 0){const b=t.contentBounds(),G=hs(a.peers,b);a.peers.forEach((de,Fe)=>{var At,vt,Mn,Sn;const Se=ls(de.url);ue.add(Se);const me=n==null?void 0:n.nodes[Se],ke=t.getNode(Se),Qe=ke!==void 0?{x:ke.x,y:ke.y}:me!==void 0?{x:me.x,y:me.y}:{x:((At=G[Fe])==null?void 0:At.x)??200,y:((vt=G[Fe])==null?void 0:vt.y)??0},tt=rt(de.url),gt=(Sn=(Mn=A.get(tt))==null?void 0:Mn.find(So=>So.team.includes("/")))==null?void 0:Sn.team;t.upsertNode({id:Se,x:Qe.x,y:Qe.y,label:de.url,team:"",name:de.url,peerUrl:de.url,remoteHandle:gt,live:!0,remote:!0,memberships:[]}),t.upsertScore(Se,de.score)})}for(const b of t.nodeIds())b.startsWith("peer-")&&!ue.has(b)&&t.removeNode(b);const Y=new Set;for(const[b,G]of A){const de=t.allNodes().find(me=>me.remote===!0&&rt(me.peerUrl??"")===b&&!me.id.startsWith("member-")),Fe=((de==null?void 0:de.x)??400)+190;let Se=(de==null?void 0:de.y)??0;for(const me of G){if(!me.team.includes("/"))continue;const ke=`member-${me.team.replace(/[^a-z0-9-]/gi,"-")}`;if(Y.has(ke))continue;Y.add(ke);const Qe=n==null?void 0:n.nodes[ke],tt=t.getNode(ke),gt=tt!==void 0?{x:tt.x,y:tt.y}:Qe!==void 0?{x:Qe.x,y:Qe.y}:{x:Fe,y:Se};Se+=92,t.upsertNode({id:ke,x:gt.x,y:gt.y,label:me.team,team:me.team,name:me.name!==void 0&&me.name!==""?me.name:me.team,remoteHandle:me.team,live:!0,remote:!0,memberships:[]})}}for(const b of t.nodeIds())b.startsWith("member-")&&!Y.has(b)&&t.removeNode(b);const W=new Map;for(const b of t.allNodes())b.remote!==!0||b.remoteHandle===void 0||b.remoteHandle===""||(!W.has(b.remoteHandle)||b.id.startsWith("member-"))&&W.set(b.remoteHandle,b.id);for(const b of a.teams){if(Te.has(b.name))continue;const G=[];for(const Se of b.members){const me=W.get(Se.id)??Se.id;t.getNode(me)!==void 0&&G.push(me)}const de=[...t.teamMemberIds(b.name)].sort().join("|"),Fe=[...G].sort().join("|");de!==Fe&&t.setTeamMembers(b.name,G)}const z=new Map,ce=x;if(x=z,a.peerOrg!==void 0){let b=0;const G=new Set(a.teams.map(de=>de.name));N.sweep(a.peerOrg);for(const de of a.peerOrg){const Fe=new Set((a.remoteTeams??[]).map(me=>me.team)),Se=xs(a.sessions,Fe);for(const me of de.org){if(me.name===""||G.has(me.name)||N.hides(me.name,de.url))continue;const ke=me.members.map(tt=>Cs(tt,Se,a.remoteTeams,de.url)).filter(tt=>t.getNode(tt)!==void 0),Qe=(Me=n==null?void 0:n.frames)==null?void 0:Me[me.name];t.getFrame(me.name)===void 0&&t.setFrame(me.name,Qe!==void 0?{x:Qe.x,y:Qe.y,w:Qe.w,h:Qe.h}:{x:200+b%4*280,y:940+Math.floor(b/4)*160,w:250,h:130}),t.setTeamMembers(me.name,ke),z.set(me.name,de.url),b+=1}}}for(const[b,G]of ce)z.has(b)||t.removeFrame(b);const Ie=new Map;for(const b of t.allNodes())b.remote===!0&&b.remoteHandle!==void 0&&b.remoteHandle!==""&&Ie.set(b.remoteHandle,b.id);const _e=po(a.teams);for(const b of a.teams){if(t.getFrame(b.name)!==void 0||Te.has(b.name))continue;const G=n==null?void 0:n.frames[b.name];if(G!==void 0){t.setFrame(b.name,{...G});continue}const de=[],Fe=[];for(const me of b.members){const ke=t.getNode(Ie.get(me.id)??me.id);ke!==void 0&&(Fe.push(at(ke)),_e.get(ke.id)===b.name&&de.push(at(ke)))}const Se=de.length>0?de:Fe;Se.length>0&&t.setFrame(b.name,Cn(Se))}for(const[b]of t.allFrames())Te.has(b)||!a.teams.some(G=>G.name===b)&&!z.has(b)&&t.removeFrame(b);if(ve.refresh(),Be(a),!d&&o.kind==="none"&&t.nodeIds().length>0){d=!0;const b=m.capture();Ut(t,new Set(x.keys())),m.commit(b)}c&&o.kind==="none"&&t.nodeIds().length>0&&(ze(),Ke>0&&ct>0&&(c=!1,s=Kn(Wn(t.contentBounds(),t.allNodes()),Ke,ct,Xn(we,oe)))),Le()}function Nn(a){return ho(a,t.allNodes().filter(h=>h.remote!==!0))}function Co(a){const h=mo(a);if(h===void 0)return;n=h;const v=e.viewportStore;if(v===void 0)c=!1,o.kind==="none"&&(s=kt({...h.viewport}));else if(!u&&o.kind==="none"){u=!0;const F=v.get(E());F!=null&&Number.isFinite(F.x)&&Number.isFinite(F.y)&&Number.isFinite(F.scale)?(s=kt({x:F.x,y:F.y,scale:F.scale}),c=!1):E()==="wide"&&(s=kt({...h.viewport}),c=!1)}r=-1,Le()}function ko(){return es(s,t.positions(),t.frameRects())}function Eo(a,h){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 v=a==="pending"?"布局待保存…":a==="saved"?`布局已保存 ${h??""}`.trimEnd():a==="error"?"保存失败 · 回车重试":"布局";Q.textContent=v}function $o(){k.style.display="block",ze(),Ve(),k.focus()}function No(){k.style.display="none"}function Mo(){fe.abort();for(const a of ne)clearTimeout(a)}return{root:k,reconcile:xo,activate:$o,deactivate:No,adoptExternalLayout:Co,snapshotDoc:ko,setLamp:Eo,notice:H,destroy:Mo,seam:{pointerDown:Ge,pointerMove:Ze,pointerUp:dt,pointerCancel:Je,wheel:be,key:Dt,keyUp:$n,contextMenu(a){a.preventDefault(),X.contextMenuAt(a.clientX,a.clientY,a.target)}}}}const fi=800;function pi(e){let t,n=!1,s=!1,o=!1,i="idle";function r(g){g!==i&&(i=g,e.onLamp(g))}function c(){t!==void 0&&(t(),t=void 0)}function d(){c(),t=e.schedule(()=>{t=void 0,m(!1)},fi)}async function m(g){if(n){s=!0;return}n=!0,c();const u=e.snapshot();let E;try{E=JSON.stringify(u)}catch{n=!1,r("error"),e.onHttpError("layout document is not JSON-serializable");return}try{const M=await e.send(u,{keepalive:g});if(M===null||typeof M!="object"||M.ok!==!0){r("error");const J=M!==null&&typeof M=="object"&&typeof M.error=="string"?M.error:"layout save refused";e.onHttpError(`layout save: ${J}`)}else JSON.stringify(e.snapshot())===E&&(e.onAdopt(M.layout),r("saved"))}catch(M){r("error"),e.onHttpError(`layout save unreachable: ${String((M==null?void 0:M.message)??M).slice(0,80)}`)}if(n=!1,i==="error"){o=!1;return}if(o){o=!1,m(!0);return}s&&(s=!1,r("pending"),d())}return{markDirty(){if(s=!1,r("pending"),n){s=!0;return}d()},retry(){i!=="error"||n||(r("pending"),m(!1))},flush(){if(n){o=!0,s=!0;return}c(),m(!0)},isBusy(){return n},dispose(){c()}}}function Zn(e){return e!=null&&typeof e.error=="string"?e.error:void 0}function hi(e){const t=new Map;let n=0;function s(r,c){n+=1;const d=t.get(r)??Promise.resolve(),m=async()=>{try{return await c()}finally{n-=1}},g=d.then(m,m);return t.set(r,g.then(()=>{},()=>{})),g}async function o(r){var fe,ne,S,C;let c;try{c=await e.send(r)}catch($){const k=String(($==null?void 0:$.message)??$).slice(0,80);return e.onNotice("error",`画布不可达:${k}`),!1}if(c.status>=400)return e.onNotice("error",Zn(c.body)??`HTTP ${c.status}`),!1;if(((fe=c.body)==null?void 0:fe.ok)===!0)return!0;const d=c.body!=null&&typeof c.body=="object"?Zn(c.body):void 0;if(d!==void 0)return e.onNotice("error",d),!1;const m=String(r.name??""),g=String(r.id??""),u=(ne=c.body)==null?void 0:ne.members,E=(S=c.body)==null?void 0:S.teams,M=Array.isArray(u)&&u.every($=>typeof $=="string"),J=Array.isArray(E)&&E.every($=>typeof $=="string");return((C=c.body)==null?void 0:C.ok)===!1&&(r.action==="add-member"&&M&&u.includes(g)||r.action==="remove-member"&&M&&!u.includes(g)||r.action==="remove"&&J&&!E.includes(m))?!0:(e.onNotice("error","画布操作未确认:"+String(r.action)+"(可能队伍/成员已达上限,请重试)"),!1)}async function i(r,c){for(const d of c)if(!await o({...r,id:d}))return!1;return!0}return{createTeam(r,c){return s(r,async()=>{if(!await o({action:"create",name:r}))return!1;for(let d=0;d<c.length;d++)if(!await o({action:"add-member",name:r,id:c[d]}))return!1;return!0})},addMembers(r,c){return s(r,()=>i({action:"add-member",name:r},c))},removeMembers(r,c){return s(r,()=>i({action:"remove-member",name:r},c))},runRosterOps(r,c){return s(r,async()=>{for(const d of c){const m=d.op==="remove"?{action:"remove-member",name:r,id:d.id}:{action:"add-member",name:r,id:d.id};if(!await o(m))return!1}return!0})},removeTeam(r){return s(r,()=>o({action:"remove",name:r}))},hasPending(){return n>0}}}const vo=document.getElementById("app"),bi=(()=>{try{return window.sessionStorage.getItem("dsh_a2a_key")??""}catch{return""}})(),gn=window.__DSH_A2A_KEY__??bi,Ue=(e,t={})=>fetch(e,{...t,headers:{...t.headers??{},...gn!==""?{"X-API-Key":gn}:{}}});gn===""&&Ue("/__dsh_a2a/owner-settings").then(e=>{if(e.status!==401)return;const t=document.createElement("div");t.className="nexus-keygate",t.style.cssText="position:fixed;inset:0;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:10px;background:#fff;z-index:9999;font:14px/1.5 system-ui,sans-serif;color:#000";const 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 c=s.value.trim();c!==""&&fetch("/__dsh_a2a/owner-settings",{headers:{"X-API-Key":c}}).then(d=>{if(d.status===401){i.textContent="密钥不对,再试一次";return}try{window.sessionStorage.setItem("dsh_a2a_key",c)}catch{}window.location.reload()})};o.addEventListener("click",r),s.addEventListener("keydown",c=>{c.key==="Enter"&&r()}),t.append(n,s,o,i),document.body.appendChild(t)});const Ot=document.createElement("div");Ot.className="nexus-fault";vo.appendChild(Ot);const{fault:vn,clear:gi}=Io({show(e){Ot.textContent=e,Ot.style.display="block"},hide(){Ot.style.display="none"}},e=>console.error(e));let Gt;const eo="dsh-a2a.viewport.",vi={get(e){try{const t=window.localStorage.getItem(eo+e);return t===null?void 0:JSON.parse(t)}catch{return}},set(e,t){try{window.localStorage.setItem(eo+e,JSON.stringify({x:t.x,y:t.y,scale:t.scale}))}catch{}}},ot=mi({viewportStore:vi,onDirty:()=>nn.markDirty(),onLampClick:()=>nn.retry(),onNodePick:e=>{Gt==null||Gt(e)},onCanvasAction:async e=>{const t=await wi(e);return rn(),t}}),nn=pi({snapshot:()=>ot.snapshotDoc(),send:(e,t)=>Ue("/__dsh_a2a/canvas-layout",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"save",layout:e}),cache:"no-store",keepalive:t.keepalive}).then(async n=>await n.json()),schedule:(e,t)=>{const n=setTimeout(e,t);return()=>{clearTimeout(n)}},now:Date.now,onLamp:e=>{yn=e;const t=new Date,n=String(t.getHours()).padStart(2,"0")+":"+String(t.getMinutes()).padStart(2,"0");ot.setLamp(e,n)},onAdopt:e=>{ot.adoptExternalLayout(e)},onHttpError:e=>vn(e)});window.addEventListener("pagehide",()=>nn.flush());const Tt=hi({send:async e=>{const t=await Ue("/__dsh_a2a/canvas",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),cache:"no-store"});return{status:t.status,body:await t.json()}},onNotice:(e,t)=>ot.notice(e,t)});async function to(e,t,n,s){const o=await Ue("/__dsh_a2a/fleet-canvas-op",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({peer:e,op:t,name:n,...s!==void 0?{id:s}:{}}),cache:"no-store"}).catch(()=>{}),i=o!==void 0?await o.json().catch(()=>{}):void 0;return(i==null?void 0:i.ok)===!0&&t==="remove"&&i.removed===!1&&ot.notice("info",`属主那边已没有「${n}」,无需解散`),(i==null?void 0:i.ok)===!0?!0:(ot.notice("error",`跨主机团队操作失败:${String((i==null?void 0:i.error)??"对端无响应")}`),!1)}async function yi(e,t){const n=async s=>{const o=await Ue("/__dsh_a2a/roster-op",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:t,...s})}).catch(()=>{}),i=o!==void 0?await o.json().catch(()=>{}):void 0;return o!=null&&o.ok&&(i==null?void 0:i.ok)===!0?!0:(ot.notice("error",`roster 操作失败:${String((i==null?void 0:i.error)??(o?`HTTP ${o.status}`:"无响应"))}`),!1)};if(e.type==="create-team")return n({op:"create",ids:e.ids});if(e.type==="remove-team")return n({op:"dissolve"});if(e.type==="add-member"||e.type==="remove-member"){for(const s of e.ids)if(!await n({op:e.type,id:s}))return!1;return!0}return ot.notice("error","roster 不支持该操作"),!1}function wi(e){if((e.type==="add-member"||e.type==="remove-member")&&e.fleetPeer!==void 0){const t=e.fleetPeer;return(async()=>{for(const n of e.ids)if(!await to(t,e.type,e.team,n))return!1;return!0})()}if(e.type==="remove-team"&&e.fleetPeer!==void 0)return to(e.fleetPeer,"remove",e.name);if(e.roster===!0){const t=go(Pt(e));return t!==void 0?yi(e,t):(ot.notice("error","无效的 roster 框名"),Promise.resolve(!1))}switch(e.type){case"create-team":return Tt.createTeam(e.name,e.ids,e.created);case"add-member":return Tt.addMembers(e.team,e.ids);case"remove-member":return Tt.removeMembers(e.team,e.ids);case"remove-team":return Tt.removeTeam(e.name);case"reorder":return Tt.runRosterOps(e.team,e.ops);case"join-network":case"leave-network":return xi(e.type==="join-network"?"join":"leave",e.id)}}async function xi(e,t){const n=await Ue(`/__dsh_a2a/${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:t}),cache:"no-store"}).catch(()=>{});return n!==void 0&&n.ok}let yn="idle",mn=new Set,no=0,on=!1,oo,fn=!1;async function Ci(){const e=await Ue("/__dsh_a2a/canvas-layout",{cache:"no-store"});if(!e.ok)throw new Error(`/__dsh_a2a/canvas-layout ${e.status}`);return(await e.json()).layout??null}const sn=Qo({now:()=>Date.now(),async ownerSettingsRead(){try{return await(await Ue("/__dsh_a2a/owner-settings")).json()}catch{return{ok:!1,error:"unreachable"}}},async ownerSettingsWrite(e){try{return await(await Ue("/__dsh_a2a/owner-settings",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})).json()}catch{return{ok:!1,error:"unreachable"}}},async abandon(e,t){try{return(await Ue("/__dsh_a2a/tasks/abandon",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({task_id:e,reason:t})})).ok}catch{return!1}},copy(e){var t;(t=navigator.clipboard)==null||t.writeText(e).catch(()=>{})},async cliHomeOptions(e,t){try{const n=await Ue("/__dsh_a2a/canvas",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({action:"cli-home-options",name:e,id:t})}),s=await n.json();return{...s,ok:n.ok&&s.ok===!0}}catch(n){return{ok:!1,error:String(n)}}},async canvasOp(e,t,n,s){try{const o=await Ue("/__dsh_a2a/canvas",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({action:e,name:t,id:n,...s===void 0?{}:{home:s}})}),i=await o.json().catch(()=>({}));return o.ok&&i.ok!==!1?!0:(console.warn(`canvas ${e} ${t}: ${i.error??`HTTP ${o.status}`}`),!1)}catch{return!1}},async dispatchQuick(e,t){try{const n=await Ue("/__dsh_a2a/dispatch",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({team:e,message:t})}),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(e){try{const t=await Ue(`/__dsh_a2a/session-log?id=${encodeURIComponent(e)}`),n=await t.json().catch(()=>({}));return{ok:t.ok&&n.ok===!0,messages:n.messages,error:n.error??(t.ok?void 0:`HTTP ${t.status}`)}}catch(t){return{ok:!1,error:t instanceof Error?t.message:String(t)}}},async sessionLogList(){try{const e=await Ue("/__dsh_a2a/session-log"),t=await e.json().catch(()=>({}));return{ok:e.ok&&t.ok===!0,sessions:t.sessions,count:typeof t.count=="number"?t.count:void 0,error:t.error??(e.ok?void 0:`HTTP ${e.status}`)}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}},async remoteSessionLog(e){try{const t=new URLSearchParams;e.team!==void 0&&t.set("team",e.team),e.peer!==void 0&&t.set("peer",e.peer),e.id!==void 0&&t.set("id",e.id),e.limit!==void 0&&t.set("limit",String(e.limit));const n=await Ue(`/__dsh_a2a/remote-session-log?${t.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(t){return{ok:!1,error:t instanceof Error?t.message:String(t)}}},board:{root:ot.root,activate:()=>ot.activate(),deactivate:()=>ot.deactivate(),available:()=>on}});vo.appendChild(sn.root);Gt=e=>{sn.openNodeChat(e)};if(new URLSearchParams(window.location.search).get("mode")==="plan"){const e=window.setInterval(()=>{on&&(sn.selectTab("board"),window.clearInterval(e))},300);window.setTimeout(()=>window.clearInterval(e),3e4)}async function rn(){var e,t;try{const n=await Ue("/__dsh_a2a/state",{cache:"no-store"});if(!n.ok)throw new Error(`/__dsh_a2a/state ${n.status}`);const s=await n.json();if(Date.now()-no>=15e3){no=Date.now();try{const u=await Ue("/__dsh_a2a/nodes",{cache:"no-store"});if(!u.ok)throw new Error(`nodes ${u.status}`);const E=await u.json();mn=new Set((E.bindings??[]).filter(M=>M.mounted!==null&&M.effective!==null&&(M.effective.core===!1||M.effective.mutable===!1)).map(M=>M.session))}catch{mn.clear()}}const o={...s,sessions:(s.sessions??[]).map(u=>({...u,...mn.has(u.id)?{nodePromptMissing:!0}:{}}))};if(gi(),on=s.canvas!==void 0,sn.update(o),on)try{const u=await Ci(),E=JSON.stringify(u??null);E!==oo&&(oo=E,(yn==="idle"||yn==="saved")&&!nn.isBusy()&&ot.adoptExternalLayout(u)),fn=!0}catch(u){if(!fn){vn(`canvas layout 获取失败:${String(u)}`);return}}else fn=!0;const i=(s.sessions??[]).map(u=>({...u,joined:u.joined===!0})),r=[...((e=s.canvas)==null?void 0:e.teams)??[],...Ls(((t=s.registry)==null?void 0:t.teams)??[],s.zone??"")],c=(s.peers??[]).filter(u=>u!==null&&typeof u=="object"&&typeof u.url=="string"),d=(s.inFlight??[]).filter(u=>u!==null&&typeof u=="object"&&typeof u.team=="string"&&typeof u.peer=="string"&&Number.isFinite(u.startedAt)),m=(s.remote??[]).filter(u=>u!==null&&typeof u=="object"&&typeof u.team=="string"&&typeof u.via=="string").map(u=>({team:u.team,name:u.name,via:u.via,workspace:u.workspace,...u.unreachable===!0?{unreachable:!0}:{},...typeof u.origin=="string"&&u.origin!==""?{origin:u.origin}:{},...Array.isArray(u.teams)&&u.teams.length>0?{teams:u.teams.filter(E=>typeof E=="string"&&E!=="")}:{}})),g=(s.peerOrg??[]).filter(u=>u!==null&&typeof u=="object").filter(u=>typeof u.url=="string"&&Array.isArray(u.org)).map(u=>({url:u.url,...u.unreachable===!0?{unreachable:!0}:{},org:u.org.filter(E=>E!==null&&typeof E=="object").filter(E=>typeof E.team=="string"&&E.team!=="").map(E=>({name:typeof E.name=="string"?E.name:"",team:E.team,members:Array.isArray(E.members)?E.members.filter(M=>typeof M=="string"):[]}))}));ot.reconcile({sessions:i,teams:r,peerCount:c.length,peers:c,inFlight:d,remoteTeams:m,peerOrg:g})}catch(n){vn(`state 轮询失败:${String(n)}`)}}rn();window.setInterval(()=>{document.hidden||rn()},3e3);document.addEventListener("visibilitychange",()=>{document.hidden||rn()});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
#dsh-plan *,#dsh-plan *:before,#dsh-plan *:after{box-sizing:border-box}#dsh-plan{--uupm-ink-0:var(--n-ink,#dde3f0);--uupm-ink-1:var(--n-ink-muted,#7a86a0);--uupm-bg-0:var(--n-bg,#060a12);--uupm-bg-1:var(--n-panel,#0d1322);--uupm-bg-2:var(--n-raised,#131b2e);--uupm-accent:var(--n-accent,#9673f7);--uupm-live:var(--n-live,#4ade80);--uupm-cold:var(--n-cold,#7a86a0);--uupm-edge-member:var(--n-canvas,#22d3ee);--uupm-warn:var(--n-act,#f59e0b);--uupm-error:var(--n-danger,#f87171);--uupm-indigo:var(--n-federal,#6366f1);--uupm-wash-5:color-mix(in srgb,var(--uupm-accent) 5%,transparent);--uupm-wash-8:color-mix(in srgb,var(--uupm-accent) 8%,transparent);--uupm-wash-12:color-mix(in srgb,var(--uupm-accent) 12%,transparent);--uupm-wash-15:color-mix(in srgb,var(--uupm-accent) 15%,transparent);--uupm-wash-18:color-mix(in srgb,var(--uupm-accent) 18%,transparent);--surface:var(--uupm-bg-1);--ink:var(--uupm-ink-0);--ink-muted:var(--uupm-ink-1);--accent:var(--uupm-accent);--edge-live:var(--uupm-live);--edge-cold:var(--uupm-cold);--federal:var(--uupm-indigo);--card-bg:var(--surface);--card-line:var(--n-card-line,#5c6680);--card-line-hover:var(--uupm-ink-1);--toolbar-bg:color-mix(in srgb,var(--uupm-bg-1) 92%,transparent);--grid-dot:color-mix(in srgb,var(--uupm-ink-1) 22%,transparent);--scrim:color-mix(in srgb,var(--uupm-bg-0) 60%,transparent);--error-ink:var(--n-error-ink,#fecaca);--error-panel:var(--n-error-panel,#2a0d10f2)}#dsh-plan{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden;background:var(--uupm-bg-0);color:var(--ink);font-size:13px;line-height:1.5;outline:none}#dsh-plan .mono{font-family:ui-monospace,Cascadia,Consolas,monospace}#dsh-plan:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}#dsh-plan .p-grid{position:absolute;top:0;right:0;bottom:0;left:0;z-index:0;pointer-events:none;background-image:radial-gradient(circle,var(--grid-dot) 1px,transparent 1px);background-size:24px 24px;background-position:0 0}#dsh-plan .p-world{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;transform-origin:0 0}#dsh-plan .p-layer{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}#dsh-plan .p-edges{position:absolute;overflow:visible;width:100%;height:100%;pointer-events:none}#dsh-plan .p-frame{pointer-events:none}#dsh-plan .p-frame-head,#dsh-plan .p-node{pointer-events:auto}#dsh-plan .e-member{stroke:var(--uupm-edge-member);stroke-opacity:.38;stroke-width:1.5}#dsh-plan .e-member.dashed{stroke-dasharray:3 4}#dsh-plan .p-frame{--frame-ink:var(--frame-line,#8B5CF6)}@media (prefers-color-scheme: light){#dsh-plan .p-frame{--frame-ink:color-mix(in srgb,var(--frame-line,#8B5CF6) 72%,black)}}#dsh-plan .p-frame{position:absolute;border:1px solid var(--frame-ink);border-radius:10px;background:var(--frame-bg,var(--uupm-wash-5));min-width:120px;min-height:60px}#dsh-plan .p-frame-head{position:absolute;top:-13px;left:50%;transform:translate(-50%);height:24px;padding:0 10px;border-radius:6px;display:flex;gap:8px;align-items:center;background:var(--uupm-bg-2);border:1px solid var(--frame-ink);font-size:12px;font-weight:600;letter-spacing:.02em;white-space:nowrap;cursor:grab}#dsh-plan .p-frame-head:active{cursor:grabbing}#dsh-plan .p-frame-head:hover{border-color:var(--card-line-hover)}#dsh-plan .p-frame-head .cnt{color:var(--ink-muted);font-weight:400}#dsh-plan .p-frame-head .route{font-size:10.5px;color:var(--ink-muted)}#dsh-plan .p-frame.is-mirror{border-style:dashed}#dsh-plan .p-frame.is-roster{border-style:double;border-width:3px}#dsh-plan .p-frame.is-roster .p-frame-head{border-style:dashed}#dsh-plan .p-frame.is-syncing .p-frame-head .route{color:var(--accent)}#dsh-plan .p-frame.is-unreachable{opacity:.76;border-style:dashed}#dsh-plan .p-frame-unreachable{position:absolute;left:8px;top:20px;max-width:calc(100% - 16px);color:var(--uupm-error);font-size:11px;pointer-events:none}#dsh-plan .p-node.remote.is-unreachable{opacity:.72;border-left-color:var(--uupm-error)}#dsh-plan .p-node.remote.is-unreachable .sub{color:var(--uupm-error)}#dsh-plan .p-node{position:absolute;width:172px;height:56px;padding:8px 26px 8px 14px;background:var(--card-bg);border:1px solid var(--card-line);border-left:3px solid var(--edge-live);border-radius:8px;cursor:grab;-webkit-user-select:none;user-select:none;transition:border-color .12s cubic-bezier(.2,0,0,1),transform .12s cubic-bezier(.2,0,0,1)}#dsh-plan .p-node:hover{border-color:var(--card-line-hover)}#dsh-plan .p-node:active{cursor:grabbing}#dsh-plan .p-node:focus-visible{outline:2px solid var(--accent);outline-offset:2px}#dsh-plan .p-node.selected{outline:2px solid var(--accent);outline-offset:1px}#dsh-plan .p-node.dragging{transform:scale(1.02);border-color:var(--accent)}#dsh-plan .p-node.cold{border-left-color:var(--edge-cold)}#dsh-plan .p-node .nm{font-weight:600;display:flex;align-items:center;gap:7px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#dsh-plan .p-node .nm-text{min-width:0;overflow:hidden;white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;line-height:1.25}#dsh-plan .p-node.remote .nm-text{overflow-wrap:anywhere}#dsh-plan .p-node .dot{width:8px;height:8px;border-radius:50%;background:var(--edge-live);flex:none}#dsh-plan .p-node.cold .dot{background:transparent;border:1.5px solid var(--edge-cold)}#dsh-plan .p-node .sub-row{display:flex;align-items:baseline;gap:6px;margin-top:2px;min-width:0}#dsh-plan .p-node .sub-row .sub{flex:1 1 auto;min-width:0;margin-top:0}#dsh-plan .p-node .work{flex:none;font-size:10.5px;font-weight:500;color:var(--ink-muted);white-space:nowrap}#dsh-plan .p-node .work:empty{display:none}#dsh-plan .p-node.is-working .work{color:var(--edge-live)}#dsh-plan .p-node.is-working .dot{animation:p-working 1.4s ease-in-out infinite}@keyframes p-working{0%,to{box-shadow:0 0 color-mix(in srgb,var(--edge-live) 55%,transparent)}50%{box-shadow:0 0 0 4px transparent}}@media (prefers-reduced-motion: reduce){#dsh-plan .p-node.is-working .dot{animation:none}}#dsh-plan .p-node .sub{font-size:11px;color:var(--ink-muted);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#dsh-plan .p-node.pulse{box-shadow:0 0 0 2px var(--accent),0 0 14px 4px var(--uupm-wash-15);border-color:var(--accent)}#dsh-plan .p-search{position:relative}#dsh-plan .p-search-input{width:170px;min-height:28px;padding:2px 8px;font-size:12px;background:transparent;color:var(--ink);border:1px solid var(--card-line);border-radius:6px}#dsh-plan .p-search-input:focus-visible{outline:2px solid var(--accent);outline-offset:1px}#dsh-plan .p-search-list{position:absolute;top:100%;left:0;margin-top:4px;display:none;min-width:240px;max-height:220px;overflow:auto;z-index:9;background:var(--toolbar-bg);border:1px solid var(--card-line);border-radius:6px}#dsh-plan .p-search-hit{padding:5px 10px;font-size:12px;color:var(--ink);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}#dsh-plan .p-search-hit:hover,#dsh-plan .p-search-hit.active{background:var(--uupm-wash-15)}#dsh-plan .p-node .prio{position:absolute;top:6px;right:8px;font-size:10px;color:var(--ink-muted);border:1px solid var(--card-line);border-radius:4px;padding:0 5px}#dsh-plan .p-marquee{position:absolute;z-index:2;display:none;pointer-events:none;border:1px solid var(--accent);background:var(--uupm-wash-8)}#dsh-plan .p-toolbar{position:absolute;top:16px;left:16px;z-index:3;display:flex;gap:6px;align-items:center;background:var(--toolbar-bg);border:1px solid var(--card-line);border-radius:8px;padding:6px 8px}#dsh-plan .p-tabs{position:absolute;top:16px;left:50%;transform:translate(-50%);z-index:3;display:flex;gap:4px;background:var(--toolbar-bg);border:1px solid var(--card-line);border-radius:8px;padding:4px}#dsh-plan .p-tabs [role=tab]{background:transparent;color:var(--ink-muted);border:1px solid transparent;border-radius:6px;padding:4px 12px;font:inherit;cursor:pointer}#dsh-plan .p-tabs [role=tab]:hover{color:var(--ink);border-color:var(--card-line)}#dsh-plan .p-tabs [role=tab][aria-selected=true]{color:var(--ink);border-color:var(--accent);background:var(--uupm-wash-12)}#dsh-plan .p-tabs [role=tab]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}#dsh-plan .p-toolbar button{background:transparent;color:var(--ink);border:1px solid var(--card-line);border-radius:6px;padding:4px 10px;font:inherit;cursor:pointer;white-space:nowrap}#dsh-plan .p-toolbar button:hover{border-color:var(--accent)}#dsh-plan .p-toolbar button:active{background:var(--uupm-wash-15)}#dsh-plan .p-toolbar button:focus-visible{outline:2px solid var(--accent);outline-offset:1px}#dsh-plan .p-zoom{min-width:44px;text-align:center;font-size:11px;color:var(--ink-muted)}#dsh-plan .p-sep{align-self:stretch;width:1px;margin:2px 4px;background:var(--card-line)}#dsh-plan .p-lamp{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--ink-muted);padding:0 6px}#dsh-plan .p-lamp i{width:7px;height:7px;border-radius:50%;background:var(--ink-muted);transition:background .14s ease}#dsh-plan .p-lamp.saved i{background:var(--edge-live)}#dsh-plan .p-lamp.pending i{background:var(--uupm-warn)}#dsh-plan .p-lamp.error{color:var(--uupm-error);cursor:pointer}#dsh-plan .p-lamp.error i{background:var(--uupm-error)}#dsh-plan .p-lamp.error:hover{border:1px solid var(--uupm-error);border-radius:4px}#dsh-plan .p-status{position:absolute;top:16px;right:16px;z-index:3;display:flex;gap:14px;background:var(--toolbar-bg);border:1px solid var(--card-line);border-radius:8px;padding:8px 14px;font-size:12px}#dsh-plan .p-status b{font-weight:600}#dsh-plan .ok{color:var(--edge-live)}#dsh-plan .warn{color:var(--uupm-warn)}#dsh-plan .mut{color:var(--ink-muted)}#dsh-plan .p-legend{position:absolute;bottom:16px;left:16px;z-index:3;font-size:11px;color:var(--ink-muted);background:var(--toolbar-bg);border:1px solid var(--card-line);border-radius:8px;padding:4px 10px}#dsh-plan .p-legend summary{cursor:pointer;padding:2px 0;-webkit-user-select:none;user-select:none}#dsh-plan .p-legend summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}#dsh-plan .p-legend[open]{padding-bottom:8px}#dsh-plan .p-legend-rows{display:grid;gap:4px;margin-top:4px}#dsh-plan .p-legend i{display:inline-block;width:18px;border-top:2px solid var(--uupm-edge-member);vertical-align:middle;margin-right:6px}#dsh-plan .p-legend i.dashed{border-top-style:dashed}@media (max-width:680px){#dsh-plan .p-toolbar{position:relative;top:auto;left:auto;margin:8px 8px 0;flex-wrap:wrap;row-gap:6px}#dsh-plan .p-toolbar>*{flex:none}#dsh-plan .p-toolbar .p-search{order:-1;flex:1 1 100%}#dsh-plan .p-toolbar .p-sep{display:none}#dsh-plan .p-toolbar .p-search-input{width:100%;box-sizing:border-box}#dsh-plan .p-status{position:relative;top:auto;right:auto;left:auto;width:fit-content;margin:6px 8px 0;padding:6px 10px;gap:10px;flex-wrap:wrap}#dsh-plan .p-legend{display:none}}@media (pointer:coarse){#dsh-plan .p-toolbar button{min-height:36px;min-width:36px}}@media (prefers-reduced-motion: reduce){#dsh-plan *{transition:none!important;animation:none!important}}#dsh-plan .p-frame.drop-target{border-color:var(--accent);border-width:2px;background:var(--uupm-wash-12)}#dsh-plan .p-frame-head:focus-visible{outline:2px solid var(--accent);outline-offset:1px}#dsh-plan .p-node.remote{border-left-color:var(--federal);padding-right:46px}#dsh-plan .p-node.remote .dot{background:var(--federal)}#dsh-plan .p-node.remote .prio{color:var(--ink)}#dsh-plan .p-node .prio.lnk-linked{color:var(--live, #2e9e5b);border-color:var(--live, #2e9e5b)}#dsh-plan .p-node .prio.lnk-stranger{color:var(--ink-muted);border-color:var(--card-line)}#dsh-plan .e-activity{stroke:var(--accent);stroke-width:2;stroke-dasharray:8 6;stroke-opacity:.9}#dsh-plan .e-federal{stroke:var(--federal);stroke-width:1.5;stroke-dasharray:6 5;stroke-opacity:.5}#dsh-plan .edge-label{font-size:10.5px;fill:var(--ink-muted)}@media (prefers-reduced-motion: no-preference){#dsh-plan .e-activity{animation:p-activity-flow 1.1s linear infinite}}@keyframes p-activity-flow{to{stroke-dashoffset:-28}}#dsh-plan .p-status{cursor:pointer}#dsh-plan .p-status:hover{border-color:var(--accent)}#dsh-plan .p-status:active{background:var(--uupm-wash-12)}#dsh-plan .p-status:focus-visible{outline:2px solid var(--accent);outline-offset:2px}#dsh-plan .p-menu{position:fixed;z-index:5;min-width:170px;display:grid;padding:4px;gap:2px;background:var(--toolbar-bg);border:1px solid var(--card-line);border-radius:8px}#dsh-plan .p-menu [role=menuitem]{background:transparent;color:var(--ink);border:1px solid transparent;border-radius:6px;padding:6px 10px;font:inherit;text-align:left;cursor:pointer;white-space:nowrap}#dsh-plan .p-menu [role=menuitem]:hover{border-color:var(--card-line);background:var(--uupm-wash-8)}#dsh-plan .p-menu [role=menuitem]:active{background:var(--uupm-wash-18)}#dsh-plan .p-menu [role=menuitem]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}#dsh-plan .p-menu [role=menuitem][aria-disabled=true]{color:var(--ink-muted);cursor:not-allowed}#dsh-plan .p-dialog{position:absolute;top:0;right:0;bottom:0;left:0;z-index:6;display:grid;place-items:center;background:var(--scrim)}#dsh-plan .p-dialog-panel{min-width:300px;padding:14px 16px;display:grid;gap:10px;background:var(--uupm-bg-2);border:1px solid var(--card-line);border-radius:10px}#dsh-plan .p-dialog-title{font-weight:600;font-size:12.5px;color:var(--ink)}#dsh-plan .p-dialog-input{font:inherit;color:var(--ink);background:var(--uupm-bg-0);border:1px solid var(--card-line);border-radius:6px;padding:7px 10px}#dsh-plan .p-dialog-input:hover{border-color:color-mix(in srgb,var(--uupm-ink-1) 55%,transparent)}#dsh-plan .p-dialog-input:focus-visible{outline:2px solid var(--accent);outline-offset:1px;border-color:var(--accent)}#dsh-plan .p-dialog-err{min-height:1.2em;font-size:11px;color:var(--uupm-error)}#dsh-plan .p-dialog-kind{display:grid;grid-template-columns:1fr 1fr;gap:4px;padding:3px;background:var(--uupm-bg-0);border:1px solid var(--card-line);border-radius:8px}#dsh-plan .p-dialog-kind button{font:inherit;color:var(--ink-muted);background:transparent;border:1px solid transparent;border-radius:6px;padding:6px 10px;cursor:pointer}#dsh-plan .p-dialog-kind button:hover{color:var(--ink);background:var(--uupm-wash-8)}#dsh-plan .p-dialog-kind button[aria-checked=true]{color:var(--ink);font-weight:600;background:var(--uupm-wash-15);border-color:var(--accent)}#dsh-plan .p-dialog-kind button:focus-visible{outline:2px solid var(--accent);outline-offset:1px}#dsh-plan .p-dialog-hint{font-size:11px;color:var(--ink-muted);max-width:340px}#dsh-plan .p-dialog-row{display:flex;gap:8px;justify-content:flex-end}#dsh-plan .p-dialog-row button{background:transparent;color:var(--ink);border:1px solid var(--card-line);border-radius:6px;padding:5px 12px;font:inherit;cursor:pointer}#dsh-plan .p-dialog-row button:hover{border-color:var(--accent)}#dsh-plan .p-dialog-row button:active{background:var(--uupm-wash-15)}#dsh-plan .p-dialog-row button:focus-visible{outline:2px solid var(--accent);outline-offset:1px}#dsh-plan .p-notice-stack{position:absolute;bottom:52px;left:50%;transform:translate(-50%);z-index:5;display:grid;gap:6px;justify-items:center;pointer-events:none}#dsh-plan .p-notice{max-width:60ch;padding:7px 12px;font-size:12px;color:var(--ink);background:var(--toolbar-bg);border:1px solid var(--card-line);border-radius:8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}#dsh-plan .p-notice.error{color:var(--error-ink);border-color:var(--uupm-error);background:var(--error-panel)}#dsh-plan .p-netbtn{color:var(--ink-muted)}#dsh-plan .p-netbtn:not([disabled]){color:var(--ink)}#dsh-plan .p-netmenu{max-height:240px;overflow:auto}#dsh-plan .p-nodebtn{color:var(--ink)}#dsh-plan .p-nodelist{min-width:300px;max-width:340px;max-height:420px;overflow:auto;padding:6px}#dsh-plan .p-nodelist-head{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:2px 4px 6px;border-bottom:1px solid var(--card-line)}#dsh-plan .p-nodelist-title{font-size:12px;font-weight:600;color:var(--ink)}#dsh-plan .p-nodesel{font:inherit;font-size:11.5px;color:var(--ink);background:var(--uupm-bg-0);border:1px solid var(--card-line);border-radius:6px;padding:2px 6px;max-width:220px}#dsh-plan .p-nodesel:focus-visible{outline:2px solid var(--accent);outline-offset:1px}#dsh-plan .p-nodelist-group{font-size:11px;color:var(--ink-muted);padding:8px 4px 3px;display:flex;align-items:baseline;gap:8px}#dsh-plan .p-nodelist-note{font-size:10px;color:var(--ink-muted);opacity:.8}#dsh-plan .p-noderow{display:flex;align-items:center;gap:6px;padding:3px 4px;border-radius:6px;font-size:12px;color:var(--ink)}#dsh-plan .p-noderow:hover{background:var(--uupm-wash-8)}#dsh-plan .p-nodedot{flex:none;width:7px;height:7px;border-radius:50%;background:var(--edge-live)}#dsh-plan .p-nodedot.cold{background:var(--ink-muted)}#dsh-plan .p-nodedot.off{background:transparent;border:1px solid var(--ink-muted)}#dsh-plan .p-nodename{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#dsh-plan .p-nonet{flex:none;font-size:10px;color:var(--uupm-warn);border:1px solid var(--uupm-warn);border-radius:4px;padding:0 4px}#dsh-plan .p-teamcount{flex:none;font-size:10px;color:var(--ink-muted);border:1px solid var(--card-line);border-radius:4px;padding:0 4px}#dsh-plan .p-listbtn{flex:none;background:transparent;color:var(--ink);border:1px solid var(--card-line);border-radius:5px;padding:1px 7px;font:inherit;font-size:11px;cursor:pointer}#dsh-plan .p-listbtn:hover{border-color:var(--card-line-hover);background:var(--uupm-wash-8)}#dsh-plan .p-listbtn:focus-visible{outline:2px solid var(--accent);outline-offset:1px}#dsh-plan .p-nodelist-empty{padding:10px 4px;font-size:11.5px;color:var(--ink-muted)}#dsh-plan .p-frame{position:absolute}#dsh-plan .p-frame-handle{position:absolute;pointer-events:auto;width:10px;height:10px;z-index:2;opacity:0;transition:opacity .12s ease}#dsh-plan .p-frame:hover .p-frame-handle{opacity:1}#dsh-plan .p-frame-handle:after{content:"";position:absolute;top:2px;right:2px;bottom:2px;left:2px;background:var(--frame-ink);border-radius:2px}#dsh-plan .p-h-n{top:-5px;left:calc(50% - 12px);width:24px;height:8px;cursor:ns-resize}#dsh-plan .p-h-s{bottom:-5px;left:calc(50% - 12px);width:24px;height:8px;cursor:ns-resize}#dsh-plan .p-h-e{right:-5px;top:calc(50% - 12px);width:8px;height:24px;cursor:ew-resize}#dsh-plan .p-h-w{left:-5px;top:calc(50% - 12px);width:8px;height:24px;cursor:ew-resize}#dsh-plan .p-h-ne{top:-5px;right:-5px;cursor:nesw-resize}#dsh-plan .p-h-nw{top:-5px;left:-5px;cursor:nwse-resize}#dsh-plan .p-h-se{bottom:-5px;right:-5px;cursor:nwse-resize}#dsh-plan .p-h-sw{bottom:-5px;left:-5px;cursor:nesw-resize}#dsh-plan .p-h-ne:after,#dsh-plan .p-h-sw:after{transform:rotate(45deg)}#dsh-plan .p-h-nw:after,#dsh-plan .p-h-se:after{transform:rotate(-45deg)}#dsh-plan .p-frame.selected .p-frame-handle{opacity:1}#dsh-plan .p-frame.selected{outline:1px solid var(--frame-ink)}:root{color-scheme:dark;--n-bg:#060a12;--n-ink:#dde3f0;--n-ink-muted:#7a86a0;--n-panel:#0d1322;--n-live:#4ade80;--n-cold:#7a86a0;--n-border:#223052;--n-act:#f59e0b;--n-danger:#f87171;--n-accent:#9673f7;--n-rail-w:300px;--n-canvas:#22d3ee;--n-line:var(--n-border);--n-raised:#131b2e;--n-federal:#6366f1;--n-card-line:#5c6680;--n-error-ink:#fecaca;--n-error-panel:#2a0d10f2;--n-shadow:rgba(0,0,0,.35)}@media (prefers-color-scheme: light){:root{--n-bg:#eef2fa;--n-ink:#1a2438;--n-ink-muted:#5a6580;--n-panel:#ffffff;--n-live:#157a37;--n-border:#c6d0e6;--n-act:#a84d08;--n-danger:#b91c1c;--n-accent:#6d28d9;--n-cold:#636c81;--n-canvas:#0e7490;--n-raised:#ffffff;--n-federal:#4f46e5;--n-card-line:#8a95ae;--n-error-ink:#b91c1c;--n-error-panel:#fef2f2f2;--n-shadow:rgba(26,36,56,.16)}}@media (min-width:1440px){:root{--n-rail-w:340px }}html,body,#app{height:100%;margin:0}body{background:var(--n-bg);color:var(--n-ink);font:13px/1.45 system-ui,Segoe UI,Roboto,PingFang SC,Microsoft YaHei,sans-serif}.wb{display:flex;flex-direction:column;height:100%}.wb-header{display:flex;align-items:center;gap:12px;padding:8px 14px;border-bottom:1px solid var(--n-border);background:var(--n-panel)}.wb-title{display:flex;align-items:center;gap:10px;font-weight:600;font-size:14px;white-space:nowrap}.wb-badge{font-size:11px;font-weight:400;color:var(--n-ink-muted);border:1px solid var(--n-border);border-radius:99px;padding:1px 8px}.wb-badge[hidden]{display:none}.wb-row-remote{margin-left:6px;padding:0 6px;border:1px solid currentColor;border-radius:99px;font-size:10.5px;color:var(--n-ink-muted);vertical-align:1px}.wb-header-stats{display:flex;gap:16px;font-size:12px;color:var(--n-ink-muted);flex-wrap:wrap;min-width:0}.wb-header-stats .wb-kv{display:flex;gap:6px}.wb-header-stats .wb-kv-k{color:var(--n-ink-muted)}.wb-header-stats .wb-kv-v{color:var(--n-ink)}.wb-header-ok{color:var(--n-ink-muted)}.wb-alert{border:1px solid currentColor;border-radius:99px;padding:0 9px;line-height:20px;white-space:nowrap;cursor:pointer;background:transparent;font:inherit}.wb-alert:hover{background:color-mix(in srgb,currentColor 12%,transparent)}.wb-alert:focus-visible{outline:2px solid currentColor;outline-offset:2px}.wb-alert-danger{color:var(--n-danger)}.wb-alert-warn{color:var(--n-act)}.wb-forensics{font-family:ui-monospace,Consolas,monospace;font-size:11px}.wb-icon-btn{background:none;border:1px solid var(--n-border);color:var(--n-ink);border-radius:8px;width:30px;height:30px;display:none;align-items:center;justify-content:center;font:inherit;font-size:14px;cursor:pointer;flex:none}.wb-icon-btn:hover{border-color:var(--n-accent)}.wb-menu{margin-left:0}.wb-rail-toggle{margin-left:auto}.wb.is-rail-collapsed .wb-rail{display:none}.wb-body{position:relative;display:grid;grid-template-columns:minmax(0,var(--n-rail-w)) minmax(0,1fr);flex:1;min-height:0}.wb-rail{border-right:1px solid var(--n-border);min-width:0;min-height:0;display:flex;flex-direction:column;overflow:hidden;background:color-mix(in srgb,var(--n-panel) 60%,var(--n-bg))}.wb-side-head{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--n-ink-muted);margin:10px 2px 4px}.wb-item{display:flex;gap:7px;align-items:center;width:100%;text-align:left;background:none;border:none;color:var(--n-ink);font:inherit;padding:3px 6px;border-radius:6px;cursor:pointer}.wb-item:hover{background:color-mix(in srgb,var(--n-accent) 14%,transparent)}.wb-dot{font-size:10px}.wb-dot-live{color:var(--n-live)}.wb-dot-cold{color:var(--n-cold)}.wb-dot-canvas{color:var(--n-canvas)}.wb-dot-remote{color:var(--n-act)}.wb-dir-tools{display:flex;flex-direction:column;gap:6px;padding:8px 6px 4px}.wb-search{background:var(--n-panel);border:1px solid var(--n-border);color:var(--n-ink);border-radius:6px;padding:4px 8px;font:inherit;font-size:12.5px;min-width:0}.wb-search:focus{outline:1px solid var(--n-accent)}.wb-filters{display:flex;flex-wrap:wrap;gap:4px}.wb-filter{background:none;border:1px solid var(--n-border);color:var(--n-ink-muted);border-radius:99px;padding:0 10px;min-height:24px;font:inherit;font-size:11.5px;cursor:pointer}.wb-filter:hover{border-color:var(--n-accent);color:var(--n-ink)}.wb-filter.is-active{border-color:var(--n-accent);color:var(--n-ink);background:color-mix(in srgb,var(--n-accent) 16%,transparent)}.wb-item-badge{flex:none;font-size:10.5px;color:var(--n-canvas);border:1px solid color-mix(in srgb,var(--n-canvas) 45%,transparent);border-radius:99px;padding:0 6px;line-height:17px;white-space:nowrap}.wb-item-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wb-member-row{display:flex;align-items:center;gap:8px;padding:3px 2px;border-radius:6px}.wb-member-row:hover{background:color-mix(in srgb,var(--n-accent) 10%,transparent)}.wb-member-dot{flex:none;font-size:11px;color:var(--n-ink-muted);min-width:44px}.wb-member-label{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wb-member-remove,.wb-member-submit{background:none;border:1px solid var(--n-border);color:var(--n-ink);border-radius:6px;padding:1px 8px;font:inherit;font-size:11.5px;cursor:pointer;flex:none}.wb-member-remove:hover:not(:disabled),.wb-member-submit:hover:not(:disabled){border-color:var(--n-danger)}.wb-member-submit:hover:not(:disabled){border-color:var(--n-accent)}.wb-member-add{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}.wb-cli-home{display:flex;flex-wrap:wrap;gap:6px;padding:8px;margin:4px 0 10px;border:1px solid var(--n-border);border-radius:6px}.wb-cli-home [hidden]{display:none}.wb-cli-home .wb-hint{flex-basis:100%;margin-top:0}.wb-cli-home .wb-member-pick{min-width:0;max-width:100%}.wb-member-pick,.wb-member-manual{background:var(--n-panel);border:1px solid var(--n-border);color:var(--n-ink);border-radius:6px;padding:3px 8px;font:inherit;font-size:12px;min-width:0}.wb-member-pick{flex:1 1 150px}.wb-member-manual{flex:1 1 130px}.wb-member-pick:focus,.wb-member-manual:focus{outline:1px solid var(--n-accent)}.wb-hint{margin-top:10px;font-size:11px;color:var(--n-ink-muted);line-height:1.5}.wb-dispatch{margin-top:12px;border-top:1px dashed var(--n-border);padding-top:8px}.wb-dispatch-form{display:flex;flex-direction:column;gap:6px;margin-top:6px}.wb-dispatch-text{background:var(--n-panel);border:1px solid var(--n-border);color:var(--n-ink);border-radius:6px;padding:5px 8px;font:inherit;font-size:12px;min-height:52px;resize:vertical}.wb-dispatch-text:focus{outline:1px solid var(--n-accent)}.wb-dispatch-submit{align-self:flex-end;background:none;border:1px solid var(--n-border);color:var(--n-ink);border-radius:6px;padding:2px 14px;font:inherit;font-size:11.5px;cursor:pointer}.wb-dispatch-submit:hover:not(:disabled){border-color:var(--n-accent)}.wb-dispatch-note{font-size:11px;color:var(--n-ink-muted);line-height:1.4;min-height:0}.wb-stage{position:relative;min-width:0;min-height:0;display:flex;flex-direction:column}.wb-stage-board{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden}.wb-stage-board.is-hidden{display:none}.wb-data{display:flex;flex-direction:column;gap:14px;padding:10px 14px;overflow-y:auto;min-height:0}.wb-data.is-hidden{display:none}.wb-pane-head{font-size:12px;color:var(--n-ink-muted);margin:4px 0 8px}.wb-pane-subhead{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--n-ink-muted);margin:12px 0 6px}.wb-table,.wb-row{display:flex;gap:10px;align-items:baseline}.wb-row{font-family:ui-monospace,Consolas,monospace;font-size:12px;background:color-mix(in srgb,var(--n-panel) 55%,transparent);border:1px solid var(--n-border);border-radius:6px;padding:3px 8px;flex-wrap:wrap}.wb-row-team{color:var(--n-accent);min-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wb-row-meta{color:var(--n-ink-muted)}.wb-row-badges{color:var(--n-live)}.wb-row-dir{min-width:16px}.wb-row-dir.is-fail{color:var(--n-danger)}.wb-btn{background:none;border:1px solid var(--n-border);color:var(--n-ink);border-radius:6px;padding:2px 10px;font:inherit;font-size:12px;cursor:pointer;margin-left:auto}.wb-btn:hover:not(:disabled){border-color:var(--n-accent)}.wb-btn:disabled{opacity:.5;cursor:default}.wb-btn-primary{border-color:var(--n-accent);color:var(--n-ink)}.wb-action{display:flex;gap:10px;align-items:baseline;font-size:12.5px;padding:5px 8px;border-radius:6px;border:1px solid var(--n-border);margin-bottom:4px}.wb-action-high{border-color:var(--n-danger)}.wb-action-text{flex:1}.wb-draft{display:flex;flex-direction:column;gap:8px;max-width:560px;margin-top:6px}.wb-select,.wb-textarea{background:var(--n-panel);border:1px solid var(--n-border);color:var(--n-ink);border-radius:8px;padding:6px 9px;font:inherit}.wb-textarea{resize:vertical}.wb-select:focus,.wb-textarea:focus{outline:1px solid var(--n-accent)}.wb-inspector{position:absolute;top:8px;right:8px;width:280px;max-height:calc(100% - 16px);overflow-y:auto;background:var(--n-panel);border:1px solid var(--n-border);border-radius:10px;padding:10px;z-index:20;box-shadow:0 8px 24px var(--n-shadow);display:none}.wb-inspector.is-open{display:block}.wb-inspector-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px}.wb-inspector-title{font-weight:600;font-size:12.5px}.wb-inspector .wb-icon-btn{display:inline-flex;width:24px;height:24px;font-size:12px}.wb-card{display:flex;flex-direction:column;gap:6px}.wb-kv{display:flex;gap:8px;font-size:12px}.wb-kv-k{color:var(--n-ink-muted);min-width:58px;flex:none}.wb-kv-v{word-break:break-all}.wb-muted{color:var(--n-ink-muted)}.wb-chat{position:absolute;top:8px;right:8px;bottom:8px;width:400px;max-width:calc(100% - 16px);display:flex;flex-direction:column;background:var(--n-panel);border:1px solid var(--n-border);border-radius:12px;z-index:22;box-shadow:0 8px 24px var(--n-shadow);overflow:hidden;transform:translate(calc(100% + 12px));transition:transform .18s ease;pointer-events:none}.wb-chat.is-open{transform:translate(0);pointer-events:auto}.wb-chat-head{display:flex;align-items:center;gap:8px;padding:10px 10px 10px 12px;border-bottom:1px solid var(--n-border);flex:none}.wb-chat-dot{flex:none;width:8px;height:8px;border-radius:50%;background:var(--n-ink-muted)}.wb-chat-dot.is-live{background:var(--n-live)}.wb-chat-dot.is-cold{background:transparent;border:1.5px solid var(--n-ink-muted)}.wb-chat-dot.is-peer{background:var(--n-federal)}.wb-chat-titles{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;line-height:1.3}.wb-chat-title{font-weight:600;font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wb-chat-sub{font:11px/1.4 ui-monospace,Consolas,monospace;color:var(--n-ink-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wb-chat .wb-icon-btn{display:inline-flex;width:28px;height:28px;font-size:13px;flex:none;border-color:transparent}.wb-chat .wb-icon-btn:hover{border-color:var(--n-border)}.wb-chat .wb-icon-btn:focus-visible{outline:2px solid var(--n-accent);outline-offset:1px}.wb-chat .wb-chat-back[hidden]{display:none}.wb-chat-info-btn[aria-expanded=true]{border-color:var(--n-accent);color:var(--n-accent)}.wb-chat-info{flex:none;display:flex;flex-direction:column;gap:4px;padding:8px 12px;font-size:12px;border-bottom:1px solid var(--n-border);background:color-mix(in srgb,var(--n-bg) 55%,var(--n-panel))}.wb-chat-info[hidden]{display:none}.wb-chat-info .wb-kv-v{font-family:ui-monospace,Consolas,monospace;font-size:11.5px}.wb-chat-thread{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;display:flex;flex-direction:column;gap:10px;padding:12px}.wb-chat-thread:focus-visible{outline:2px solid var(--n-accent);outline-offset:-2px}.wb-chat-log,.wb-chat-sent{display:flex;flex-direction:column;gap:10px}.wb-chat-notice{align-self:center;max-width:92%;text-align:center;font-size:11.5px;line-height:1.5;color:var(--n-ink-muted);border:1px dashed var(--n-border);border-radius:8px;padding:6px 10px}.wb-chat-notice[hidden]{display:none}.wb-chat-empty{align-self:center;padding:24px 8px;font-size:12px;color:var(--n-ink-muted);text-align:center}.wb-chat-empty.is-error{color:var(--n-danger)}.wb-msg{display:flex;flex-direction:column;gap:4px;max-width:86%;padding:8px 11px;border-radius:12px;font-size:13px;line-height:1.55}.wb-msg-assistant{align-self:flex-start;background:var(--n-raised);border:1px solid var(--n-border);border-bottom-left-radius:4px}.wb-msg-user{align-self:flex-end;background:color-mix(in srgb,var(--n-accent) 16%,var(--n-panel));border:1px solid color-mix(in srgb,var(--n-accent) 35%,transparent);border-bottom-right-radius:4px}.wb-msg-ledger{align-self:center;max-width:92%;background:transparent;border:1px dashed var(--n-border);font-size:12px}.wb-msg-ledger .wb-msg-text{color:var(--n-ink-muted)}.wb-msg-ledger .wb-msg-meta{justify-content:center}.wb-msg-in .wb-msg-meta{justify-content:flex-start}.wb-msg-who{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.wb-msg-text{color:var(--n-ink);white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere}.wb-msg-meta{display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:6px;font-size:11px}.wb-msg-task{font-family:ui-monospace,Consolas,monospace;color:var(--n-ink-muted)}.wb-msg-status{border:1px solid currentColor;border-radius:99px;padding:0 7px;line-height:18px;white-space:nowrap}.wb-msg-status.is-wait,.wb-msg-status.is-muted{color:var(--n-ink-muted)}.wb-msg-status.is-ok{color:var(--n-live)}.wb-msg-status.is-warn{color:var(--n-act)}.wb-msg-status.is-danger{color:var(--n-danger)}.wb-chat-divider{display:flex;align-items:center;gap:8px;font-size:11px;color:var(--n-ink-muted);margin-top:4px}.wb-chat-divider:before,.wb-chat-divider:after{content:"";flex:1;border-top:1px solid var(--n-border)}.wb-chat-sessions{display:flex;flex-direction:column;gap:6px}.wb-chat-session{display:flex;flex-direction:column;align-items:flex-start;gap:2px;width:100%;text-align:left;background:var(--n-raised);border:1px solid var(--n-border);border-radius:8px;padding:7px 10px;color:var(--n-ink);font:inherit;cursor:pointer}.wb-chat-session:hover{border-color:var(--n-accent)}.wb-chat-session:focus-visible{outline:2px solid var(--n-accent);outline-offset:1px}.wb-chat-session-id{font:12px ui-monospace,Consolas,monospace}.wb-chat-session-meta{font-size:11px;color:var(--n-ink-muted)}.wb-chat-foot{flex:none;border-top:1px solid var(--n-border);padding:8px 10px 10px;background:var(--n-panel)}.wb-chat-composer{display:flex;flex-direction:column;gap:4px}.wb-chat-composer-row{display:flex;align-items:flex-end;gap:8px}.wb-chat-composer .wb-dispatch-text{flex:1 1 auto;min-height:38px;max-height:160px;resize:none;border-radius:10px;padding:8px 10px;font-size:13px;line-height:1.5}.wb-chat-composer .wb-dispatch-submit{align-self:auto;height:38px;padding:0 16px;border-radius:10px;background:var(--n-accent);border-color:var(--n-accent);color:var(--n-bg);font-size:13px;font-weight:600}.wb-chat-composer .wb-dispatch-submit:hover:not(:disabled){border-color:var(--n-accent);filter:brightness(1.08)}.wb-chat-composer .wb-dispatch-submit:disabled{opacity:.45;cursor:default}.wb-chat-composer .wb-dispatch-note{font-size:11px;padding-left:2px}.wb-chat-composer .wb-dispatch-note.is-error{color:var(--n-danger)}.wb-chat-readonly{font-size:12px;color:var(--n-ink-muted);text-align:center;padding:4px 0}.nexus-fault{display:none;position:fixed;top:10px;right:12px;z-index:50;max-width:420px;font:12px/1.5 ui-monospace,Consolas,monospace;color:var(--n-error-ink);background:var(--n-error-panel);border:1px solid var(--n-danger);border-radius:8px;padding:6px 10px;pointer-events:none}@media (max-width:1023px){.wb-menu{display:inline-flex}.wb-rail-toggle{display:none}.wb-body{grid-template-columns:minmax(0,1fr)}.wb-rail{position:fixed;left:0;top:0;bottom:0;width:min(86vw,320px);z-index:40;background:var(--n-panel);border-right:1px solid var(--n-border);transform:translate(-102%);transition:transform .18s ease;box-shadow:8px 0 24px var(--n-shadow)}.wb.is-rail-open .wb-rail{transform:translate(0)}.wb-inspector{left:8px;right:8px;width:auto;top:auto;bottom:8px;max-height:45%}.wb-chat{left:8px;right:8px;width:auto;top:auto;bottom:8px;height:85%;max-height:85%;transform:translateY(102%)}.wb-chat.is-open{transform:translateY(0)}}@media (pointer:coarse){.wb-filter,.wb-item,.wb-tab{min-height:36px}.wb-icon-btn,.wb-inspector .wb-icon-btn,.wb-chat .wb-icon-btn{width:36px;height:36px}}@media (max-width:680px){.wb-header{flex-wrap:wrap;row-gap:4px}.wb-header-stats{order:3;width:100%}.wb-row-team{min-width:0;flex:1 1 auto}.wb-data{padding:8px}}.wb-host-row{display:flex;align-items:center;gap:7px;padding:4px 6px;border:1px solid var(--n-border);border-radius:7px;margin-bottom:4px;cursor:pointer;font-size:12px}.wb-host-row:hover{border-color:var(--n-accent);background:color-mix(in srgb,var(--n-accent) 8%,transparent)}.wb-host-row:focus-visible{outline:2px solid var(--n-accent);outline-offset:1px}.wb-host-lamp{flex:none;width:8px;height:8px;border-radius:50%;background:var(--n-ink-muted)}.wb-host-lamp.is-live{background:var(--n-live)}.wb-host-lamp.is-warm{background:var(--n-act)}.wb-host-lamp.is-cold{background:var(--n-ink-muted)}.wb-host-lamp.is-fail{background:var(--n-danger)}.wb-host-lamp.is-unknown{background:transparent;border:1px solid var(--n-ink-muted)}.wb-host-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--n-ink)}.wb-host-badge{flex:none;font-size:10.5px;border-radius:99px;padding:0 7px;line-height:17px;border:1px solid var(--n-border)}.wb-host-badge.is-linked{color:var(--n-live);border-color:var(--n-live)}.wb-host-badge.is-stranger{color:var(--n-ink-muted);border-color:var(--n-border)}.wb-host-ver{flex:none;font-size:10px;color:var(--n-ink-muted);border:1px solid var(--n-border);border-radius:4px;padding:0 4px}.wb-host-url{flex:none;max-width:40%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--n-ink-muted);font-size:10.5px}.wb-tabs{flex:none;display:flex;gap:2px;padding:6px 6px 0;border-bottom:1px solid var(--n-border);overflow-x:auto;scrollbar-width:none}.wb-tab{flex:1 1 auto;display:inline-flex;align-items:center;justify-content:center;gap:5px;min-width:0;background:none;border:none;border-bottom:2px solid transparent;color:var(--n-ink-muted);font:inherit;font-size:12.5px;padding:6px 6px 7px;cursor:pointer;white-space:nowrap}.wb-tab:hover{color:var(--n-ink)}.wb-tab.is-active{color:var(--n-ink);border-bottom-color:var(--n-accent);font-weight:600}.wb-tab:focus-visible{outline:2px solid var(--n-accent);outline-offset:-2px;border-radius:6px 6px 0 0}.wb-tab[hidden]{display:none}.wb-tab-badge{font:10.5px/16px ui-monospace,Consolas,monospace;color:var(--n-ink-muted);font-weight:400}.wb-tab-badge:empty{display:none}.wb-tab-badge.is-danger,.wb-tab-badge.is-warn,.wb-tab-badge.is-accent{padding:0 6px;border-radius:99px;border:1px solid currentColor}.wb-tab-badge.is-danger{color:var(--n-danger)}.wb-tab-badge.is-warn{color:var(--n-act)}.wb-tab-badge.is-accent{color:var(--n-accent)}.wb-tabpanels{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}.wb-tabpanel{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:8px 10px 16px}.wb-tabpanel[hidden]{display:none}.wb-tabpanel:focus-visible{outline:2px solid var(--n-accent);outline-offset:-2px}.wb-tabpanel .wb-pane{display:flex;flex-direction:column;gap:8px}.wb-tabpanel .wb-dir-tools{padding:0 0 6px}.wb-dir-group{display:flex;flex-direction:column;gap:1px;margin-top:10px}.wb-dir-group:first-child{margin-top:2px}.wb-dir-head{display:flex;align-items:baseline;justify-content:space-between;gap:8px;padding:0 6px 4px;font-size:11px;letter-spacing:.04em;color:var(--n-ink-muted)}.wb-dir-head-label{font-weight:600;color:var(--n-ink)}.wb-dir-head-note{font-size:10.5px}.wb-dir-day{padding:6px 6px 2px;font-size:10.5px;color:var(--n-ink-muted)}.wb-dir-empty{padding:24px 8px;text-align:center;font-size:12px;color:var(--n-ink-muted)}.wb-directory .wb-item{gap:9px;padding:5px 6px;border-radius:8px}.wb-directory .wb-item:focus-visible{outline:2px solid var(--n-accent);outline-offset:-2px}.wb-item-text{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;line-height:1.35}.wb-item-sub{font:11px/1.35 ui-monospace,Consolas,monospace;color:var(--n-ink-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wb-item.is-untitled .wb-item-label{color:var(--n-ink-muted);font-family:ui-monospace,Consolas,monospace;font-size:12px}.wb-directory .wb-item.is-unreachable{opacity:.78}.wb-unreachable-note,.wb-node-warning{font-size:11px;line-height:1.35;color:var(--n-danger);white-space:normal;overflow-wrap:anywhere}.wb-dot-log{color:var(--n-ink-muted)}.wb-led-tiles{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}.wb-led-tile{display:flex;flex-direction:column;align-items:flex-start;gap:1px;padding:7px 8px;border-radius:8px;border:1px solid var(--n-border);background:var(--n-raised);cursor:help;min-width:0}.wb-led-tile-v{font:600 17px/1.15 ui-monospace,Consolas,monospace;color:var(--n-ink)}.wb-led-tile-k{font-size:11px;color:var(--n-ink-muted)}.wb-led-tile.is-warn{border-color:var(--n-act)}.wb-led-tile.is-warn .wb-led-tile-v{color:var(--n-act)}.wb-led-tile.is-danger{border-color:var(--n-danger)}.wb-led-tile.is-danger .wb-led-tile-v{color:var(--n-danger)}.wb-led-split{display:flex;flex-direction:column;gap:4px}.wb-led-split-bar{display:flex;height:6px;border-radius:99px;overflow:hidden;background:var(--n-border)}.wb-led-seg{display:block;height:100%}.wb-led-split-legend{display:flex;flex-wrap:wrap;gap:4px 10px;font-size:11px;color:var(--n-ink-muted)}.wb-led-split-item{display:inline-flex;align-items:center;gap:4px}.wb-led-swatch{display:inline-block;width:8px;height:8px;border-radius:2px}.wb-led-seg.is-completed,.wb-led-swatch.is-completed{background:var(--n-live)}.wb-led-seg.is-rejected,.wb-led-swatch.is-rejected{background:var(--n-act)}.wb-led-seg.is-failed,.wb-led-swatch.is-failed{background:var(--n-danger)}.wb-led-seg.is-abandoned,.wb-led-swatch.is-abandoned{background:var(--n-ink-muted)}.wb-led-seg.is-unclassified,.wb-led-swatch.is-unclassified,.wb-led-seg.is-other,.wb-led-swatch.is-other{background:color-mix(in srgb,var(--n-ink-muted) 45%,var(--n-border))}.wb-led-group{display:flex;flex-direction:column;gap:6px;margin-top:4px}.wb-led-group-head{display:flex;align-items:baseline;justify-content:space-between;gap:8px;font-size:11.5px;font-weight:600;color:var(--n-ink)}.wb-led-group-hint{font-size:10.5px;font-weight:400;color:var(--n-ink-muted)}.wb-led-group.is-danger .wb-led-group-head{color:var(--n-danger)}.wb-led-group.is-warn .wb-led-group-head{color:var(--n-act)}.wb-led-card{position:relative;display:flex;flex-direction:column;gap:3px;padding:7px 9px;border-radius:8px;border:1px solid var(--n-border);background:var(--n-raised);min-width:0}.wb-led-card.is-danger{border-color:var(--n-danger)}.wb-led-card.is-warn{border-left:3px solid var(--n-act)}.wb-led-card.is-muted,.wb-led-card.is-quiet{background:transparent}.wb-led-card.is-link{cursor:pointer}.wb-led-card.is-link:hover{border-color:var(--n-accent)}.wb-led-card.is-link:focus-visible{outline:2px solid var(--n-accent);outline-offset:1px}.wb-led-card-head{display:flex;align-items:flex-start;gap:6px;min-width:0}.wb-led-dir{flex:none;font-size:12px;color:var(--n-ink-muted);line-height:1.45}.wb-led-dir.is-in{color:var(--n-federal)}.wb-led-brief{flex:1 1 auto;min-width:0;font-size:12.5px;line-height:1.45;color:var(--n-ink);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}.wb-led-card.is-muted .wb-led-brief,.wb-led-card.is-quiet .wb-led-brief{color:var(--n-ink-muted)}.wb-led-card.is-danger .wb-led-brief{color:var(--n-danger)}.wb-led-brief.is-missing{font-style:italic}.wb-led-meta{display:flex;flex-wrap:wrap;gap:2px 8px;font:11px/1.45 ui-monospace,Consolas,monospace;color:var(--n-ink-muted);min-width:0}.wb-led-meta>span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}.wb-led-chip{border:1px solid var(--n-border);border-radius:99px;padding:0 6px;font-family:inherit}.wb-led-abandon{position:absolute;top:6px;right:6px;margin-left:0;padding:1px 9px;font-size:11.5px}.wb-led-abandon.is-quiet{border-color:transparent;background:transparent;color:var(--n-ink-muted)}.wb-led-abandon.is-quiet:hover{border-color:var(--n-border);color:var(--n-ink)}.wb-led-card:has(.wb-led-abandon) .wb-led-card-head{padding-right:52px}.wb-led-empty{padding:24px 8px;text-align:center;font-size:12px;color:var(--n-ink-muted)}.wb-led-forensics{font-size:11px;color:var(--n-ink-muted);border-top:1px dashed var(--n-border);padding-top:6px;margin-top:4px}.wb-led-forensics summary{cursor:pointer}.wb-led-forensics summary:focus-visible{outline:2px solid var(--n-accent);outline-offset:1px}.wb-led-forensics-body{display:flex;flex-direction:column;gap:2px;padding:4px 0 0 12px;font-family:ui-monospace,Consolas,monospace}
|