@nelsonlongxiang/dsh-open-a2a-net 0.6.25 → 0.6.27
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 +15 -11
- package/README_zh.md +3 -2
- package/assets/nexusDist/assets/index-DszoLz8i.js +5 -0
- package/assets/nexusDist/assets/index-uQf7NwjF.css +1 -0
- package/assets/nexusDist/index.html +2 -2
- package/cli/a2a.mjs +612 -0
- package/lib/card.js +17 -0
- package/lib/cli-deposit.js +141 -0
- package/lib/index.js +636 -25
- package/lib/owner-settings.js +100 -0
- package/lib/peer-store.js +65 -9
- package/lib/task-ledger.js +44 -3
- package/lib/types/cli-deposit.d.ts +53 -0
- package/lib/types/owner-settings.d.ts +19 -0
- package/lib/types/peer-store.d.ts +22 -3
- package/lib/types/task-ledger.d.ts +18 -0
- package/lib/types/types.d.ts +10 -0
- package/nexus-stage/src/canvas-ops.ts +2 -2
- package/nexus-stage/src/federation.ts +6 -0
- package/nexus-stage/src/main.ts +97 -4
- package/nexus-stage/src/planning-menus.ts +16 -4
- package/nexus-stage/src/planning-types.ts +3 -0
- package/nexus-stage/src/planning-view.ts +208 -18
- package/nexus-stage/src/planning.css +4 -0
- package/nexus-stage/src/wb-chat.ts +670 -0
- package/nexus-stage/src/wb-directory.ts +222 -0
- package/nexus-stage/src/wb-ledger.ts +266 -0
- package/nexus-stage/src/wb-rail.ts +147 -0
- package/nexus-stage/src/workbench.css +190 -84
- package/nexus-stage/src/workbench.ts +385 -721
- package/nexus-stage/src/world.ts +5 -1
- package/package.json +214 -218
- package/assets/nexusDist/assets/index-034h1cNc.js +0 -3
- package/assets/nexusDist/assets/index-PG9EieGX.css +0 -1
package/README.md
CHANGED
|
@@ -215,17 +215,20 @@ verified OriginClaim envelope (`X-A2A-Caller` / `-Url` / `-Ts` / `-Sig`,
|
|
|
215
215
|
signed with your own card key); see `docs/protocol/delivery-origin-auth.md`
|
|
216
216
|
and the rest of `docs/protocol/` for the envelope details.
|
|
217
217
|
|
|
218
|
-
**Which artifact to build against.**
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
`
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
218
|
+
**Which artifact to build against.** npm direct install already includes the
|
|
219
|
+
four subpaths: releases from 0.6.25 (badge `latest`) carry them, so
|
|
220
|
+
`npm install @nelsonlongxiang/dsh-open-a2a-net` works out of the box —
|
|
221
|
+
see `examples/external-node/` for a runnable external-node example that
|
|
222
|
+
exercises all four subpaths against an embedded mock peer. The subpath
|
|
223
|
+
exports landed in commit `9cb3852`; versions before that (public 0.5.15
|
|
224
|
+
included) predate the admission rules and the OriginClaim envelope above,
|
|
225
|
+
and importing the subpaths from them fails with
|
|
226
|
+
`ERR_PACKAGE_PATH_NOT_EXPORTED` — the historical recipe (pin a commit,
|
|
227
|
+
`pnpm build`, `npm pack`, depend on the tarball) survives below for
|
|
228
|
+
pre-0.6.25 deployments only:
|
|
227
229
|
|
|
228
230
|
```bash
|
|
231
|
+
# HISTORICAL (0.5.15 and earlier): build the package from a pinned commit
|
|
229
232
|
git clone https://github.com/NelsonLongxiang/dsh-open-a2a-net && cd dsh-open-a2a-net
|
|
230
233
|
git checkout <commit> # pin one; any commit at or after 9cb3852 exports the subpaths
|
|
231
234
|
pnpm install --frozen-lockfile # pnpm version from package.json "packageManager"
|
|
@@ -235,8 +238,9 @@ npm pack # → nelsonlongxiang-dsh-open-a2a-net-<versi
|
|
|
235
238
|
npm install /path/to/nelsonlongxiang-dsh-open-a2a-net-<version>.tgz
|
|
236
239
|
```
|
|
237
240
|
|
|
238
|
-
Installing
|
|
239
|
-
|
|
241
|
+
Installing the package (npm or the historical tarball) pulls no
|
|
242
|
+
`@deepseek-ai/*` package: the DSH peers are optional and the four
|
|
243
|
+
subpaths import only each other and `node:crypto`.
|
|
240
244
|
|
|
241
245
|
## License
|
|
242
246
|
|
package/README_zh.md
CHANGED
|
@@ -125,9 +125,10 @@ import { A2aClient } from '@nelsonlongxiang/dsh-open-a2a-net/a2a-client'
|
|
|
125
125
|
|
|
126
126
|
外部节点需要自己实现三样东西:签名卡片、`GET /.well-known/agent-card.json` 和 `POST /a2a/direct`,这些模块编码的线上格式就是契约。匿名取卡只能拿到最小发现面。要拿完整卡片,必须带上通过验证的 OriginClaim 信封,即用你自己的卡片密钥签名的 `X-A2A-Caller` / `-Url` / `-Ts` / `-Sig`,细节见 `docs/protocol/delivery-origin-auth.md` 及 `docs/protocol/` 下其余文档。
|
|
127
127
|
|
|
128
|
-
**按哪个产物实现。**
|
|
128
|
+
**按哪个产物实现。** npm 直装已含四个子路径:自 0.6.25 起(徽章 `latest`)的正式版带齐这批导出,`npm install @nelsonlongxiang/dsh-open-a2a-net` 开箱即用——`examples/external-node/` 有一个可对内嵌 mock peer 跑通全部四个子路径的外部节点参考实现。子路径导出随提交 `9cb3852` 落地;更早的版本(含公开 0.5.15)早于这批导出,也早于上述准入规则和 OriginClaim 信封,从它们引入会报 `ERR_PACKAGE_PATH_NOT_EXPORTED`——历史上的做法(钉提交、`pnpm build`、`npm pack`、依赖 tarball)仅留作 0.6.25 之前部署的历史注:
|
|
129
129
|
|
|
130
130
|
```bash
|
|
131
|
+
# 历史做法(0.5.15 及更早):从钉住的提交自行构建
|
|
131
132
|
git clone https://github.com/NelsonLongxiang/dsh-open-a2a-net && cd dsh-open-a2a-net
|
|
132
133
|
git checkout <commit> # 钉一个提交;9cb3852 及之后的提交都导出这四个子路径
|
|
133
134
|
pnpm install --frozen-lockfile # pnpm 版本以 package.json 的 "packageManager" 为准
|
|
@@ -137,7 +138,7 @@ npm pack # → nelsonlongxiang-dsh-open-a2a-net-<versi
|
|
|
137
138
|
npm install /path/to/nelsonlongxiang-dsh-open-a2a-net-<version>.tgz
|
|
138
139
|
```
|
|
139
140
|
|
|
140
|
-
|
|
141
|
+
安装这个包(npm 或历史 tarball)不会拉入任何 `@deepseek-ai/*` 包:DSH peer 依赖都是可选的,四个子路径只互相引用,外加 `node:crypto`。
|
|
141
142
|
|
|
142
143
|
## 许可证
|
|
143
144
|
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
var Xn=Object.defineProperty;var Jn=(t,e,o)=>e in t?Xn(t,e,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[e]=o;var xt=(t,e,o)=>Jn(t,typeof e!="symbol"?e+"":e,o);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))s(n);new MutationObserver(n=>{for(const r of n)if(r.type==="childList")for(const a of r.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&s(a)}).observe(document,{childList:!0,subtree:!0});function o(n){const r={};return n.integrity&&(r.integrity=n.integrity),n.referrerPolicy&&(r.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?r.credentials="include":n.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function s(n){if(n.ep)return;n.ep=!0;const r=o(n);fetch(n.href,r)}})();const Yt=6e4;function zn(t,e,o=Date.now){let s=-Yt;return{fault(n){const r=o();r-s>=Yt&&(e(`[nexus] ${n}`),s=r),t.show(n)},clear(){t.hide(),s=-Yt}}}const Vn=60*6e4;function kt(t){var e;return t.direction==="inbound"||t.direction===void 0&&((e=t.peer)==null?void 0:e.startsWith("local:"))===!0}function mn(t){var e;return((e=t.peer)==null?void 0:e.startsWith("local:"))===!0?t.peer.slice(6):void 0}function Ft(t,e){return t.settleable!==void 0?t.settleable===!1:e-t.startedAt>=Vn}function zt(t,e){const o=(t.tasks??[]).filter(a=>a.receiptExpected!==!1),s=o.filter(a=>!kt(a)&&Ft(a,e)),n=o.filter(a=>kt(a)&&Ft(a,e)),r=t.tasksDead??[];return{stale:s,owedOverdue:n,deadLetters:r.filter(a=>a.reason!=="fire-forget"),expired:r.filter(a=>a.reason==="fire-forget")}}function ye(t,e){const o=document.createElement(t);return e!==void 0&&(o.className=e),o}function un(t,e){const o=Math.max(0,Math.round((e-t)/1e3));if(o<90)return`${o}s`;const s=Math.round(o/60);if(s<90)return`${s}m`;const n=Math.round(s/60);return n<48?`${n}h`:`${Math.round(n/24)}d`}function Lt(t,e,o,s,n){const r=ye("div",`wb-led-tile${n!==void 0?` is-${n}`:""}`);r.title=s,r.appendChild(ye("span","wb-led-tile-v")).textContent=String(o),r.appendChild(ye("span","wb-led-tile-k")).textContent=e,t.appendChild(r)}const Vt=[{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 qn(t,e,o){const s=ye("div","wb-led-split"),n=ye("div","wb-led-split-bar");n.setAttribute("role","img");const r=ye("div","wb-led-split-legend"),a=new Set(Vt.map(c=>c.key)),u=Vt.map(c=>[c.tone,c.label,e[c.key]??0]);for(const[c,S]of Object.entries(e))a.has(c)||u.push(["other",c,S]);const C=[];for(const[c,S,R]of u){if(R<=0)continue;const K=ye("span",`wb-led-seg is-${c}`);K.style.width=`${Math.max(2,R/o*100)}%`,n.appendChild(K);const D=ye("span","wb-led-split-item");D.appendChild(ye("i",`wb-led-swatch is-${c}`)),D.appendChild(document.createTextNode(`${S} ${R}`)),r.appendChild(D),C.push(`${S} ${R}`)}n.setAttribute("aria-label",`归档结局:${C.join(",")}`),s.append(n,r),t.appendChild(s)}function Gn(t,e){var $e;t.replaceChildren();const{state:o,now:s}=e,n=o.tasks??[],r=o.tasksDead??[],a=o.archivedCount??0,u=zt(o,s),C=n.filter($=>$.receiptExpected===!1),c=n.filter($=>$.receiptExpected!==!1),S=c.filter($=>kt($)),R=c.filter($=>!kt($)),K=u.stale,D=R.filter($=>!Ft($,s)),q=u.stale.length,we=ye("div","wb-led-tiles");Lt(we,"待回执",n.length,"等待回执的任务(pending),含陈旧与免回执行"),Lt(we,"陈旧",q,"我方派发、要回执、已等待 ≥1h 仍未回执(可催办);本机欠对方的入站行在「待本机回执」组另计,免回执行不算陈旧",q>0?"warn":void 0),Lt(we,"死信",u.deadLetters.length,"超过 24h TTL 仍未结算(unconsumed);需清账(abandon)才能移出。免回执到期另列,不算死信",u.deadLetters.length>0?"danger":void 0),Lt(we,"已归档",a,"已离开台账并留档的任务(结算、拒绝或放弃),用于审计"),t.appendChild(we),a>0&&o.archivedSplit!==void 0&&qn(t,o.archivedSplit,a);const ae=($,z)=>{const oe=ye("div",`wb-led-card is-${z.tone}`),pe=ye("div","wb-led-card-head");pe.appendChild(ye("span",`wb-led-dir${z.inbound?" is-in":""}`)).textContent=z.inbound?"↙":"↗";const Q=ye("span","wb-led-brief");Q.textContent=z.brief!==void 0&&z.brief!==""?z.brief:"(无摘要——派发未带 brief)",(z.brief===void 0||z.brief==="")&&Q.classList.add("is-missing"),pe.appendChild(Q),oe.appendChild(pe);const U=ye("div","wb-led-meta");U.appendChild(ye("span","wb-led-team")).textContent=z.inbound?`来自 ${z.sender??"对端"}`:`发往 ${z.team}`,z.inbound&&(U.appendChild(ye("span","wb-led-to")).textContent=`至 ${z.team}`),U.appendChild(ye("span")).textContent=z.atText,U.appendChild(ye("span","wb-led-task")).textContent=z.taskId;for(const ue of z.chips)U.appendChild(ye("span","wb-led-chip")).textContent=ue;if(oe.appendChild(U),oe.title=`${z.taskId}
|
|
2
|
+
${z.team}`,z.dead!==void 0){const ue=z.dead,ne=ye("button","wb-btn wb-led-abandon");ne.type="button",ne.textContent="清账",ne.title="从台账移出这条死信(abandon)",ne.addEventListener("click",_e=>{_e.stopPropagation(),ne.disabled=!0,e.abandon(ue.taskId,"workbench dead-letter cleanup").then(Oe=>{ne.disabled=!1,ne.textContent=Oe?"已清":"失败"})}),oe.appendChild(ne)}if(e.canOpenTeam(z.team)){oe.classList.add("is-link"),oe.setAttribute("role","button"),oe.tabIndex=0,oe.setAttribute("aria-label",`${Q.textContent},打开 ${z.team} 的对话`);const ue=()=>{e.openTeam(z.team)};oe.addEventListener("click",ue),oe.addEventListener("keydown",ne=>{(ne.key==="Enter"||ne.key===" ")&&(ne.preventDefault(),ue())})}$.appendChild(oe)},w=($,z,oe,pe)=>{if(z===0)return null;const Q=ye("div",`wb-led-group is-${oe}`),U=ye("div","wb-led-group-head");return U.appendChild(ye("span")).textContent=`${$} · ${z}`,U.appendChild(ye("span","wb-led-group-hint")).textContent=pe,Q.appendChild(U),t.appendChild(Q),Q},E=($,z)=>{const oe=kt($);return{brief:$.brief,team:$.team,sender:mn($),taskId:$.taskId,atText:`${un($.startedAt,s)} 前${oe?"收到":"派发"}`,inbound:oe,tone:z,chips:[...$.settleable===!0?["可结算"]:[],...$.receiptExpected===!1?["无回执债"]:[],...oe?["入站"]:[],...$.status!=="pending"?[$.status]:[]]}},H=($,z,oe)=>({brief:$.brief,team:$.team,sender:mn($),taskId:$.taskId,atText:`${un($.deadAt,s)} 前${oe}`,inbound:kt($),tone:z,dead:$,chips:$.reason!==void 0&&$.reason!==""&&$.reason!=="unspecified"&&$.reason!=="fire-forget"?[$.reason]:[]}),h=w("死信",u.deadLetters.length,"danger","需清账");if(h!==null)for(const $ of[...u.deadLetters].sort((z,oe)=>oe.deadAt-z.deadAt))ae(h,H($,"danger","死信"));const f=w("陈旧",K.length,"warn","我方派发 ≥1 小时仍无回执,可催办");if(f!==null)for(const $ of[...K].sort((z,oe)=>z.startedAt-oe.startedAt))ae(f,E($,"warn"));const N=u.owedOverdue.length,v=w("待本机回执",S.length,N>0?"warn":"quiet",N>0?`对方在等本机回执 · ${N} 条超过 1 小时`:"对方在等本机回执");if(v!==null)for(const $ of[...S].sort((z,oe)=>z.startedAt-oe.startedAt))ae(v,E($,Ft($,s)?"warn":"quiet"));const L=w("等待回执",D.length,"quiet","1 小时内");if(L!==null)for(const $ of[...D].sort((z,oe)=>oe.startedAt-z.startedAt))ae(L,E($,"quiet"));const b=w("免回执",C.length,"muted","不等回执,24h 后自动归档");if(b!==null)for(const $ of C)ae(b,E($,"muted"));const P=w("已过期(免回执)",u.expired.length,"muted","正常记账,不是失败");if(P!==null)for(const $ of[...u.expired].sort((z,oe)=>oe.deadAt-z.deadAt))ae(P,H($,"muted","过期"));n.length+r.length===0&&(t.appendChild(ye("div","wb-led-empty")).textContent="台账为空——没有待回执的任务");const O=o.idempotency,me=($e=o.reconcile)==null?void 0:$e.state;if(O!==void 0||me!==void 0){const $=ye("details","wb-led-forensics wb-forensics");$.appendChild(ye("summary")).textContent="取证";const z=ye("div","wb-led-forensics-body");O!==void 0&&(z.appendChild(ye("div")).textContent=`幂等 claims ${O.claimsFresh??0} · replays ${O.replays??0} · conflicts ${O.conflicts??0}`),me!==void 0&&(z.appendChild(ye("div")).textContent=`reconcile ${me}`),$.appendChild(z),t.appendChild($)}const Ee=c.length+u.deadLetters.length;return{badge:Ee>0?String(Ee):"",tone:u.deadLetters.length>0?"danger":q>0||N>0?"warn":void 0}}function mt(t){return t.name??t.team??t.label??""}const Nt=4e3,Qn=60*60*1e3,Zn=32;function ge(t,e){const o=document.createElement(t);return e!==void 0&&(o.className=e),o}function It(t,e,o=""){const s=ge("button",`wb-icon-btn wb-chat-act ${o}`.trim());return s.type="button",s.setAttribute("aria-label",t),s.title=t,s.textContent=e,s}function Wt(t,e){const o=Math.max(0,Math.round((e-t)/1e3));if(o<60)return"刚刚";const s=Math.round(o/60);if(s<60)return`${s} 分钟前`;const n=Math.round(s/60);return n<48?`${n} 小时前`:`${Math.round(n/24)} 天前`}function eo(t){return t>=1e6?`${(t/1e6).toFixed(1)} MB`:t>=1e3?`${Math.round(t/1e3)} KB`:`${t} B`}function Kt(t){const e=t.kind==="session"||t.kind==="remote"?t.team:void 0;return e!==void 0&&e!==""?e:void 0}function fn(t){return t.kind==="remote"?`remote:${t.team}`:`${t.kind}:${t.id}`}function to(t){let e=null,o=null,s=!1,n=!1;const r=new Map,a=new Map,u=new Map,C=new Map,c=new Set,S=new Map,R=new Map,K=ge("aside","wb-chat");K.setAttribute("aria-label","对话");const D=ge("div","wb-chat-head"),q=It("返回会话列表","‹","wb-chat-back"),we=ge("span","wb-chat-dot"),ae=ge("div","wb-chat-titles"),w=ge("span","wb-chat-title"),E=ge("span","wb-chat-sub");ae.append(w,E);const H=It("刷新对话","↻","wb-chat-refresh"),h=It("会话详情","ⓘ","wb-chat-info-btn");h.setAttribute("aria-expanded","false");const f=It("关闭对话","✕","wb-chat-close");D.append(q,we,ae,H,h,f);const N=ge("div","wb-chat-info");N.hidden=!0;const v=ge("div","wb-chat-thread");v.setAttribute("role","log"),v.setAttribute("aria-live","polite"),v.tabIndex=0;const L=ge("div","wb-chat-notice"),b=ge("div","wb-chat-log"),P=ge("div","wb-chat-sent");v.append(L,b,P);const O=ge("div","wb-chat-foot");K.append(D,N,v,O),q.addEventListener("click",()=>{(e==null?void 0:e.kind)==="peer"&&(e.picked=void 0,tt())}),H.addEventListener("click",()=>{if(e===null)return;const l=me(e);l!==void 0&&r.delete(l),e.kind==="peer"&&e.picked===void 0&&e.url!==void 0&&u.delete(`peer:${e.url}`),Oe(!0)}),h.addEventListener("click",()=>{n=!n,N.hidden=!n,h.setAttribute("aria-expanded",String(n))}),f.addEventListener("click",()=>Xe()),v.addEventListener("scroll",()=>{const l=e!==null?me(e):void 0;l!==void 0&&a.set(l,v.scrollTop)}),document.addEventListener("keydown",l=>{if(l.key!=="Escape"||!K.classList.contains("is-open"))return;const I=l.target;if(I instanceof HTMLElement){if(!K.contains(I)){const A=I instanceof HTMLTextAreaElement||I instanceof HTMLInputElement||I.isContentEditable,G=I.closest(".wb-stage-board")!==null;if(A||G)return}Xe()}});function me(l){if(l.kind==="session"||l.kind==="log")return t.sessionLog!==void 0?`local:${l.id}`:void 0;if(l.kind==="remote")return t.remoteSessionLog!==void 0?`remote:${l.team}`:void 0;if(l.picked!==void 0&&l.url!==void 0&&t.remoteSessionLog!==void 0)return`peer:${l.url}:${l.picked}`}function Ee(l){var I,A,G;return l.kind==="session"||l.kind==="log"?((I=t.sessionLog)==null?void 0:I.call(t,l.id))??Promise.resolve({ok:!1,error:"sessionLog unavailable"}):l.kind==="remote"?((A=t.remoteSessionLog)==null?void 0:A.call(t,{team:l.team}))??Promise.resolve({ok:!1,error:"remoteSessionLog unavailable"}):((G=t.remoteSessionLog)==null?void 0:G.call(t,{peer:l.url,id:l.picked}))??Promise.resolve({ok:!1,error:"remoteSessionLog unavailable"})}function $e(){const l=e;if(l===null)return;const I=l.kind==="log"||l.kind==="remote"||l.kind==="session"&&l.live===!1;we.className=`wb-chat-dot ${l.kind==="peer"?"is-peer":I?"is-cold":"is-live"}`,we.title=l.kind==="peer"?"对端主机":l.kind==="log"?"只读日志":l.kind==="remote"?"远端会话":l.live===!1?"冷会话":"在线",w.textContent=l.kind==="peer"&&l.picked!==void 0?`…${l.picked.slice(-12)}`:l.title,E.textContent=l.kind==="peer"&&l.picked!==void 0?l.title:l.sub,q.hidden=!(l.kind==="peer"&&l.picked!==void 0)}function $(l,I){const A=ge("div","wb-kv");A.appendChild(ge("span","wb-kv-k")).textContent=l,A.appendChild(ge("span","wb-kv-v")).textContent=I,N.appendChild(A)}function z(){var I,A,G;N.replaceChildren();const l=e;l!==null&&(l.kind==="session"?($("会话",l.id),l.team!==void 0&&$("路由",l.team),$("来源","本机会话日志")):l.kind==="log"?($("会话",l.id),$("来源","本机会话日志(不在网络目录)")):l.kind==="remote"?($("路由",l.team),((I=l.row)==null?void 0:I.origin)!==void 0&&$("来源",l.row.origin),((A=l.row)==null?void 0:A.via)!==void 0&&$("经",l.row.via),((G=l.row)==null?void 0:G.workspace)!==void 0&&$("工作区",l.row.workspace)):($("对端",l.url??l.sub),l.picked!==void 0&&$("会话",l.picked),$("来源","经本机代理读取对端 /a2a/log")))}function oe(l){return l.kind==="log"?"只读日志 —— 此会话当前不在网络目录(可能已归档或未入网)。":l.kind==="remote"?t.remoteSessionLog!==void 0?"远端会话 —— 经本机代理从对端 /a2a/log 读取最近对话。":"远端节点的对话记录在对端机器上;本页的代理读取面未启用。":l.kind==="peer"?l.url===void 0||t.remoteSessionLog===void 0?`对端主机节点(${l.sub})—— 会话记录存放在对端机器上,本页只读本机会话日志。`:l.picked===void 0?"对端主机 —— 选择一个会话阅读(经本机代理读取对端 /a2a/log)。":"":t.sessionLog===void 0?"本页未接入会话日志读取,只显示从这里发出的消息。":""}function pe(){return v.scrollHeight-v.scrollTop-v.clientHeight<=Zn}function Q(l){const I=()=>{v.scrollTop=v.scrollHeight};I(),requestAnimationFrame(I)}function U(l,I){const A=ge("div",`wb-chat-empty${I==="error"?" is-error":""}`);return A.textContent=l,A}function ue(l,I){const A=l==="user",G=ge("div",`wb-msg ${A?"wb-msg-user":"wb-msg-assistant"}`),B=ge("span","wb-msg-who");B.textContent=A?"问":"答";const le=ge("div","wb-msg-text");return le.textContent=I,G.append(B,le),G}function ne(l){if(b.replaceChildren(),l===void 0){b.appendChild(U("读取中…"));return}if(l.ok!==!0||l.messages===void 0){b.appendChild(U(`无法读取(${l.error??"未知错误"})`,"error"));return}if(l.messages.length===0){b.appendChild(U("暂无对话记录"));return}for(const I of l.messages)b.appendChild(ue(I.role,I.text))}function _e(l,I){if(b.replaceChildren(),I===void 0){b.appendChild(U("读取中…"));return}if(I.ok!==!0||I.sessions===void 0){b.appendChild(U(`无法读取(${I.error??"未知错误"})`,"error"));return}if(I.sessions.length===0){b.appendChild(U("对端没有可读会话"));return}const A=ge("div","wb-chat-sessions"),G=t.now();for(const B of I.sessions){const le=ge("button","wb-chat-session");le.type="button",le.appendChild(ge("span","wb-chat-session-id")).textContent=`…${B.id.slice(-12)}`;const he=[B.mtimeMs!==void 0?Wt(B.mtimeMs,G):"",eo(B.sizeBytes)].filter(Boolean).join(" · ");le.appendChild(ge("span","wb-chat-session-meta")).textContent=he,le.title=B.id,le.addEventListener("click",()=>{(e==null?void 0:e.kind)!=="peer"||e.url!==l||(e.picked=B.id,tt())}),A.appendChild(le)}b.appendChild(A)}function Oe(l=!1){const I=e;if(I===null)return;if(L.textContent=oe(I),L.hidden=L.textContent==="",I.kind==="peer"&&I.picked===void 0){if(I.url===void 0||t.remoteSessionLog===void 0){b.replaceChildren();return}const B=I.url,le=`peer:${B}`;if(!l&&u.has(le)){_e(B,u.get(le));return}u.set(le,void 0),_e(B,void 0),t.remoteSessionLog({peer:B}).then(he=>{u.set(le,he),(e==null?void 0:e.kind)==="peer"&&e.url===B&&e.picked===void 0&&_e(B,he)},he=>{const se={ok:!1,error:he instanceof Error?he.message:String(he)};u.set(le,se),(e==null?void 0:e.kind)==="peer"&&e.url===B&&e.picked===void 0&&_e(B,se)});return}const A=me(I);if(A===void 0){b.replaceChildren(),Ye(!0);return}const G=()=>{const B=a.get(A);B===void 0||l?Q():(v.scrollTop=B,requestAnimationFrame(()=>{e!==null&&me(e)===A&&(v.scrollTop=B)}))};if(!l&&r.has(A)&&r.get(A)!==void 0){ne(r.get(A)),Ye(!0),G();return}l&&a.delete(A),r.set(A,void 0),ne(void 0),Ye(!0),Ee(I).then(B=>{var le;r.set(A,B),(B==null?void 0:B.ok)===!0&&B.messages!==void 0&&((le=t.onTranscript)==null||le.call(t,I,B.messages)),!(e===null||me(e)!==A)&&(ne(B),Ye(),G())},B=>{const le={ok:!1,error:B instanceof Error?B.message:String(B)};r.set(A,le),e!==null&&me(e)===A&&ne(le)})}function Be(l){return((o==null?void 0:o.tasks)??[]).filter(I=>I.team===l)}function Ie(l){return((o==null?void 0:o.tasksDead)??[]).filter(I=>I.team===l)}let Fe="";function pt(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 He(l,I){const A=l.direction==="inbound";if(l.receiptExpected===!1)return{text:A?"来信 · 无需回执":"已送达 · 无回执",tone:"muted",hint:"免回执消息:不等回执,24h 后自动归档"};const G=I-l.startedAt>Qn;return{text:`${G?"陈旧":A?"待本机回执":"待回执"} · ${l.status}`,tone:G?"warn":"wait",hint:`${A?"对方等待本机回执;":""}派发于 ${Wt(l.startedAt,I)}`}}function Ue(l,I){const A=`结算于 ${Wt(l.resolvedAt,I)}`;if(l.endedBy==="abandoned"||l.endedBy==="cancelled"){const he=l.endedBy==="cancelled"?"撤回":"放弃";return l.late===!0?{text:`已${he} · 回执迟到`,tone:"warn",hint:`${A};本机${he}之后对方回执才到,结局不改写`}:{text:`已${he}`,tone:"muted",hint:`${A};本机${he},未等到回执`}}if(l.endedBy==="echo")return{text:"已结算 · 内容回显",tone:"ok",hint:`${A};对方回了内容但未带正式回执,按内容回显结算`};if(l.endedBy===void 0&&l.outcome==="abandoned")return{text:"已放弃(本机或对方)",tone:"muted",hint:`${A};本机放弃或撤回,或对方回执报告放弃`};const G=l.summary!==void 0&&l.summary!==""?` · ${l.summary}`:"";if(l.outcome==="abandoned")return{text:"已回执 · 对方放弃",tone:"warn",hint:`${A};对方回执报告放弃${G}`};const B=Vt.find(he=>he.key===l.outcome),le=(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:`${A};回执未带结论${G}`}:{text:`已回执 · ${(B==null?void 0:B.label)??l.outcome}`,tone:le,hint:`${A}${G}`}}function Te(l,I,A){const G=Ie(I).find(he=>he.taskId===l);if(G!==void 0)return pt(G);const B=Be(I).find(he=>he.taskId===l);if(B!==void 0)return He(B,A);const le=((o==null?void 0:o.archived)??[]).find(he=>he.taskId===l&&he.team===I);return le!==void 0?Ue(le,A):c.has(l)?{text:"已离开台账",tone:"muted",hint:"已结算、放弃或撤回之一;主机未给出这条的结局(旧主机,或已超出最近 64 条归档)"}:{text:"已派发",tone:"muted",hint:"异步送达;回执到达后进台账"}}function Ke(l){const I=t.now(),A=C.get(l)??[],G=new Set(A.map(Z=>Z.taskId).filter(Z=>Z!==void 0)),B=Z=>Z!==void 0&&Z!==""?Z:"(无摘要)",le=Be(l).filter(Z=>!G.has(Z.taskId)).map(Z=>({at:Z.startedAt,side:Z.direction==="inbound"?"theirs":"mine",text:B(Z.brief),status:He(Z,I),taskId:Z.taskId})),he=Ie(l).filter(Z=>!G.has(Z.taskId)).map(Z=>{var x;const Ae=Z.direction??S.get(Z.taskId)??(((x=Z.peer)==null?void 0:x.startsWith("local:"))===!0?"inbound":void 0);return{at:Z.startedAt,side:Ae==="inbound"?"theirs":Ae==="outbound"?"mine":"system",text:B(Z.brief),status:pt(Z),taskId:Z.taskId}}),se=A.map(Z=>({at:Z.at,side:"mine",text:Z.text,status:Z.state==="sending"?{text:"发送中…",tone:"muted"}:Z.state==="failed"?{text:`失败:${Z.error??"未知原因"}`,tone:"danger"}:Z.taskId!==void 0?Te(Z.taskId,l,I):{text:"已派发",tone:"muted"},taskId:Z.taskId}));return[...le,...he,...se].sort((Z,Ae)=>Z.at-Ae.at)}function Ye(l=!1){const I=e,A=I!==null?Kt(I):void 0,G=A!==void 0?Ke(A):[],B=JSON.stringify([A??"",...G.map(se=>[se.taskId??"",se.side,se.text,se.status.text])]);if(!l&&B===Fe)return;Fe=B;const le=pe();if(P.replaceChildren(),G.length===0)return;const he=ge("div","wb-chat-divider");he.textContent="台账往来 · 异步送达,回执进台账",P.appendChild(he);for(const se of G){const Z=se.side==="mine"?"wb-msg wb-msg-user wb-msg-out":se.side==="theirs"?"wb-msg wb-msg-assistant wb-msg-in":"wb-msg wb-msg-ledger",Ae=ge("div",Z);Ae.appendChild(ge("span","wb-msg-who")).textContent=se.side==="mine"?"我":se.side==="theirs"?"对方":"台账记录",Ae.appendChild(ge("div","wb-msg-text")).textContent=se.text;const x=ge("div","wb-msg-meta");se.taskId!==void 0&&(x.appendChild(ge("span","wb-msg-task")).textContent=se.taskId);const p=ge("span",`wb-msg-status is-${se.status.tone}`);p.textContent=se.status.text,se.status.hint!==void 0&&(p.title=se.status.hint),x.appendChild(p),Ae.appendChild(x),P.appendChild(Ae)}le&&Q()}function ht(l){const I=l.text.value.length;l.note.classList.remove("is-error"),l.note.textContent=I>Nt*.9?`${I}/${Nt}`:"Enter 发送 · Shift+Enter 换行",I>Nt&&l.note.classList.add("is-error"),l.submit.disabled=l.text.value.trim()===""||I>Nt}function et(l){l.style.height="auto",l.style.height=`${Math.min(l.scrollHeight,160)}px`}function Ve(l){const I=ge("form","wb-dispatch-form wb-chat-composer"),A=document.createElement("textarea");A.className="wb-dispatch-text",A.rows=1,A.placeholder="发一句话任务给这个节点…",A.setAttribute("aria-label","发送消息");const G=ge("button","wb-dispatch-submit");G.type="submit",G.textContent="发送",G.setAttribute("aria-label","发送");const B=ge("div","wb-dispatch-note");B.setAttribute("aria-live","polite");const le=ge("div","wb-chat-composer-row");le.append(A,G),I.append(le,B);const he={team:l,form:I,text:A,note:B,submit:G};return A.addEventListener("input",()=>{et(A),ht(he)}),A.addEventListener("keydown",se=>{se.key!=="Enter"||se.shiftKey||se.ctrlKey||se.altKey||se.metaKey||se.isComposing||(se.preventDefault(),I.requestSubmit())}),I.addEventListener("submit",se=>{se.preventDefault();const Z=A.value.trim();if(Z===""||Z.length>Nt||t.dispatchQuick===void 0)return;const Ae={text:Z,at:t.now(),state:"sending"},x=C.get(l)??[];x.push(Ae),C.set(l,x),A.value="",et(A),ht(he),A.focus({preventScroll:!0}),Ye(),Q(),t.dispatchQuick(l,Z).then(p=>p,p=>({ok:!1,error:p instanceof Error?p.message:String(p)})).then(p=>{p.ok===!0?(Ae.state="sent",Ae.taskId=p.task_id,B.classList.remove("is-error"),B.textContent=`已派发${p.task_id!==void 0?` · ${p.task_id}`:""} · 回执将入台账`):(Ae.state="failed",Ae.error=p.error??"未知原因",A.value===""&&(A.value=Z,et(A)),B.classList.add("is-error"),B.textContent=`失败:${Ae.error}`,G.disabled=A.value.trim()===""),e!==null&&Kt(e)===l&&Ye()})}),ht(he),he}function st(){const l=e;if(O.replaceChildren(),l===null)return;const I=Kt(l);if(I!==void 0&&t.dispatchQuick!==void 0){let G=R.get(I);G===void 0&&(G=Ve(I),R.set(I,G)),O.appendChild(G.form),s&&(s=!1,G.text.focus({preventScroll:!0}));return}s=!1;const A=ge("div","wb-chat-readonly");A.textContent=l.kind==="log"?"只读日志:此会话不在网络目录,不能从这里派发。":l.kind==="peer"?"对端主机:选择会话阅读;要派发请打开它的远端会话节点。":"此节点没有可派发的路由。",O.appendChild(A)}function tt(){$e(),z(),Oe(),st()}function dt(l){const I=e!==null&&fn(e)===fn(l);e=l,I||(s=!0),tt(),K.classList.add("is-open")}function Xe(){e=null,K.classList.remove("is-open")}function qe(l){o=l;for(const A of(l==null?void 0:l.tasks)??[])c.add(A.taskId),S.set(A.taskId,A.direction==="inbound"?"inbound":"outbound");const I=e;if(I!==null){if(I.kind==="session"&&l!==null){const A=(l.sessions??[]).find(G=>G.id===I.id);A!==void 0&&(I.title=mt(A),I.live=A.live)}$e(),Ye()}}return{root:K,open:dt,close:Xe,isOpen:()=>e!==null,update:qe}}const An="dsh-a2a.rail.tab";function no(){try{return window.localStorage.getItem(An)}catch{return null}}function oo(t){try{window.localStorage.setItem(An,t)}catch{}}function so(t,e={}){var ae;const o=document.createElement("aside");o.className="wb-rail";const s=document.createElement("div");s.className="wb-tabs",s.setAttribute("role","tablist"),s.setAttribute("aria-label","工作台侧栏");const n=document.createElement("div");n.className="wb-tabpanels",o.append(s,n);const r=new Map,a=new Map,u=new Map,C=new Set;for(const w of t){const E=document.createElement("button");E.type="button",E.className="wb-tab",E.id=`wb-tab-${w.key}`,E.dataset.sec=w.key,E.setAttribute("role","tab"),E.setAttribute("aria-controls",`wb-panel-${w.key}`);const H=document.createElement("span");H.className="wb-tab-label",H.textContent=w.label;const h=document.createElement("span");h.className="wb-tab-badge",E.append(H,h),E.addEventListener("click",()=>D(w.key)),s.appendChild(E);const f=document.createElement("section");f.className="wb-tabpanel",f.id=`wb-panel-${w.key}`,f.dataset.sec=w.key,f.setAttribute("role","tabpanel"),f.setAttribute("aria-labelledby",E.id),f.tabIndex=-1,n.appendChild(f),r.set(w.key,E),a.set(w.key,f),u.set(w.key,h)}const c=()=>t.map(w=>w.key).filter(w=>!C.has(w)),S=no();let R=((ae=t.find(w=>w.key===S))==null?void 0:ae.key)??t[0].key;s.addEventListener("keydown",w=>{const E=c(),H=E.indexOf(R);let h;w.key==="ArrowRight"?h=E[(H+1)%E.length]:w.key==="ArrowLeft"?h=E[(H-1+E.length)%E.length]:w.key==="Home"?h=E[0]:w.key==="End"&&(h=E[E.length-1]),h!==void 0&&(w.preventDefault(),D(h,{focus:!0}))});function K(){for(const w of t){const E=w.key===R,H=r.get(w.key);H.setAttribute("aria-selected",String(E)),H.tabIndex=E?0:-1,H.classList.toggle("is-active",E),H.hidden=C.has(w.key),a.get(w.key).hidden=!E}}function D(w,E={}){var h;if(C.has(w))return;const H=w!==R;R=w,oo(w),K(),E.focus===!0&&r.get(w).focus(),H&&((h=e.onChange)==null||h.call(e,w))}function q(w,E,H){const h=u.get(w);h.textContent=E,h.className=`wb-tab-badge${H!==void 0?` is-${H}`:""}`}function we(w,E){E?C.add(w):C.delete(w),C.has(R)&&(R=c()[0]??t[0].key),K()}return K(),{root:o,panel:w=>a.get(w),select:D,selected:()=>R,setBadge:q,setHidden:we}}const io=[{key:"all",label:"全部",hint:"不过滤:目录全部条目"},{key:"local",label:"本机",hint:"本机会话节点(现场 + 冷启动)"},{key:"canvas",label:"队",hint:"画布队(人类手工分配的组队)"},{key:"remote",label:"远端",hint:"远端会话队(来自对端卡片)"},{key:"logs",label:"日志",hint:"本机日志:不在网络目录里的会话档案"}];function Ge(t,e){const o=document.createElement(t);return e!==void 0&&(o.className=e),o}function Tt(...t){const e=[];for(const o of t)o!==void 0&&(typeof o=="string"?e.push(o):e.push(...o));return e.join(" ").toLowerCase()}function ao(t,e){const o=Math.max(0,Math.round((e-t)/1e3));if(o<60)return"刚刚";const s=Math.round(o/60);if(s<60)return`${s} 分钟前`;const n=Math.round(s/60);return n<48?`${n} 小时前`:`${Math.round(n/24)} 天前`}function pn(t){return t>=1e6?`${(t/1e6).toFixed(1)} MB`:t>=1e3?`${Math.round(t/1e3)} KB`:`${t} B`}function ro(t,e){const o=new Date(e);o.setHours(0,0,0,0);const s=o.getTime();return t>=s?"今天":t>=s-864e5?"昨天":"更早"}function lo(t,e){var H;t.replaceChildren();const{state:o,search:s,filter:n}=e,r=s!==""||n!=="all",a=(h,f)=>(n==="all"||n===h)&&(s===""||f.includes(s)),u=(h,f,N)=>{const v=Ge("div","wb-dir-group"),L=Ge("div","wb-dir-head");return L.appendChild(Ge("span","wb-dir-head-label")).textContent=`${h} · ${f}`,N!==void 0&&(L.appendChild(Ge("span","wb-dir-head-note")).textContent=N),v.appendChild(L),t.appendChild(v),v},C=(h,f,N,v,L,b,P)=>{const O=Ge("button","wb-item");O.type="button",O.appendChild(Ge("span",`wb-dot ${f}`)).textContent=N;const me=Ge("span","wb-item-text");return me.appendChild(Ge("span","wb-item-label")).textContent=v,L!==""&&(me.appendChild(Ge("span","wb-item-sub")).textContent=L),O.appendChild(me),P!==void 0&&(O.title=P),O.addEventListener("click",b),h.appendChild(O),O},c=(h,f)=>{if(f===void 0||f.length===0)return;const N=Ge("span","wb-item-badge"),v=f.map(L=>L.slice(L.lastIndexOf("/")+1));N.textContent=`▤ ${v.slice(0,2).join(" ")}${v.length>2?` +${v.length-2}`:""}`,N.title=`画布队:${f.join(" · ")}`,h.appendChild(N)},S=(o.sessions??[]).filter(h=>a("local",Tt(mt(h),h.team,h.label,h.id,h.canvasTeams))),R=S.filter(h=>h.live===!0),K=S.filter(h=>h.live!==!0);if(S.length>0){const h=u("本机会话",S.length,K.length>0?`${R.length} 在线 · ${K.length} 冷`:void 0);for(const f of[...R,...K]){const N=f.live===!0,v=C(h,N?"wb-dot-live":"wb-dot-cold",N?"●":"○",mt(f),N?f.team:`冷 · ${f.team}`,()=>e.openChat({kind:"session",id:f.id,title:mt(f),sub:f.team,team:f.team,live:f.live}),f.id);c(v,f.canvasTeams)}}const D=(((H=o.canvas)==null?void 0:H.teams)??[]).filter(h=>a("canvas",Tt(h.name,h.team,h.members.map(f=>f.team??f.id))));if(D.length>0){const h=u("画布队",D.length);for(const f of D){const N=f.members.filter(v=>v.remote===!0).length;C(h,"wb-dot-canvas","▤",f.name,`${f.members.length} 成员${N>0?` · ${N} 远端`:""}`,()=>e.selectCanvas(f),f.team)}}const q=(o.remote??[]).filter(h=>a("remote",Tt(mt(h),h.team,h.origin,h.workspace,h.canvasTeams)));if(q.length>0){const h=u("远端节点",q.length);for(const f of q){const N=C(h,"wb-dot-remote","◇",mt(f),f.origin!==void 0&&f.origin!==""?f.origin:f.team,()=>e.openChat({kind:"remote",team:f.team,title:mt(f),sub:f.team,row:f}),f.team);c(N,f.canvasTeams)}}const we=new Set((o.sessions??[]).map(h=>h.id)),ae=e.logs.filter(h=>!we.has(h.id)&&a("logs",Tt(h.id,e.titles.get(h.id))));if(ae.length>0){const h=e.logTotal!==void 0&&e.logTotal>e.logs.length,f=u("本机日志",ae.length,h?`显示 ${e.logs.length} / 共 ${e.logTotal}`:void 0);let N="";for(const v of[...ae].sort((L,b)=>b.mtimeMs-L.mtimeMs)){const L=ro(v.mtimeMs,e.now);L!==N&&(N=L,f.appendChild(Ge("div","wb-dir-day")).textContent=L);const b=e.titles.get(v.id),P=C(f,"wb-dot-log","❐",b??`会话 …${v.id.slice(-12)}`,`${ao(v.mtimeMs,e.now)} · ${pn(v.sizeBytes)}`,()=>e.openChat({kind:"log",id:v.id,title:b??`…${v.id.slice(-12)}`,sub:"本机日志"}),`${v.id}
|
|
3
|
+
${new Date(v.mtimeMs).toLocaleString()} · ${pn(v.sizeBytes)}`);b===void 0&&P.classList.add("is-untitled")}}S.length+D.length+q.length+ae.length===0&&(t.appendChild(Ge("div","wb-dir-empty")).textContent=r?"无匹配条目":"目录为空");const w=o.sessions??[];return`${w.filter(h=>h.live===!0).length}/${w.length}`}const Ln="dsh-a2a.logtitles",co=300,hn=60;function mo(){try{const t=window.localStorage.getItem(Ln),e=t===null?null:JSON.parse(t);if(e!==null&&typeof e=="object")return new Map(Object.entries(e).filter(o=>typeof o[1]=="string"))}catch{}return new Map}function uo(t,e,o){const s=o.find(a=>a.role==="user"&&a.text.trim()!=="")??o.find(a=>a.text.trim()!=="");if(s===void 0)return!1;const n=s.text.trim().split(`
|
|
4
|
+
`)[0].trim(),r=n.length>hn?`${n.slice(0,hn-1)}…`:n;if(t.get(e)===r)return!1;for(t.delete(e),t.set(e,r);t.size>co;)t.delete(t.keys().next().value);try{window.localStorage.setItem(Ln,JSON.stringify(Object.fromEntries(t)))}catch{}return!0}function it(t){return t.name??t.team??t.label??""}function Mt(t,e){const o=Math.max(0,Math.round((e-t)/1e3));if(o<90)return`${o}s`;const s=Math.round(o/60);if(s<90)return`${s}m`;const n=Math.round(s/60);return n<48?`${n}h`:`${Math.round(n/24)}d`}function M(t,e){const o=document.createElement(t);return e!==void 0&&(o.className=e),o}function bn(t,e,o){const s=M("div","wb-kv");s.appendChild(M("span","wb-kv-k")).textContent=e,s.appendChild(M("span","wb-kv-v")).textContent=o,t.appendChild(s)}function fo(t){try{return new URL(t).host}catch{return t}}const po=[{key:"directory",label:"目录"},{key:"hosts",label:"主机"},{key:"ledger",label:"台账"},{key:"activity",label:"活动"},{key:"plan",label:"规划"}];function ho(t){const e=t.board;let o="data",s,n=null,r="",a="all",u=null,C=null,c=[],S;const R=mo();let K=!1;const D=M("div","wb");D.setAttribute("data-testid","wb-root");const q=M("header","wb-header"),we=M("button","wb-icon-btn wb-menu");we.type="button",we.dataset.testid="wb-menu",we.setAttribute("aria-label","打开目录抽屉"),we.textContent="☰",we.addEventListener("click",()=>D.classList.toggle("is-rail-open")),q.appendChild(we);const ae=M("div","wb-title");ae.appendChild(M("span","wb-title-main")).textContent="A2A 工作台";const w=M("span","wb-badge");ae.appendChild(w),q.appendChild(ae);const E=M("button","wb-icon-btn wb-owner-btn");E.type="button",E.dataset.testid="wb-owner-btn",E.setAttribute("aria-label","主人设置(三键面板)"),E.title="主人设置:入网白名单 / 可见性 / 发布",E.textContent="⚙",E.addEventListener("click",()=>{Xe=!Xe,l()}),q.appendChild(E);const H=M("div","wb-header-stats");q.appendChild(H);const h=M("button","wb-icon-btn wb-rail-toggle");h.type="button",h.dataset.testid="wb-rail-toggle",h.setAttribute("aria-label","折叠/展开侧栏"),h.textContent="◧",h.addEventListener("click",()=>{D.classList.toggle("is-rail-collapsed"),o==="canvas"&&e!==void 0&&e.activate()}),q.appendChild(h);const f=M("div","wb-body"),N=so(po),v=N.root,L=M("div","wb-directory"),b=M("div","wb-dir-tools"),P=document.createElement("input");P.className="wb-search",P.type="search",P.placeholder="搜索:名称 / 队 / 会话 / 节点",P.setAttribute("aria-label","统一搜索目录"),P.addEventListener("input",()=>{r=P.value.trim().toLowerCase(),He()}),b.appendChild(P);const O=M("div","wb-filters");for(const x of io){const p=M("button","wb-filter");p.type="button",p.textContent=x.label,p.dataset.filter=x.key,p.title=x.hint,p.addEventListener("click",()=>{a=x.key,He()}),O.appendChild(p)}b.appendChild(O),N.panel("directory").appendChild(b),N.panel("directory").appendChild(L);const me=M("section","wb-pane"),Ee=M("section","wb-pane"),$e=M("section","wb-pane"),$=M("section","wb-pane"),z=[["ledger",me],["activity",Ee],["plan",$e],["hosts",$]],oe=M("main","wb-stage"),pe=M("section","wb-stage-board");e!==void 0&&(pe.appendChild(e.root),oe.appendChild(pe));const Q=M("div","wb-data"),U=M("aside","wb-inspector"),ue=M("div","wb-inspector-head");ue.appendChild(M("span","wb-inspector-title")).textContent="详情";const ne=M("button","wb-icon-btn");ne.type="button",ne.setAttribute("aria-label","关闭详情"),ne.textContent="✕",ne.addEventListener("click",()=>pt(void 0)),ue.appendChild(ne),U.appendChild(ue);const _e=M("div","wb-inspector-body");U.appendChild(_e);const Oe=to({now:t.now,sessionLog:t.sessionLog,remoteSessionLog:t.remoteSessionLog,dispatchQuick:t.dispatchQuick,onTranscript:(x,p)=>{x.kind!=="log"&&x.kind!=="session"||uo(R,x.id,p)&&He()}});oe.appendChild(Q),f.appendChild(v),f.appendChild(oe),f.appendChild(U),f.appendChild(Oe.root),D.appendChild(q),D.appendChild(f);function Be(x){for(const[p,F]of z){const k=x==="canvas"?N.panel(p):Q;N.setHidden(p,x!=="canvas"),F.parentElement!==k&&k.appendChild(F)}}function Ie(){const p=e!==void 0&&e.available()?"canvas":"data";D.dataset.mode=p,pe.classList.toggle("is-hidden",p!=="canvas"),Q.classList.toggle("is-hidden",p==="canvas"),Be(p),p!==o&&(e!==void 0&&(p==="canvas"?e.activate():e.deactivate()),o=p)}function Fe(x){for(;x.firstChild!==null;)x.removeChild(x.firstChild);return x}function pt(x){s=x,((x==null?void 0:x.kind)!=="canvas"||(u==null?void 0:u.name)!==x.row.name)&&(u=null),(x==null?void 0:x.kind)!=="canvas"&&(C=null),A(),D.classList.remove("is-rail-open")}function He(){for(let p=0;p<O.children.length;p++){const F=O.children[p];F.classList.toggle("is-active",F.dataset.filter===a)}if(n===null){L.replaceChildren(M("div","wb-muted")),L.firstElementChild.textContent="载入中…",N.setBadge("directory","");return}const x=lo(L,{state:n,logs:c,logTotal:S,titles:R,search:r,filter:a,now:t.now(),openChat:le,selectCanvas:p=>pt({kind:"canvas",row:p})});N.setBadge("directory",x)}function Ue(){const x=Fe($);if(n===null){N.setBadge("hosts","");return}const p=t.now(),F=[...n.peers??[]].sort((k,_)=>{const Y=ee=>ee.link==="linked"?0:1;return Y(k)-Y(_)||(_.score??0)-(k.score??0)});if(N.setBadge("hosts",F.length>0?`${F.filter(k=>k.link==="linked").length}/${F.length}`:""),F.length===0){x.appendChild(M("div","wb-nodelist-empty")).textContent="暂无 tracked peer——配 peers 种子或等 referral 到达";return}for(const k of F){const _=fo(k.url),Y=M("div","wb-host-row"),ee=M("span","wb-host-lamp"),J=k.lastContactAt,be=J===void 0?void 0:p-J,ke=k.lastContactOk;be===void 0?ee.classList.add("is-unknown"):ke===!1&&be<=5*6e4?ee.classList.add("is-fail"):be<=6e4?ee.classList.add("is-live"):be<=5*6e4?ee.classList.add("is-warm"):ee.classList.add("is-cold"),ee.title=J===void 0?"尚无接触记录":`最近接触 ${Mt(J,p)}${ke===!1?"(失败)":ke===!0?"(成功)":""}`,Y.appendChild(ee),Y.appendChild(M("span","wb-host-name")).textContent=k.name!==void 0&&k.name!==""?k.name:_;const Pe=M("span",`wb-host-badge ${k.link==="linked"?"is-linked":"is-stranger"}`);Pe.textContent=`${k.link==="linked"?"linked":"stranger"} ${k.verified===!0?"✓":"✗"}`,Pe.title=k.link==="linked"?`已建立运营者链接(互种或 canvas 引用);${k.verified===!0?"验签有效":"尚未持有验签通过的卡片"}`:"无运营者关系(验签 ≠ 关系)",Y.appendChild(Pe),k.version!==void 0&&k.version!==""&&(Y.appendChild(M("span","wb-host-ver")).textContent=k.version),Y.appendChild(M("span","wb-host-url mono")).textContent=_,Y.setAttribute("role","button"),Y.tabIndex=0,Y.title=`${k.url} · score ${String(k.score??0)}`;const te=()=>{le({kind:"peer",id:`peer-${_}`,title:k.name!==void 0&&k.name!==""?k.name:_,sub:_,url:k.url})};Y.addEventListener("click",te),Y.addEventListener("keydown",Se=>{(Se.key==="Enter"||Se.key===" ")&&(Se.preventDefault(),te())}),x.appendChild(Y)}}function Te(){if(n===null){me.replaceChildren(),N.setBadge("ledger","");return}const x=n,p=k=>{const _=(x.sessions??[]).find(ee=>ee.team===k);if(_!==void 0)return{kind:"session",id:_.id,title:it(_),sub:_.team,team:_.team,live:_.live};const Y=(x.remote??[]).find(ee=>ee.team===k);if(Y!==void 0)return{kind:"remote",team:Y.team,title:it(Y),sub:Y.team,row:Y}},F=Gn(me,{state:x,now:t.now(),abandon:(k,_)=>t.abandon(k,_),canOpenTeam:k=>p(k)!==void 0,openTeam:k=>{const _=p(k);return _===void 0?!1:(le(_),!0)}});N.setBadge("ledger",F.badge,F.tone)}function Ke(){var ee;const x=Fe(Ee);if(n===null)return;const p=t.now(),F=n.inFlight??[];N.setBadge("activity",F.length>0?String(F.length):"",F.length>0?"accent":void 0);const k=M("div","wb-pane-head");if(k.textContent=`在途 ${F.length} · 活动 ${((ee=n.activity)==null?void 0:ee.length)??0}`,x.appendChild(k),F.length>0){const J=M("div","wb-pane-subhead");J.textContent="在途路由",x.appendChild(J);for(const be of F){const ke=M("div","wb-row");ke.appendChild(M("span","wb-row-dir")).textContent="→",ke.appendChild(M("span","wb-row-team")).textContent=be.team,ke.appendChild(M("span","wb-row-meta")).textContent=`${be.peer} · ${Mt(be.startedAt,p)}`,x.appendChild(ke)}}const _=M("div","wb-pane-subhead");_.textContent="活动环(最新在前)",x.appendChild(_);const Y=n.activity??[];if(Y.length===0){x.appendChild(M("div","wb-muted")).textContent="暂无活动";return}for(const J of Y){const be=M("div","wb-row"),ke=M("span","wb-row-dir");ke.textContent=J.dir==="out"?"→":"←",J.ok!==!0&&ke.classList.add("is-fail"),be.appendChild(ke),be.appendChild(M("span","wb-row-team")).textContent=J.team,be.appendChild(M("span","wb-row-meta")).textContent=`${J.peer} · ${Mt(J.ts,p)}`,be.appendChild(M("span","wb-row-badges")).textContent=J.ok===!0?"":"失败",x.appendChild(be)}}function Ye(x){var Y,ee;const p=t.now(),F=[],k=zt(x,p);k.deadLetters.length>0&&F.push({severity:"high",text:`清账 ${k.deadLetters.length} 条死信(目标早已离开或死信化,无回执可期)`});for(const J of k.stale){const be=J.brief===void 0||J.brief===""?"":`「${J.brief}」`;F.push({severity:"normal",text:`催办 ${J.taskId} → ${J.team}(等待 ${Mt(J.startedAt,p)} 无回执)${be}`,brief:`a2a_route 催收回执:task ${J.taskId}(team ${J.team})${be===""?"":`原任务「${J.brief}」`}已派发 ${Mt(J.startedAt,p)},请回报结果或回执。`})}for(const J of x.sessions??[])J.live!==!0&&F.push({severity:"normal",text:`冷会话 ${it(J)}:在 GUI 打开该会话即可唤醒加入面`});for(const J of((Y=x.reconcile)==null?void 0:Y.rows)??[])J.needsRepair===!0&&F.push({severity:"high",text:`reconcile 需修复:${J.id} ${J.error}`});const _=((ee=x.idempotency)==null?void 0:ee.conflicts)??0;return _>0&&F.push({severity:"high",text:`幂等冲突 ${_} 例:人工核查 UNIQUE-ization 流量`}),F}function ht(){const x=Fe($e);if(n===null)return;const p=Ye(n);N.setBadge("plan",p.length>0?String(p.length):"",p.some(_=>_.severity==="high")?"danger":void 0);const F=M("div","wb-pane-head");F.textContent=p.length===0?"网络健康——无待办行动":`待办行动 ${p.length}`,x.appendChild(F);for(const _ of p){const Y=M("div",`wb-action${_.severity==="high"?" wb-action-high":""}`);if(Y.appendChild(M("span","wb-action-text")).textContent=_.text,_.brief!==void 0){const ee=M("button","wb-btn");ee.type="button",ee.textContent="复制催办",ee.addEventListener("click",()=>t.copy(_.brief??"")),Y.appendChild(ee)}x.appendChild(Y)}const k=M("div","wb-pane-subhead");k.textContent="派单起草(复制后在任一会话粘贴执行)",x.appendChild(k),x.appendChild(et)}const et=M("div","wb-draft"),Ve=document.createElement("select");Ve.className="wb-select";const st=document.createElement("textarea");st.className="wb-textarea",st.rows=3,st.placeholder="任务正文:目标、验收、期限…";const tt=M("button","wb-btn wb-btn-primary");tt.type="button",tt.textContent="复制任务书",tt.addEventListener("click",()=>{const x=Ve.value,p=st.value.trim();x===""||p===""||t.copy(`a2a_route 派单 → ${x}:
|
|
5
|
+
${p}`)}),et.appendChild(Ve),et.appendChild(st),et.appendChild(tt);function dt(){var _;const x=Ve.value;Fe(Ve);const p=document.createElement("option");if(p.value="",p.textContent="选择目标队…",Ve.appendChild(p),n===null)return;const F=n,k=new Map;for(const Y of F.sessions??[])Y.team!==void 0&&Y.team!==""&&k.set(Y.team,`${it(Y)}(会话队)`);for(const Y of((_=F.canvas)==null?void 0:_.teams)??[])k.set(Y.team,`${Y.name}(canvas 队)`);for(const Y of F.remote??[])k.set(Y.team,`${it(Y)}(远端)`);for(const[Y,ee]of k){const J=document.createElement("option");J.value=Y,J.textContent=`${ee} · ${Y}`,Ve.appendChild(J)}x!==""&&k.has(x)&&(Ve.value=x)}let Xe=!1,qe=null;function l(){var x;A(),Xe&&((x=t.ownerSettingsRead)==null||x.call(t).then(p=>{if(Xe){if(p.ok!==!0){qe=null,A();return}qe={teamJoinAllowlist:p.teamJoinAllowlist??[],teamScopeInfo:p.teamScopeInfo!==!1,announce:p.announce===!0,announceRestartPending:p.announceRestartPending===!0},A()}}))}function I(x){const p=M("div","wb-card"),F=M("div","wb-inspector-head");F.appendChild(M("span","wb-inspector-title")).textContent="主人设置";const k=M("button","wb-icon-btn");if(k.type="button",k.setAttribute("aria-label","关闭主人设置"),k.textContent="✕",k.addEventListener("click",()=>{Xe=!1,A()}),F.appendChild(k),p.appendChild(F),t.ownerSettingsRead===void 0){const xe=M("div","wb-hint");xe.textContent="此宿主未提供主人设置面(旧版本)——升级后可用。",p.appendChild(xe),x.appendChild(p);return}if(qe===null){const xe=M("div","wb-hint");xe.textContent="读取中…",p.appendChild(xe),x.appendChild(p);return}const _=qe,Y=M("div","wb-side-head");Y.textContent="入网白名单(精确团队名)",p.appendChild(Y);for(const xe of _.teamJoinAllowlist){const ot=M("div","wb-member-row");ot.appendChild(M("span","wb-member-label")).textContent=xe;const bt=M("button","wb-member-remove");bt.type="button",bt.textContent="移除",bt.addEventListener("click",()=>{var gt;(gt=t.ownerSettingsWrite)==null||gt.call(t,{teamJoinAllowlist:_.teamJoinAllowlist.filter(Ht=>Ht!==xe)}).then(()=>l())}),ot.appendChild(bt),p.appendChild(ot)}const ee=M("div","wb-member-add"),J=M("input","wb-member-manual");J.type="text",J.placeholder="dsh/团队名(精确,无通配)",J.setAttribute("aria-label","新增白名单团队名");const be=M("button","wb-member-submit");be.type="button",be.textContent="加入";const ke=()=>{var ot;const xe=J.value.trim();xe===""||_.teamJoinAllowlist.includes(xe)||(ot=t.ownerSettingsWrite)==null||ot.call(t,{teamJoinAllowlist:[..._.teamJoinAllowlist,xe]}).then(()=>l())};be.addEventListener("click",ke),J.addEventListener("keydown",xe=>{xe.key==="Enter"&&ke()}),ee.append(J,be),p.appendChild(ee);const Pe=M("div","wb-side-head");Pe.textContent="目录可见性(teamScopeInfo)",p.appendChild(Pe);const te=M("div","wb-member-row"),Se=M("button","wb-member-submit");Se.type="button",Se.textContent=_.teamScopeInfo?"已开:仅显示已加入团队(点击放开为全舰队可见)":"已关:全舰队可见(点击收窄为已加入团队)",Se.addEventListener("click",()=>{var xe;(xe=t.ownerSettingsWrite)==null||xe.call(t,{teamScopeInfo:!_.teamScopeInfo}).then(()=>l())}),te.appendChild(Se),p.appendChild(te);const je=M("div","wb-hint");je.textContent="精度说明:teamScopeInfo 只管「目录显示范围」。关上它不会解锁任何通信准入——会话入网(S3)与目标级路由(F5)规则原样生效。",p.appendChild(je);const De=M("div","wb-side-head");De.textContent="节点发布(announce)",p.appendChild(De);const nt=M("div","wb-member-row"),Re=M("button","wb-member-submit");if(Re.type="button",Re.textContent=_.announce?"已开:本节点发布签名卡(点击关闭)":"已关:本节点不发布(点击开启——重启宿主后生效)",Re.addEventListener("click",()=>{var xe;(xe=t.ownerSettingsWrite)==null||xe.call(t,{announce:!_.announce}).then(()=>l())}),nt.appendChild(Re),p.appendChild(nt),_.announceRestartPending){const xe=M("div","wb-hint");xe.textContent="有 announce 变更待生效:重启宿主后按新配置发布。",p.appendChild(xe)}x.appendChild(p)}function A(){var k;const x=Fe(_e);if(Xe){U.classList.add("is-open"),I(x);return}if(U.classList.toggle("is-open",s!==void 0),s===void 0)return;const p=s,F=M("div","wb-card");if(p.kind==="canvas"){const _=(((k=n==null?void 0:n.canvas)==null?void 0:k.teams)??[]).find(te=>te.name===p.row.name)??p.row;bn(F,"Canvas 队",_.name),bn(F,"路由队",_.team);const Y=M("div","wb-side-head");if(Y.textContent=`成员 · ${_.members.length}`,F.appendChild(Y),_.members.length===0){const te=M("div","wb-muted");te.textContent="空队——用下方表单添加成员",F.appendChild(te)}for(const te of _.members){const Se=M("div","wb-member-row"),je=te.remote===!0?"◇ 远端":te.live===!0?"● 现场":te.joined===!0?"○ 冷启":"· 未入网";Se.appendChild(M("span","wb-member-dot")).textContent=je;const De=M("span","wb-member-label"),nt=((n==null?void 0:n.sessions)??[]).find(xe=>xe.id===te.id);De.textContent=te.remote===!0?te.id:nt!==void 0?it(nt):te.id,De.title=te.team??te.id,Se.appendChild(De);const Re=M("button","wb-member-remove");Re.type="button",Re.textContent="移除",Re.addEventListener("click",async()=>{Re.disabled=!0,await t.canvasOp("remove-member",_.name,te.id)||(Re.disabled=!1)}),Se.appendChild(Re),F.appendChild(Se)}if((u==null?void 0:u.name)!==_.name){const te=M("form","wb-member-add"),Se=document.createElement("select");Se.className="wb-member-pick",Se.setAttribute("aria-label","选择成员");const je=document.createElement("input");je.type="text",je.className="wb-member-manual",je.placeholder="或输入远端句柄 zone/id8",je.setAttribute("aria-label","远端成员句柄");const De=M("button","wb-member-submit");De.type="submit",De.textContent="添加",te.appendChild(Se),te.appendChild(je),te.appendChild(De),te.addEventListener("submit",async nt=>{nt.preventDefault();const Re=je.value.trim(),xe=Re!==""?Re:Se.value;if(xe==="")return;De.disabled=!0;const ot=await t.canvasOp("add-member",_.name,xe);De.disabled=!1,ot&&(je.value="")}),u={name:_.name,form:te,pick:Se,manual:je}}const ee=u.pick,J=ee.value;Fe(ee),ee.appendChild(new Option("本机会话(现场/冷启动)…","",!0,!0));const be=new Set(_.members.map(te=>te.id));for(const te of(n==null?void 0:n.sessions)??[])be.has(te.id)||ee.appendChild(new Option(`${it(te)} — 本机`,te.id));let ke=!1;for(const te of(n==null?void 0:n.remote)??[])te.team.includes("/")&&(be.has(te.team)||(ke||(ee.appendChild(new Option("远端会话队(目录卡片)…","",!0,!1)),ke=!0),ee.appendChild(new Option(`${it(te)} — 远端`,te.team))));ke||ee.appendChild(new Option("(暂无可拉入的远端会话队——见下方说明)","",!0,!1)),J!==""&&Array.from(ee.options).some(te=>te.value===J)&&(ee.value=J),F.appendChild(u.form);const Pe=M("div","wb-hint");Pe.textContent="成员由人类在此手工分配(agent 不可自组队)。远端成员走对端目录路由,不做本机冷唤醒;地址由目录在派发时重解析。远端下拉只列 zone/id8 会话句柄——若为空,说明目录里还没有已链接对端的会话队(未链接的对端只给最小卡);此时可在输入框手输句柄(如 dsh/xxxxxxxx)先把人拉进来,句柄本身即链接手势。",F.appendChild(Pe),t.dispatchQuick!==void 0&&F.appendChild(B(_.team))}x.appendChild(F)}function G(x){const p=M("form","wb-dispatch-form"),F=document.createElement("textarea");F.className="wb-dispatch-text",F.placeholder="一句话任务…(≤4000 字符,异步送达,回执进台账)",F.setAttribute("aria-label","快派消息");const k=M("button","wb-dispatch-submit");k.type="submit",k.textContent="发送";const _=M("div","wb-dispatch-note");return p.appendChild(F),p.appendChild(k),p.appendChild(_),F.addEventListener("keydown",Y=>{Y.key!=="Enter"||Y.shiftKey||Y.ctrlKey||Y.altKey||Y.metaKey||Y.isComposing||(Y.preventDefault(),k.disabled||p.requestSubmit())}),p.addEventListener("submit",async Y=>{var be;Y.preventDefault();const ee=F.value.trim();if(ee===""||k.disabled)return;k.disabled=!0,_.textContent="派发中…";let J;try{J=await(((be=t.dispatchQuick)==null?void 0:be.call(t,x,ee))??Promise.resolve({ok:!1,error:"dispatch unavailable"}))}catch(ke){J={ok:!1,error:ke instanceof Error?ke.message:String(ke)}}k.disabled=!1,J.ok===!0&&(F.value=""),F.focus({preventScroll:!0}),_.textContent=J.ok===!0?`已派发${J.task_id!==void 0?` · ${J.task_id}`:""} · 回执将入台账(待回执)`:`失败:${J.error??"未知原因"}`}),{form:p,text:F,note:_}}function B(x){const p=M("div","wb-dispatch"),F=M("div","wb-side-head");return F.textContent="快派",p.appendChild(F),(C==null?void 0:C.team)!==x&&(C={team:x,...G(x)}),p.appendChild(C.form),p}function le(x){Oe.open(x),D.classList.remove("is-rail-open")}function he(x){if(n===null)return;const p=(n.sessions??[]).find(k=>k.id===x);if(p!==void 0){le({kind:"session",id:x,title:it(p),sub:p.team,team:p.team,live:p.live});return}if(x.startsWith("peer-")){const k=x.slice(5),_=(n.peers??[]).find(Y=>Y.url.includes(k));le({kind:"peer",id:x,title:_!==void 0?_.url:k,sub:k,url:_==null?void 0:_.url});return}c.find(k=>k.id===x)!==void 0&&le({kind:"log",id:x,title:`…${x.slice(-12)}`,sub:"档案"})}function se(){var be,ke;w.textContent=(n==null?void 0:n.version)!==void 0?`v${n.version}`:"v?";const x=Fe(H);if(n===null)return;const p=[],F=zt(n,t.now()),k=F.deadLetters.length;k>0&&p.push({text:`死信 ${k}`,tone:"danger",title:"超过 24h TTL 仍未结算的任务(unconsumed),需在台账清账"});const _=F.stale.length;_>0&&p.push({text:`陈旧 ${_}`,tone:"warn",title:"我方派发、要回执、已等待 ≥1h 仍未回执(可催办;免回执行不算)"});const Y=F.owedOverdue.length;Y>0&&p.push({text:`欠回执 ${Y}`,tone:"warn",title:"对方投递给本机、已等待本机回执超过 1 小时"});const ee=((be=n.idempotency)==null?void 0:be.conflicts)??0;ee>0&&p.push({text:`幂等冲突 ${ee}`,tone:"danger",title:"同一幂等键对应了不同载荷,需人工核查"});const J=(((ke=n.reconcile)==null?void 0:ke.rows)??[]).filter(Pe=>Pe.needsRepair===!0).length;if(J>0&&p.push({text:`需修复 ${J}`,tone:"danger",title:"reconcile 无法自动恢复的会话,见行动计划"}),p.length===0){x.appendChild(M("span","wb-header-ok")).textContent="● 无异常";return}for(const Pe of p){const te=M("span",`wb-alert wb-alert-${Pe.tone}`);te.textContent=Pe.text,te.title=Pe.title,x.appendChild(te)}}function Z(x){n=x,t.sessionLogList!==void 0&&!K&&(K=!0,t.sessionLogList().then(p=>{c=p.ok&&p.sessions!==void 0?p.sessions:[],S=p.ok?p.count:void 0}).catch(()=>{}).finally(()=>{K=!1,He()})),se(),He(),dt(),Ue(),Te(),Oe.update(x),Ke(),ht(),A(),Ie()}function Ae(x){if(x==="board"){Ie();return}N.select(x)}return Z(null),{root:D,update:Z,mode:()=>o,selectTab:Ae,openNodeChat:he}}const ut=1e6,en=.25,tn=3,In=256,Tn=96;function $t(t){const e=typeof t=="number"?t:Number.NaN;if(Number.isFinite(e))return Math.max(-ut,Math.min(ut,Math.round(e)))}function _n(t){if(t===null||typeof t!="object")return;const e=t,o=$t(e.x),s=$t(e.y);return o===void 0||s===void 0?void 0:{x:o,y:s}}function bo(t){const e=_n(t);if(e===void 0)return;const o=t,s=$t(o.w),n=$t(o.h);if(!(s===void 0||n===void 0||s<=0||n<=0))return{...e,w:Math.min(s,ut),h:Math.min(n,ut)}}function On(t){if(t===null||typeof t!="object")return;const e=t;if(e.version!==1)return;const o=e.viewport;if(o===null||typeof o!="object")return;const s=o,n=$t(s.x),r=$t(s.y),a=s.scale,u=typeof a=="number"?a:Number.NaN;if(n===void 0||r===void 0||!Number.isFinite(u))return;const C=Math.max(en,Math.min(tn,u)),c={};if(e.nodes!==null&&typeof e.nodes=="object")for(const[R,K]of Object.entries(e.nodes)){if(typeof R!="string"||R===""||R.length>128)continue;const D=_n(K);if(D!==void 0&&(c[R]=D),Object.keys(c).length>=In)break}const S={};if(e.frames!==null&&typeof e.frames=="object")for(const[R,K]of Object.entries(e.frames)){if(typeof R!="string"||R===""||R.includes("/")||R.length>40)continue;const D=bo(K);if(D!==void 0&&(S[R]=D),Object.keys(S).length>=Tn)break}return{version:1,viewport:{x:n,y:r,scale:C},nodes:c,frames:S}}function go(t,e,o){const s=a=>Math.max(-ut,Math.min(ut,Math.round(a))),n={};for(const[a,u]of e)if(!(typeof a!="string"||a===""||a.length>128)&&(n[a]={x:s(u.x),y:s(u.y)},Object.keys(n).length>=In))break;const r={};for(const[a,u]of o){if(typeof a!="string"||a===""||a.includes("/")||a.length>40)continue;const C=s(u.w),c=s(u.h);if(!(C<=0||c<=0)&&(r[a]={x:s(u.x),y:s(u.y),w:Math.min(C,ut),h:Math.min(c,ut)},Object.keys(r).length>=Tn))break}return{version:1,viewport:{x:s(t.x),y:s(t.y),scale:Math.max(en,Math.min(tn,t.scale))},nodes:n,frames:r}}function Pn(t){let e=2166136261;for(let o=0;o<t.length;o++)e^=t.charCodeAt(o),e=Math.imul(e,16777619)>>>0;return e>>>0}const yt=172,rt=56,vt=[150,290,430],Qe=16;function vo(t){const e=Pn(t),o=Math.floor(e/Qe)%vt.length,n=e%Qe/Qe*Math.PI*2+o*(Math.PI/Qe),r=vt[o];return{x:Math.round(Math.cos(n)*r),y:Math.round(Math.sin(n)*r*.6)}}function Fn(t){const e=new Map;for(const o of t)for(const s of o.members)e.has(s.id)||e.set(s.id,o.name);return e}const gn=64,vn=24,yn=20,yo=4,wn=24,xn=44,wo=24;function xo(t,e,o=Number.POSITIVE_INFINITY){const s=new Set(e),n=Fn(t),r=t.map(R=>[...new Set(R.members.map(K=>K.id))].filter(K=>s.has(K)&&n.get(K)===R.name));r.push(e.filter(R=>!n.has(R)));const a=new Map;let u=0,C=0,c=0,S=0;for(const R of r){if(R.length===0)continue;const K=Math.min(3,Math.max(R.length>1?2:1,Math.ceil(Math.sqrt(R.length)))),D=Math.ceil(R.length/K),q=Math.max(260,K*yt+(K-1)*vn+wn*2),we=Math.max(160,D*rt+(D-1)*yn+xn+wo);S>0&&(S%yo===0||u+q>o)&&(u=0,C+=c+gn,c=0),R.forEach((ae,w)=>{const E=w%K,H=Math.floor(w/K);a.set(ae,{x:u+wn+yt/2+E*(yt+vn),y:C+xn+rt/2+H*(rt+yn)})}),u+=q+gn,c=Math.max(c,we),S+=1}return a}const _t=12;function Dn(t,e){const o=C=>e.every(c=>Math.abs(c.x-C.x)>=yt+_t||Math.abs(c.y-C.y)>=rt+_t),s=vo(t);if(o(s))return s;const n=Pn(t),r=Qe*vt.length,a=Math.floor(n/Qe)%vt.length*Qe+n%Qe;for(let C=1;C<r;C++){const c=(a+C)%r,S=Math.floor(c/Qe),R=c%Qe/Qe*Math.PI*2+S*(Math.PI/Qe),K=vt[S],D={x:Math.round(Math.cos(R)*K),y:Math.round(Math.sin(R)*K*.6)};if(o(D))return D}const u=vt[vt.length-1];for(let C=0;;C++)for(let c=0;c<6;c++){const S={x:Math.round(-u+c*(yt+_t)),y:Math.round(u*.6+rt*2+C*(rt+_t))};if(o(S))return S}}function ft(t){return{x:t.x-yt/2,y:t.y-rt/2,w:yt,h:rt}}function nn(t){if(t.length===0)return{x:0,y:0,w:260,h:160};let e=Number.POSITIVE_INFINITY,o=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY,n=Number.NEGATIVE_INFINITY;for(const S of t)e=Math.min(e,S.x),o=Math.min(o,S.y),s=Math.max(s,S.x+S.w),n=Math.max(n,S.y+S.h);const r=24,a=44,u=24,C=Math.max(260,Math.round(s-e+r*2)),c=Math.max(160,Math.round(n-o+a+u));return{x:Math.round(e-r),y:Math.round(o-a),w:C,h:c}}class on{constructor(){xt(this,"revisionCounter",0);xt(this,"nodes",new Map);xt(this,"frames",new Map);xt(this,"selection",new Set);xt(this,"viewport",{x:0,y:0,scale:1})}get revision(){return this.revisionCounter}getNode(e){return this.nodes.get(e)}allNodes(){return[...this.nodes.values()]}nodeIds(){return[...this.nodes.keys()]}getFrame(e){return this.frames.get(e)}allFrames(){return[...this.frames.entries()]}isSelected(e){return this.selection.has(e)}selectedIds(){return[...this.selection]}bump(){this.revisionCounter+=1}dragNodes(e,o,s){let n=!1;for(const r of e){const a=this.nodes.get(r);a!==void 0&&(a.x+=o,a.y+=s,n=!0)}n&&this.bump()}beginFrameDrag(e){const o=this.frames.get(e);if(o===void 0)return;const s=[];for(const n of this.nodes.values())for(const r of n.memberships)if(r.team===e){s.push([n.id,n.x,n.y]);break}return{name:e,rect:{...o},centers:s}}applyFrameDrag(e,o,s){const n=this.frames.get(e.name);if(n!==void 0){n.x=e.rect.x+o,n.y=e.rect.y+s;for(const[r,a,u]of e.centers){const C=this.nodes.get(r);C!==void 0&&(C.x=a+o,C.y=u+s)}this.bump()}}nudge(e,o,s){this.dragNodes(e,o,s)}marqueeSelect(e,o){o||this.selection.clear();for(const s of this.nodes.values()){const n=ft(s);n.x<e.x+e.w&&n.x+n.w>e.x&&n.y<e.y+e.h&&n.y+n.h>e.y&&this.selection.add(s.id)}this.bump()}setSelection(e){this.selection=new Set(e),this.bump()}upsertNode(e){const o=this.nodes.get(e.id);if(o===void 0){this.nodes.set(e.id,e),this.bump();return}o.label=e.label,o.name=e.name,o.live=e.live,o.memberships=e.memberships,this.bump()}removeNode(e){this.nodes.delete(e)&&(this.selection.delete(e),this.bump())}setFrame(e,o){this.frames.set(e,o),this.bump()}removeFrame(e){this.frames.delete(e)&&this.bump()}upsertScore(e,o){const s=this.nodes.get(e);s===void 0||s.score===o||(s.score=o,this.bump())}positions(){const e=new Map;for(const[o,s]of this.nodes)e.set(o,{x:s.x,y:s.y});return e}frameRects(){const e=new Map;for(const[o,s]of this.frames)e.set(o,{...s});return e}teamMemberIds(e){const o=[];for(const s of this.nodes.values()){const n=s.memberships.find(r=>r.team===e);n!==void 0&&o.push({id:s.id,index:n.index})}return o.sort((s,n)=>s.index-n.index).map(s=>s.id)}setTeamMembers(e,o){for(const s of this.nodes.values()){const n=s.memberships.filter(a=>a.team!==e),r=o.indexOf(s.id);r>=0&&n.push({team:e,index:r}),s.memberships=n}this.bump()}contentBounds(){let e=Number.POSITIVE_INFINITY,o=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY,n=Number.NEGATIVE_INFINITY;const r=a=>{e=Math.min(e,a.x),o=Math.min(o,a.y),s=Math.max(s,a.x+a.w),n=Math.max(n,a.y+a.h)};for(const a of this.nodes.values())a.remote!==!0&&r(ft(a));for(const a of this.frames.values())r(a);return e===Number.POSITIVE_INFINITY?null:{minX:e,minY:o,maxX:s,maxY:n}}static fromState(e){const o=new on,s=On(e.layout),n=new Map;for(const r of e.teams)for(let a=0;a<r.members.length;a++){const u=r.members[a].id,C=n.get(u)??[];C.push({team:r.name,index:a}),n.set(u,C)}for(const r of e.sessions){if(r.joined!==!0)continue;const a=s==null?void 0:s.nodes[r.id];let u,C;if(a!==void 0&&typeof a.x=="number"&&typeof a.y=="number")u=a.x,C=a.y;else{const c=Dn(r.id,[...o.nodes.values()]);u=c.x,C=c.y}o.nodes.set(r.id,{id:r.id,x:u,y:C,label:r.label,team:r.team,name:r.name,live:r.live!==!1,memberships:n.get(r.id)??[]})}for(const r of e.teams){const a=s==null?void 0:s.frames[r.name];if(a!==void 0){o.frames.set(r.name,{x:a.x,y:a.y,w:a.w,h:a.h});continue}const u=[];for(const C of r.members){const c=o.nodes.get(C.id);c!==void 0&&u.push(ft(c))}u.length>0&&o.frames.set(r.name,nn(u))}return o.viewport=s!==void 0?{...s.viewport}:{x:0,y:0,scale:1},o}}const Co=24,ko=-13,Rn=ko+Co;function Eo(t,e,o){const s=[],n=new Set;for(const r of t){const a=e.get(r.name);if(a===void 0)continue;const u=a.x+a.w/2,C=a.y+Rn;for(const c of r.members){const S=o.get(c.id);if(S===void 0)continue;const R=n.has(c.id);n.add(c.id),s.push({x1:u,y1:C,x2:S.x,y2:S.y-rt/2,dashed:R,team:r.name,id:c.id})}}return s}function $o(t){return`peer-${Et(t).replace(/[^A-Za-z0-9.:\[\]-]/g,"-")}`}function Et(t){try{return new URL(t).host}catch{return t}}function No(t){const e=new Map;for(const o of t){const s=o.via!==void 0&&o.via!==""?Et(o.via):"",n=e.get(s)??[];n.push(o),e.set(s,n)}return e}const Mo=140,So=200,Ao=90,Lo=20,Ot=60;function Io(t,e){const o=e!==null?e.maxX+Mo:So,s=e!==null?e.minY:0;return t.map((n,r)=>({url:n.url,score:n.score,x:o,y:s+r*Ao}))}function To(t,e,o,s){const n=new Map;for(const a of t){if(!e.has(a.team))continue;const u=`${a.team}\0${a.peer}`,C=n.get(u);C===void 0?n.set(u,{team:a.team,peer:a.peer,startedAt:a.startedAt,count:1}):(C.startedAt=Math.min(C.startedAt,a.startedAt),C.count+=1)}const r=[];for(const a of n.values()){const u=e.get(a.team);if(u===void 0)continue;const C=o.find(S=>{try{return new URL(S.url).host===a.peer}catch{return!1}});if(C===void 0)continue;const c=Math.max(0,Math.round((s-a.startedAt)/1e3));r.push({x1:u.x,y1:u.y,x2:C.x,y2:C.y,label:`a2a_route · ${a.peer} · ${c}s`+(a.count>1?` ×${a.count}`:"")})}return r}function _o(t,e){const o=e!==null?{x:e.maxX+Lo,y:t.length>0?(t[0].y+t[t.length-1].y)/2:(e.minY+e.maxY)/2}:{x:-80,y:0};return t.map((s,n)=>({x1:o.x,y1:o.y,x2:s.x,y2:s.y,label:n===0?"gns referral":""}))}function Oo(t,e){if(t===null&&e.length===0)return null;let o=t!==null?t.minX:Number.POSITIVE_INFINITY,s=t!==null?t.minY:Number.POSITIVE_INFINITY,n=t!==null?t.maxX:Number.NEGATIVE_INFINITY,r=t!==null?t.maxY:Number.NEGATIVE_INFINITY;for(const a of e)o=Math.min(o,a.x-Ot),s=Math.min(s,a.y-Ot),n=Math.max(n,a.x+Ot),r=Math.max(r,a.y+Ot);return{minX:o,minY:s,maxX:n,maxY:r}}const Cn={x:0,y:0,scale:1};function sn(t){return Math.max(en,Math.min(tn,t))}function Ct(t){const e=Number.isFinite(t.scale)?t.scale:1,o=Number.isFinite(t.x)?t.x:0,s=Number.isFinite(t.y)?t.y:0;return{x:o,y:s,scale:sn(e)}}function at(t,e,o){return{x:t.x+e/t.scale,y:t.y+o/t.scale}}function Ut(t,e,o){return{x:t.x+e/t.scale,y:t.y+o/t.scale,scale:t.scale}}function kn(t,e,o,s){const n=sn(t.scale*e);return n===t.scale?t:{x:t.x+o/t.scale-o/n,y:t.y+s/t.scale-s/n,scale:n}}function Xt(t,e,o,s=Number.POSITIVE_INFINITY){if(t===null||e<=0||o<=0)return Cn;const n=t.maxX-t.minX,r=t.maxY-t.minY;if(!(n>0)||!(r>0))return Cn;const a=sn(Math.min(s,.9*Math.min(e/n,o/r)));return{x:(t.minX+t.maxX)/2-e/(2*a),y:(t.minY+t.maxY)/2-o/(2*a),scale:a}}function Po(t){return`translate(${-t.x*t.scale}px, ${-t.y*t.scale}px) scale(${t.scale})`}function Fo(t){return t.type==="join-network"||t.type==="leave-network"?"$network":t.type==="create-team"||t.type==="remove-team"?t.name:t.team}function Do(t,e){if(e.type==="create-team"){const n=e.ids.map(r=>t.getNode(r)).filter(r=>r!==void 0).map(r=>ft(r));return n.length>0&&t.setFrame(e.name,nn(n)),t.setTeamMembers(e.name,e.ids),()=>{t.setTeamMembers(e.name,t.teamMemberIds(e.name).filter(r=>!e.ids.includes(r))),t.removeFrame(e.name)}}if(e.type==="add-member"){const n=t.teamMemberIds(e.team),r=e.ids.filter(a=>!n.includes(a));return t.setTeamMembers(e.team,[...n,...r]),()=>{t.setTeamMembers(e.team,t.teamMemberIds(e.team).filter(a=>!r.includes(a)))}}if(e.type==="remove-member"){const n=t.teamMemberIds(e.team);return t.setTeamMembers(e.team,n.filter(r=>!e.ids.includes(r))),()=>{const r=t.teamMemberIds(e.team);t.setTeamMembers(e.team,[...r,...e.ids.filter(a=>!r.includes(a))])}}if(e.type==="remove-team"){const n=t.teamMemberIds(e.name),r=t.getFrame(e.name),a=r!==void 0?{...r}:void 0;return t.setTeamMembers(e.name,[]),t.removeFrame(e.name),()=>{a!==void 0&&t.setFrame(e.name,a),t.setTeamMembers(e.name,n)}}if(e.type==="join-network"||e.type==="leave-network")return()=>{};const o=t.teamMemberIds(e.team);let s=[...o];for(const n of e.ops)n.op==="remove"?s=s.filter(r=>r!==n.id):s.push(n.id);return t.setTeamMembers(e.team,s),()=>{let n=t.teamMemberIds(e.team);for(let r=0;r<o.length;r++){const a=o[r];n[r]!==a&&n.includes(a)&&(n=n.filter(u=>u!==a),n.push(a))}t.setTeamMembers(e.team,n)}}function qt(t,e){const o=[...t],s=[];for(let n=0;n<e.length;n++){const r=e[n];o[n]!==r&&o.includes(r)&&(s.push({op:"remove",id:r}),s.push({op:"add",id:r}),o.splice(o.indexOf(r),1),o.push(r))}return s}function Ro(t,e){return t.teamMemberIds(e).map(o=>{var s;return{id:o,y:((s=t.getNode(o))==null?void 0:s.y)??0}}).sort((o,s)=>o.y-s.y).map(o=>o.id)}function En(t,e){let o,s=Number.POSITIVE_INFINITY;for(const[n,r]of t){if(e.x<r.x||e.x>r.x+r.w||e.y<r.y||e.y>r.y+r.h)continue;const a=r.w*r.h;a<s&&(o=n,s=a)}return o}const $n=[9133302,3900150,1357990,16096779,15485081,8702998];function jo(t){const{root:e,netBtn:o,signal:s,model:n}=t;function r(){return n.selectedIds().map(f=>{var N;return{id:f,y:((N=n.getNode(f))==null?void 0:N.y)??0}}).sort((f,N)=>f.y-N.y).map(f=>f.id)}function a(){if(u!==null)return;const f=r().filter(N=>{const v=n.getNode(N);return v===void 0?!1:v.remote!==!0||v.remoteHandle!==void 0&&v.remoteHandle!==""});if(f.length<2){t.notice("info","框选至少 2 个会话节点");return}C(f)}let u=null;function C(f){const N=document.createElement("div");N.className="p-dialog";const v=document.createElement("div");v.className="p-dialog-panel",v.setAttribute("role","dialog"),v.setAttribute("aria-modal","true"),v.setAttribute("aria-labelledby","p-dialog-title");const L=document.createElement("div");L.id="p-dialog-title",L.className="p-dialog-title",L.textContent=`组建团队(${f.length} 个节点,自上而下即优先级)`;const b=document.createElement("input");b.className="p-dialog-input",b.maxLength=40,b.setAttribute("aria-label","团队名");const P=document.createElement("div");P.className="p-dialog-err",P.setAttribute("aria-live","polite");const O=document.createElement("div");O.className="p-dialog-row";const me=document.createElement("button");me.type="button",me.textContent="组建";const Ee=document.createElement("button");Ee.type="button",Ee.textContent="取消",O.append(me,Ee),v.append(L,b,P,O),N.appendChild(v),e.appendChild(N);const $e=document.activeElement,$=()=>{N.remove(),u=null,$e==null||$e.focus()},z=()=>{const pe=b.value.trim();return pe===""||pe.length>40||pe.includes("/")||/^\d+$/.test(pe)?"队名需 1..40 字,不含“/”,不为纯数字":null},oe=()=>{const pe=z();if(pe!==null){P.textContent=pe,b.focus();return}const Q=b.value.trim();if($(),n.getFrame(Q)!==void 0){t.notice("info",`已加入现有团队「${Q}」`),t.emit({type:"add-member",team:Q,ids:f});return}t.emit({type:"create-team",name:Q,ids:f,created:!0})};me.addEventListener("click",oe),Ee.addEventListener("click",$),b.addEventListener("keydown",pe=>{const Q=pe;Q.key==="Enter"&&(Q.preventDefault(),oe()),Q.key==="Escape"&&(Q.preventDefault(),$())}),N.addEventListener("keydown",pe=>{const Q=pe;if(Q.key==="Escape"){Q.preventDefault(),Q.stopPropagation(),$();return}if(Q.key!=="Tab")return;Q.preventDefault();const U=Array.from(v.querySelectorAll("input, button")),ue=U.indexOf(document.activeElement),ne=Q.shiftKey?U[(ue-1+U.length)%U.length]:U[(ue+1)%U.length];ne==null||ne.focus()},s),u={wrap:N,restoreFocus:$e},b.focus()}let c=null,S="root",R=null,K=null,D=[];function q(){K==null||K.remove(),K=null}function we(){var v;if(K!==null){q();return}if(D.length===0)return;const f=document.createElement("div");f.className="p-menu p-netmenu",f.setAttribute("role","menu"),f.setAttribute("aria-label","未入网会话");for(const L of D)f.appendChild(w(`${L.name!==void 0&&L.name!==""?L.name:L.label} — 入网`,!0,()=>{q(),t.emit({type:"join-network",id:L.id})}));K=f,e.appendChild(f);const N=o.getBoundingClientRect();f.style.left=`${String(Math.min(N.left,window.innerWidth-220))}px`,f.style.top=`${String(Math.max(8,N.top-(D.length*30+10)))}px`,f.addEventListener("keydown",L=>{L.key==="Escape"&&(L.stopPropagation(),q(),o.focus())}),(v=f.querySelector("button"))==null||v.focus(),document.addEventListener("pointerdown",L=>{if(K===null)return;const b=L.target;b!==null&&(b.closest(".p-netmenu")!==null||b===o||o.contains(b))||q()},s)}function ae(){c==null||c.remove(),c=null,S="root",R!==null&&R.isConnected?R.focus():e.focus(),R=null}function w(f,N,v){const L=document.createElement("button");return L.type="button",L.setAttribute("role","menuitem"),L.textContent=f,N?L.addEventListener("click",()=>{ae(),v()}):(L.disabled=!0,L.setAttribute("aria-disabled","true")),L}function E(f,N,v,L="root",b){var Ee,$e,$,z,oe,pe;b!==void 0&&(R=b),R===null&&(R=t.anchorFor(v)),c==null||c.remove(),S=L;const P=document.createElement("div");P.className="p-menu",P.setAttribute("role","menu"),P.setAttribute("aria-label","团队操作");let O=[];if(v.kind==="frame")O=[w(`解散团队「${v.name}」`,!0,()=>t.emit({type:"remove-team",name:v.name}))];else{const Q=v.id;if(L==="root"){const U=w("组成团队…",n.selectedIds().length>=2,()=>C(r()));U.title="先框选或 Shift 加选至少 2 个节点",O.push(U),t.teams().length>0&&(O.push(w("加入团队 ▸",!0,()=>E(f,N,v,"join"))),(((Ee=n.getNode(Q))==null?void 0:Ee.memberships.map(ne=>ne.team))??[]).length>0&&(O.push(w("置顶路由 ▸",!0,()=>E(f,N,v,"promote"))),O.push(w("离队 ▸",!0,()=>E(f,N,v,"leave"))))),(($e=n.getNode(Q))==null?void 0:$e.remote)!==!0&&O.push(w("退网",!0,()=>t.emit({type:"leave-network",id:Q})))}else{O.push(w("‹ 返回",!0,()=>E(f,N,v,"root")));for(const U of t.teams())if(L==="join"){const ue=(($=n.getNode(Q))==null?void 0:$.memberships.some(ne=>ne.team===U.name))??!0;O.push(w(ue?`${U.name}(已加入)`:U.name,!ue,()=>t.emit({type:"add-member",team:U.name,ids:[Q]})))}else if(L==="leave"){const ue=((z=n.getNode(Q))==null?void 0:z.memberships.some(ne=>ne.team===U.name))??!1;O.push(w(U.name,ue,()=>t.emit({type:"remove-member",team:U.name,ids:[Q]})))}else{const ue=((oe=n.getNode(Q))==null?void 0:oe.memberships.some(ne=>ne.team===U.name))??!1;O.push(w(U.name,ue,()=>{const ne=n.teamMemberIds(U.name),_e=[Q,...ne.filter(Oe=>Oe!==Q)];t.emit({type:"reorder",team:U.name,ops:qt(ne,_e)})}))}}}P.append(...O),P.style.left=`${Math.min(f,window.innerWidth-200)}px`;const me=O.length*30+8;P.style.top=`${Math.max(8,Math.min(N,window.innerHeight-me-8))}px`,P.addEventListener("keydown",Q=>{var _e,Oe,Be,Ie;const U=Q,ue=Array.from(P.querySelectorAll("[role=menuitem]")),ne=ue.indexOf(document.activeElement);U.key==="ArrowDown"?(U.preventDefault(),(_e=ue[(ne+1+ue.length)%ue.length])==null||_e.focus()):U.key==="ArrowUp"?(U.preventDefault(),(Oe=ue[(ne-1+ue.length)%ue.length])==null||Oe.focus()):U.key==="Home"?(U.preventDefault(),(Be=ue[0])==null||Be.focus()):U.key==="End"?(U.preventDefault(),(Ie=ue[ue.length-1])==null||Ie.focus()):U.key==="Escape"&&(U.preventDefault(),U.stopPropagation(),S!=="root"?E(f,N,v,"root"):ae())}),e.appendChild(P),c=P,(pe=O[0])==null||pe.focus()}function H(f,N,v){if(u!==null)return;const L=(v==null?void 0:v.closest(".p-node"))??null;if(L!==null){const O=n.getNode(L.dataset.id??"");if((O==null?void 0:O.remote)===!0&&(O.remoteHandle===void 0||O.remoteHandle===""))return}const b=L,P=(v==null?void 0:v.closest(".p-frame-head"))??null;if(b!==null){const O=b.dataset.id??"";n.isSelected(O)||n.setSelection([O]),R=b,E(f,N,{kind:"node",id:O})}else P!==null&&(R=P,E(f,N,{kind:"frame",name:P.dataset.frame??""}))}function h(f){D=f,o.textContent=`未入网${D.length>0?`(${String(D.length)})`:""}`,o.disabled=D.length===0,o.setAttribute("aria-disabled",String(D.length===0)),D.length===0&&q()}return{menuItem:w,isMenuOpen:()=>c!==null,isDialogOpen:()=>u!==null,closeMenu:ae,openMenu:E,contextMenuAt:H,openNameDialog:C,startCreateFromSelection:a,toggleNetMenu:we,setUnjoined:h}}function Bo(t){const{root:e,trigger:o,signal:s,model:n}=t;let r=null,a="",u=null;function C(){u==null||u.remove(),u=null}function c(){C(),r==null||r.remove(),r=null}function S(){if(r!==null){c();return}const E=document.createElement("div");E.className="p-menu p-nodelist",E.setAttribute("role","dialog"),E.setAttribute("aria-label","节点清单"),r=E,e.appendChild(E);const H=o.getBoundingClientRect();E.style.left=`${String(Math.min(H.left,window.innerWidth-340))}px`,E.style.top=`${String(Math.max(8,H.top-320))}px`,E.addEventListener("keydown",h=>{h.key==="Escape"&&(h.stopPropagation(),c(),o.focus())}),R()}function R(){var L;const E=r;if(E===null)return;C(),E.textContent="";const H=document.createElement("div");H.className="p-nodelist-head";const h=document.createElement("span");h.className="p-nodelist-title",h.textContent="节点";const f=document.createElement("select");f.className="p-nodesel",f.setAttribute("aria-label","选择 host 或对等节点");const N=document.createElement("option");N.value="",N.textContent="本机",f.appendChild(N);for(const[b,P]of t.facts().remoteTeams){if(b==="")continue;const O=document.createElement("option");O.value=b,O.textContent=((L=P[0])==null?void 0:L.origin)!==void 0&&P[0].origin!==""?`${P[0].origin}(${b})`:b,f.appendChild(O)}a!==""&&!t.facts().remoteTeams.has(a)&&(a=""),f.value=a,f.addEventListener("change",()=>{a=f.value,R()}),H.append(h,f);const v=document.createElement("div");v.className="p-nodelist-body",E.append(H,v),a===""?ae(v):w(v,t.facts().remoteTeams.get(a)??[])}function K(E,H){const h=document.createElement("span");return h.className="p-nodedot"+(H!==!0?" off":E===!1?" cold":""),h}function D(E,H){const h=document.createElement("button");return h.type="button",h.className="p-listbtn",h.textContent=E,h.addEventListener("click",f=>{f.stopPropagation(),H()}),h}function q(E,H){const h=document.createElement("div");if(h.className="p-nodelist-group",h.textContent=E,H!==void 0){const f=document.createElement("span");f.className="p-nodelist-note",f.textContent=H,h.appendChild(f)}return h}function we(E,H){var N,v;C();const h=document.createElement("div");h.className="p-menu",h.setAttribute("role","menu"),h.setAttribute("aria-label","加入团队");for(const L of t.facts().teams){const b=((N=n.getNode(H))==null?void 0:N.memberships.some(P=>P.team===L.name))??!1;h.appendChild(t.menuItem(b?`${L.name}(已加入)`:L.name,!b,()=>{c(),t.emit({type:"add-member",team:L.name,ids:[H]})}))}h.appendChild(t.menuItem("新团队…",!0,()=>{c(),t.openNameDialog([H])})),u=h,e.appendChild(h);const f=E.getBoundingClientRect();h.style.left=`${String(Math.min(f.right+4,window.innerWidth-180))}px`,h.style.top=`${String(Math.max(8,f.top-60))}px`,h.addEventListener("keydown",L=>{L.key==="Escape"&&(L.stopPropagation(),C(),E.focus())}),(v=h.querySelector("button"))==null||v.focus()}function ae(E){var v,L;const H=new Set(t.facts().canvasMemberIds);for(const b of t.facts().sessions)b.teams!==void 0&&b.teams.length>0&&H.add(b.id);const h=t.facts().sessions.filter(b=>b.joined===!0&&!H.has(b.id)),f=t.facts().sessions.filter(b=>b.joined!==!0),N=t.facts().sessions.filter(b=>b.joined===!0&&H.has(b.id));E.appendChild(q(`未组队 (${String(h.length)})`,"无网络能力"));for(const b of h){const P=document.createElement("div");P.className="p-noderow";const O=document.createElement("span");O.className="p-nodename",O.textContent=b.name!==void 0&&b.name!==""?b.name:b.label,O.title=b.team;const me=document.createElement("span");me.className="p-nonet",me.textContent="无网络能力";const Ee=D("入队▸",()=>we(Ee,b.id));P.append(K(b.live,!0),O,me,Ee,D("退网",()=>{c(),t.emit({type:"leave-network",id:b.id})})),E.appendChild(P)}E.appendChild(q(`未入网 (${String(f.length)})`));for(const b of f){const P=document.createElement("div");P.className="p-noderow";const O=document.createElement("span");O.className="p-nodename",O.textContent=b.name!==void 0&&b.name!==""?b.name:b.label,O.title=b.id,P.append(K(b.live,!1),O,D("入网",()=>{c(),t.emit({type:"join-network",id:b.id})})),E.appendChild(P)}E.appendChild(q(`已组队 (${String(N.length)})`,"画布展示"));for(const b of N){const P=document.createElement("div");P.className="p-noderow";const O=document.createElement("span");O.className="p-nodename",O.textContent=b.name!==void 0&&b.name!==""?b.name:b.label,O.title=b.team;const me=((v=n.getNode(b.id))==null?void 0:v.memberships.length)??0,Ee=((L=b.teams)==null?void 0:L.length)??0,$e=document.createElement("span");$e.className="p-teamcount",$e.textContent=`队×${String(Math.max(me,0)+Ee)}`,P.append(K(b.live,!0),O,$e,D("定位",()=>{t.locate(b.id)})),E.appendChild(P)}if(t.facts().sessions.length===0){const b=document.createElement("div");b.className="p-nodelist-empty",b.textContent="无会话节点",E.appendChild(b)}}function w(E,H){var N;const h=H.filter(v=>v.teams===void 0||v.teams.length===0),f=H.filter(v=>v.teams!==void 0&&v.teams.length>0);E.appendChild(q(`未组队 (${String(h.length)})`,"无网络能力 · 只读"));for(const v of h){const L=document.createElement("div");L.className="p-noderow";const b=document.createElement("span");b.className="p-nodename",b.textContent=v.name!==void 0&&v.name!==""?v.name:v.team,b.title=v.team;const P=document.createElement("span");P.className="p-nonet",P.textContent="无网络能力",L.append(K(!0,!0),b,P),E.appendChild(L)}E.appendChild(q(`已组队 (${String(f.length)})`,"只读"));for(const v of f){const L=document.createElement("div");L.className="p-noderow";const b=document.createElement("span");b.className="p-nodename",b.textContent=v.name!==void 0&&v.name!==""?v.name:v.team,b.title=v.team;const P=document.createElement("span");P.className="p-teamcount",P.textContent=`队×${String(((N=v.teams)==null?void 0:N.length)??0)}`,L.append(K(!0,!0),b,P),E.appendChild(L)}if(H.length===0){const v=document.createElement("div");v.className="p-nodelist-empty",v.textContent="该节点未发布会话",E.appendChild(v)}}return document.addEventListener("pointerdown",E=>{if(r===null)return;const H=E.target;if(H===null){c();return}H.closest(".p-nodelist")!==null||H.closest(".p-menu")!==null||H===o||o.contains(H)||c()},s),{toggle:S,close:c,refresh:()=>{r!==null&&R()}}}function Ho(t){return t<680?"narrow":t<1024?"medium":"wide"}function Yo(t){let e=0;for(let u=0;u<t.length;u++)e=(e*31+t.charCodeAt(u)&268435455)>>>0;const o=$n[e%$n.length],s="#"+o.toString(16).padStart(6,"0"),n=o>>16&255,r=o>>8&255,a=o&255;return{line:s,bg:`rgba(${n},${r},${a},0.05)`}}function Wo(t){const e=new on;let o,s={...e.viewport},n={kind:"none"},r=!1,a=-1,u=!0,C=!1;const c=()=>Ho(globalThis.innerWidth||Ie),S=()=>{var i;(i=t.viewportStore)==null||i.set(c(),s),t.onDirty()},R=t.now??Date.now,K=new AbortController,D=[];let q=null,we=!1;const ae={signal:K.signal},w=document.createElement("section");w.id="dsh-plan",w.setAttribute("role","tabpanel"),w.setAttribute("aria-label","A2A 规划画布"),w.tabIndex=0,w.style.display="none";const E=document.createElement("div");E.className="p-grid";const H=document.createElement("div");H.className="p-world";const h=document.createElementNS("http://www.w3.org/2000/svg","svg");h.setAttribute("class","p-edges");const f=document.createElement("div");f.className="p-layer p-frames";let N;const v=i=>{var d,m;N!==void 0&&((d=Ke.get(N))==null||d.classList.remove("selected")),N=i,i!==void 0&&((m=Ke.get(i))==null||m.classList.add("selected"))},L=document.createElement("div");L.className="p-layer p-nodes",L.setAttribute("role","listbox"),L.setAttribute("aria-multiselectable","true"),L.setAttribute("aria-label","会话节点"),H.append(h,f,L);const b=document.createElement("div");b.className="p-marquee";const P=document.createElement("div");P.className="p-toolbar";const O=document.createElement("span");O.className="p-zoom mono",O.textContent="100%";const me=(i,d,m)=>{const g=document.createElement("button");return g.type="button",g.textContent=i,g.title=d,g.addEventListener("click",m,ae),g};P.append(me("适配","适配视图(快捷键 0)",()=>nt()),me("-","缩小",()=>De(1/1.2)),O,me("+","放大",()=>De(1.2)),me("建队","组成团队(G):先框选至少 2 个节点",()=>k.startCreateFromSelection()));const Ee=me("未入网","未入网会话(点击选择入网)",()=>k.toggleNetMenu());Ee.className="p-netbtn",Ee.setAttribute("aria-haspopup","menu"),P.appendChild(Ee);const $e=me("节点","节点清单:本机与对等节点(未组队/未入网在此管理)",()=>ee.toggle());$e.className="p-nodebtn",$e.setAttribute("aria-haspopup","dialog"),P.appendChild($e);const $=document.createElement("span");$.setAttribute("aria-live","polite"),$.className="p-lamp";const z=document.createElement("i"),oe=document.createElement("span");oe.textContent="布局",$.append(z,oe),$.addEventListener("click",()=>{$.classList.contains("error")&&t.onLampClick()},ae),$.addEventListener("keydown",i=>{const d=i;(d.key==="Enter"||d.key===" ")&&$.classList.contains("error")&&(d.preventDefault(),t.onLampClick())},ae),P.appendChild($);const pe=document.createElement("div");pe.className="p-status";const Q=document.createElement("span"),U=document.createElement("span"),ue=document.createElement("span");ue.className="mut";const ne=document.createElement("span");ne.className="mut",pe.append(Q,U,ue,ne),pe.tabIndex=0,pe.setAttribute("role","button"),pe.setAttribute("aria-label","定位在途路由与联邦对端"),pe.title="定位在途与联邦(回车)",pe.addEventListener("click",()=>le(),ae),pe.addEventListener("keydown",i=>{const d=i;(d.key==="Enter"||d.key===" ")&&(d.preventDefault(),le())},ae);const _e=document.createElement("div");_e.className="p-legend";const Oe=(i,d,m)=>{const g=document.createElement("span"),T=document.createElement("i");i&&(T.className="dashed"),m!==void 0&&(T.style.borderTopColor=m),g.append(T,document.createTextNode(d)),_e.appendChild(g)};Oe(!1,"成员边(星形,框→成员)"),Oe(!0,"跨队多属(虚线)"),Oe(!1,"活动边(inFlight 路由,瞬时)","var(--accent)"),Oe(!0,"联邦线(→peer)","var(--federal)");const Be=document.createElement("div");Be.className="p-notice-stack",Be.setAttribute("role","log"),Be.setAttribute("aria-live","polite"),w.append(E,H,b,P,pe,_e,Be);let Ie=0,Fe=0;const pt=()=>t.viewSize?t.viewSize():{w:w.clientWidth,h:w.clientHeight},He=()=>{const i=pt();Ie=i.w,Fe=i.h};function Ue(){H.style.transform=Po(s);const i=24*s.scale;E.style.backgroundSize=`${i}px ${i}px`,E.style.backgroundPosition=`${-s.x*s.scale}px ${-s.y*s.scale}px`,O.textContent=`${Math.round(s.scale*100)}%`}function Te(){Ue(),e.revision!==a&&(a=e.revision,ht(),st(),tt()),G()}const Ke=new Map,Ye=new Map;function ht(){const i=new Set;for(const[d,m]of e.allFrames()){i.add(d);let g=Ke.get(d);if(g===void 0){g=document.createElement("div"),g.className="p-frame",g.dataset.name=d;const Me=document.createElement("div");Me.className="p-frame-head",Me.dataset.frame=d,Me.tabIndex=0,Me.setAttribute("role","button"),Me.setAttribute("aria-haspopup","menu"),Me.setAttribute("aria-label",`团队框 ${d}(拖动整组,回车菜单)`);const Je=document.createElement("span");Je.className="ttl";const ze=document.createElement("span");ze.className="cnt mono";const y=document.createElement("span");y.className="route mono",Me.append(Je,ze,y),g.appendChild(Me);for(const ce of["n","s","e","w","ne","nw","se","sw"]){const V=document.createElement("div");V.className=`p-frame-handle p-h-${ce}`,V.dataset.frame=d,V.dataset.dir=ce,g.appendChild(V)}f.appendChild(g),Ke.set(d,g)}const T=Yo(d);g.style.setProperty("--frame-line",T.line),g.style.setProperty("--frame-bg",T.bg),g.style.left=`${m.x}px`,g.style.top=`${m.y}px`,g.style.width=`${m.w}px`,g.style.height=`${m.h}px`;const W=g.querySelector(".ttl"),j=g.querySelector(".cnt"),X=g.querySelector(".route");W.textContent!==d&&(W.textContent=d);let ie=0,fe=0;for(const Me of e.allNodes())Me.memberships.find(ze=>ze.team===d)!==void 0&&(ie+=1,Me.memberships.length>1&&(fe+=1));const re=`${ie} 成员`+(fe>0?` +${fe} 跨队`:"");j.textContent!==re&&(j.textContent=re);const de=Ve(d);X.textContent!==de&&(X.textContent=de)}for(const[d,m]of[...Ke])i.has(d)||(m.remove(),Ke.delete(d))}function et(i){const d=qe.get(i)??[],m=d.map(j=>j.name!==void 0&&j.name!==""?j.name:j.team),g=m.slice(0,2).join("、"),T=m.length>2?` +${m.length-2}`:"",W=l.get(i);return(W!==void 0?`score ${W} · `:"")+`${d.length} 远端团队`+(g!==""?`:${g}${T}`:"")}function Ve(i){const d=gt.find(m=>m.name===i);return(d==null?void 0:d.team)??i}function st(){const i=new Set;for(const d of e.allNodes()){i.add(d.id);let m=Ye.get(d.id);if(m===void 0){m=document.createElement("div"),m.className="p-node",m.dataset.id=d.id,m.tabIndex=0;const de=document.createElement("div");de.className="nm";const Me=document.createElement("span");Me.className="dot";const Je=document.createElement("span");Je.className="nm-text",de.append(Me,Je);const ze=document.createElement("div");ze.className="sub mono";const y=document.createElement("span");y.className="prio mono",m.append(de,ze,y),L.appendChild(m),Ye.set(d.id,m)}const g=ft(d);m.style.left=`${g.x}px`,m.style.top=`${g.y}px`,m.classList.toggle("cold",!d.live),m.classList.toggle("remote",d.remote===!0),m.classList.toggle("selected",e.isSelected(d.id)),m.setAttribute("aria-selected",String(e.isSelected(d.id)));const T=d.id.slice(5),W=d.id.startsWith("member-")?d.name!==void 0&&d.name!==""?d.name:d.team:d.remote===!0?T:mt(d),j=m.querySelector(".nm-text");j.textContent!==W&&(j.textContent=W);const X=m.querySelector(".sub"),ie=d.team+(d.name!==void 0&&d.name!==""?" · "+d.name:""),fe=d.id.startsWith("member-")?d.team:d.remote===!0?et(T):(ie===W?"":ie)+(d.memberships.length>1?` · 跨队×${d.memberships.length}`:"")+(d.teams!==void 0&&d.teams.length>0?` · 网络队×${d.teams.length}`:"");X.textContent!==fe&&(X.textContent=fe);const re=m.querySelector(".prio");if(d.remote===!0){const de=I.get(T),Me=(de==null?void 0:de.link)==="linked"?"lnk-linked":(de==null?void 0:de.link)==="stranger"?"lnk-stranger":"";re.className!==`prio mono ${Me}`.trim()&&(re.className=`prio mono ${Me}`.trim());const Je=de===void 0?"":de.verified===!0?"✓":"✗",ze=((de==null?void 0:de.link)??"peer")+Je;re.textContent!==ze&&(re.textContent=ze)}else{re.className!=="prio mono"&&(re.className="prio mono");const de=d.memberships[0]!==void 0?`P${d.memberships[0].index}`:"";re.textContent!==de&&(re.textContent=de)}}for(const[d,m]of[...Ye])i.has(d)||(m.remove(),Ye.delete(d))}function tt(){for(;h.firstChild!==null;)h.firstChild.remove();const i=e.allFrames().map(([d])=>({name:d,members:e.teamMemberIds(d).map(m=>({id:m}))}));for(const d of Eo(i,new Map(e.allFrames()),e.positions())){const m=document.createElementNS("http://www.w3.org/2000/svg","line");m.setAttribute("class","e-member"+(d.dashed?" dashed":"")),m.setAttribute("x1",String(d.x1)),m.setAttribute("y1",String(d.y1)),m.setAttribute("x2",String(d.x2)),m.setAttribute("y2",String(d.y2)),h.appendChild(m)}}let dt=[],Xe=[],qe=new Map;const l=new Map,I=new Map;let A=[];function G(){for(const m of dt)m.remove();dt=[];const i=e.allNodes().filter(m=>m.remote===!0).map(m=>({url:m.peerUrl??m.id.slice(5),score:m.score,x:m.x,y:m.y}));Xe=i;const d=e.contentBounds();if(d!==null){const m=new Map;for(const[g,T]of e.allFrames())m.set(g,{name:g,x:T.x+T.w/2,y:T.y+Rn});for(const g of To(A,m,i,R()))dt.push(...B(g,"e-activity",g.label));for(const g of _o(i,d))dt.push(...B(g,"e-federal",g.label))}}function B(i,d,m){const g=document.createElementNS("http://www.w3.org/2000/svg","line");g.setAttribute("class",d),g.setAttribute("x1",String(i.x1)),g.setAttribute("y1",String(i.y1)),g.setAttribute("x2",String(i.x2)),g.setAttribute("y2",String(i.y2)),h.appendChild(g);const T=[g];if(m!==""){const W=document.createElementNS("http://www.w3.org/2000/svg","text");W.setAttribute("class","edge-label mono"),W.setAttribute("x",String((i.x1+i.x2)/2+14)),W.setAttribute("y",String((i.y1+i.y2)/2+18)),W.textContent=m,h.appendChild(W),T.push(W)}return T}function le(){s=Xt(Oo(e.contentBounds(),Xe),w.clientWidth||Ie,w.clientHeight||Fe),Ue(),S()}function he(i){var W;const d=i.sessions.filter(j=>j.live!==!1).length,m=i.sessions.length-d;Q.textContent="";const g=document.createElement("b");g.className="ok",g.textContent=`● ${d} live`,Q.appendChild(g),U.textContent="";const T=document.createElement("b");T.className="warn",T.textContent=`● ${m} cold`,U.appendChild(T),ue.textContent=`${((W=i.inFlight)==null?void 0:W.length)??0} inFlight`,ne.className="mut",ne.textContent=`${i.teams.length} 队 · ${i.peerCount} peer`}const se=new Map,Z=i=>{se.set(i,(se.get(i)??0)+1)},Ae=i=>{const d=(se.get(i)??0)-1;d<=0?se.delete(i):se.set(i,d)};let x=new Map;function p(i){function d(T){const W=j=>{var ie;const X=[];for(const fe of j){if(!fe.startsWith("peer-")&&!fe.startsWith("member-")){X.push(fe);continue}const re=(ie=e.getNode(fe))==null?void 0:ie.remoteHandle;re!==void 0&&re!==""&&X.push(re)}return X};if(T.type==="add-member"||T.type==="remove-member"||T.type==="create-team"){const j=W(T.ids),X=T.type!=="create-team"?x.get(T.team):void 0;return j.length>0||X!==void 0?{...T,ids:j,...X!==void 0?{fleetPeer:X}:{}}:T}return T}if(i.type==="add-member"||i.type==="remove-member"||i.type==="reorder"||i.type==="create-team"){const T=i.type==="reorder"?i.ops.map(W=>W.id):[...i.ids];for(const W of T){if(W===""||W.startsWith("peer-")||W.startsWith("member-")||e.getNode(W)!==void 0)continue;const j=_.find(fe=>fe.id===W);if(j===void 0)continue;const X=o==null?void 0:o.nodes[W],ie=X!==void 0?{x:X.x,y:X.y}:an(W);e.upsertNode({id:W,x:ie.x,y:ie.y,label:j.label,team:j.team,name:j.name,live:j.live!==!1,memberships:[],...j.teams!==void 0&&j.teams.length>0?{teams:j.teams}:{}})}}const m=Do(e,i),g=Fo(i);Z(g),Te(),t.onCanvasAction(d(i)).then(T=>{Ae(g),T||m(),Te()},()=>{Ae(g),m(),F("error","操作通道异常,已回滚"),Te()})}function F(i,d){var g;for(;Be.childElementCount>=3;)(g=Be.firstElementChild)==null||g.remove();const m=document.createElement("div");m.className="p-notice"+(i==="error"?" error":""),m.setAttribute("role",i==="error"?"alert":"status"),m.textContent=d,Be.appendChild(m),D.push(setTimeout(()=>m.remove(),4e3))}const k=jo({root:w,netBtn:Ee,signal:ae,model:e,teams:()=>gt,anchorFor:i=>(i.kind==="node"?Ye.get(i.id):Ke.get(i.name))??null,emit:p,notice:F});let _=[],Y=new Set;const ee=Bo({root:w,trigger:$e,signal:ae,model:e,facts:()=>({sessions:_,canvasMemberIds:Y,remoteTeams:qe,teams:gt}),menuItem:k.menuItem,emit:p,openNameDialog:k.openNameDialog,locate:J});function J(i){var g;const d=e.getNode(i);if(d===void 0)return;ee.close();const m=((g=t.viewSize)==null?void 0:g.call(t))??{w:w.clientWidth>0?w.clientWidth:800,h:w.clientHeight>0?w.clientHeight:600};s=Ct({scale:s.scale,x:d.x-m.w/(2*s.scale),y:d.y-m.h/(2*s.scale)}),Ue(),a=-1,Te()}function be(i){const d=w.getBoundingClientRect();return{x:i.clientX-d.left,y:i.clientY-d.top}}function ke(i,d){var j;const m=be(d),g=at(s,m.x,m.y),T=En(new Map(e.allFrames()),g),W=i.ids.filter(X=>{const ie=e.getNode(X);return ie===void 0?!1:ie.remote!==!0?!0:ie.remoteHandle!==void 0&&ie.remoteHandle!==""});if(T!==void 0){const X=W.filter(ie=>{var fe;return!((fe=e.getNode(ie))!=null&&fe.memberships.some(re=>re.team===T))});if(X.length>0){p({type:"add-member",team:T,ids:X});return}if(i.ids.length===1&&((j=e.getNode(i.clicked))==null?void 0:j.remote)!==!0){const ie=e.teamMemberIds(T),fe=Ro(e,T);fe.join("\0")!==ie.join("\0")&&p({type:"reorder",team:T,ops:qt(ie,fe)})}}}function Pe(i){if(Ie===0&&He(),k.isDialogOpen()){i.preventDefault();return}const d=i.target;if(k.isMenuOpen()){if(d!==null&&d.closest(".p-menu")!==null)return;k.closeMenu(),i.preventDefault();return}const m=be(i);if(i.button===2){q={x:m.x,y:m.y,target:i.target,moved:!1},i.preventDefault();try{w.setPointerCapture(i.pointerId??0)}catch{}return}if(d!==null&&(d.closest("button")!==null||d.closest(".p-lamp")!==null||d.closest(".p-status")!==null))return;const g=d!==null?d.closest(".p-node"):null,T=d!==null?d.closest(".p-frame-head"):null;if((g!==null||T!==null)&&i.button===1){n={kind:"pan",last:m,moved:!1},i.preventDefault();try{w.setPointerCapture(i.pointerId??0)}catch{}return}const W=d!==null?d.closest(".p-frame-handle"):null;if(N!==void 0){const j=Ke.get(N),X=d!==null&&j!==void 0&&(j.contains(d)||j===d),ie=T!==null&&T.dataset.frame===N;!X&&!ie&&v(void 0)}if(W!==null&&i.button===0){const j=W.dataset.frame??"";v(j);const X=e.getFrame(j);if(X===void 0)return;n={kind:"frame-resize",name:j,dir:W.dataset.dir??"se",startRect:{...X},origin:at(s,m.x,m.y),moved:!1},i.preventDefault();try{w.setPointerCapture(i.pointerId??0)}catch{}return}if(g!==null){if(i.button!==0)return;const j=g.dataset.id??"",X=e.isSelected(j);!X&&!i.shiftKey&&e.setSelection([j]);const ie=i.shiftKey||X?e.isSelected(j)?e.selectedIds():[...e.selectedIds(),j]:[j];n={kind:"node",clicked:j,ids:ie,last:at(s,m.x,m.y),moved:!1,el:g},g.classList.add("dragging")}else if(T!==null){if(i.button!==0)return;const j=T.dataset.frame??"";v(j);const X=e.beginFrameDrag(j);if(X===void 0)return;n={kind:"frame",name:j,snap:X,origin:at(s,m.x,m.y),moved:!1}}else if(i.button===1||i.button===0&&r)n={kind:"pan",last:m,moved:!1};else if(i.button===0)n={kind:"marquee",origin:m,last:m,additive:i.shiftKey},b.style.display="block",b.style.left=`${m.x}px`,b.style.top=`${m.y}px`,b.style.width="0px",b.style.height="0px";else return;i.preventDefault();try{w.setPointerCapture(i.pointerId??0)}catch{}}function te(i){const d=be(i);if(q!==null){const m=d.x-q.x,g=d.y-q.y;Math.hypot(m,g)>4&&(q.moved=!0,s=Ct(Ut(s,-m,-g)),q.x=d.x,q.y=d.y,Ue());return}if(n.kind==="node"){const m=at(s,d.x,d.y),g=m.x-n.last.x,T=m.y-n.last.y;if(g===0&&T===0)return;n.moved=!0,n.last=m,e.dragNodes(n.ids,g,T);const W=En(new Map(e.allFrames()),m),j=n.ids.filter(ie=>{const fe=e.getNode(ie);return fe===void 0?!1:fe.remote!==!0||fe.remoteHandle!==void 0&&fe.remoteHandle!==""}),X=W!==void 0&&j.length>0;for(const[ie,fe]of Ke)fe.classList.toggle("drop-target",X&&ie===W);Te()}else if(n.kind==="frame"){const m=at(s,d.x,d.y),g=m.x-n.origin.x,T=m.y-n.origin.y;if(!n.moved&&g===0&&T===0)return;n.moved=!0,e.applyFrameDrag(n.snap,g,T),Te()}else if(n.kind==="frame-resize"){const m=at(s,d.x,d.y),g=m.x-n.origin.x,T=m.y-n.origin.y;if(!n.moved&&g===0&&T===0)return;n.moved=!0;const W=220,j=120,X={...n.startRect};let{x:ie,y:fe,w:re,h:de}=X;n.dir.includes("e")&&(re=Math.max(W,X.w+g)),n.dir.includes("s")&&(de=Math.max(j,X.h+T)),n.dir.includes("w")&&(re=Math.max(W,X.w-g),ie=X.x+(X.w-re)),n.dir.includes("n")&&(de=Math.max(j,X.h-T),fe=X.y+(X.h-de)),e.setFrame(n.name,{x:Math.round(ie),y:Math.round(fe),w:Math.round(re),h:Math.round(de)}),Te()}else if(n.kind==="pan")s=Ut(s,d.x-n.last.x,d.y-n.last.y),n.last=d,n.moved=!0,Ue();else if(n.kind==="marquee"){const m=Math.min(n.origin.x,d.x),g=Math.min(n.origin.y,d.y);b.style.left=`${m}px`,b.style.top=`${g}px`,b.style.width=`${Math.abs(d.x-n.origin.x)}px`,b.style.height=`${Math.abs(d.y-n.origin.y)}px`,n.last=d}}function Se(i){var d,m;if(q!==null){const g=q.moved,T=q.target,W=q.x,j=q.y;q=null,g?(we=!0,S()):T!==null&&k.contextMenuAt(W,j,T);return}if(n.kind==="node"){const g=n.clicked;if(n.moved)ke(n,i),S();else if(i.shiftKey){const T=e.selectedIds();e.setSelection(T.includes(g)?T.filter(W=>W!==g):[...T,g])}else e.setSelection([g]),(d=t.onNodePick)==null||d.call(t,g);for(const T of Ke.values())T.classList.remove("drop-target");(m=n.el)==null||m.classList.remove("dragging"),Te()}else if(n.kind==="frame")n.moved&&S();else if(n.kind==="frame-resize")n.moved&&S();else if(n.kind==="pan")n.moved&&S();else if(n.kind==="marquee"){const g=n.last,T=at(s,Math.min(n.origin.x,g.x),Math.min(n.origin.y,g.y)),W=at(s,Math.max(n.origin.x,g.x),Math.max(n.origin.y,g.y));e.marqueeSelect({x:T.x,y:T.y,w:W.x-T.x,h:W.y-T.y},n.additive),b.style.display="none",Te()}n={kind:"none"};try{w.releasePointerCapture(i.pointerId??0)}catch{}}function je(i){k.isMenuOpen()&&k.closeMenu();const d=be(i);if(i.shiftKey&&!i.ctrlKey){const m=i.deltaMode===1?16:1;s=Ct(Ut(s,(i.deltaX??0)*m,(i.deltaY??0)*m))}else{const m=i.deltaMode===1?16:1,g=Math.exp(-((i.deltaY??0)*m)*.0015);s=kn(s,g,d.x,d.y)}i.preventDefault(),Ue(),S()}function De(i){He(),s=kn(s,i,Ie/2,Fe/2),Ue(),S()}function nt(){He(),s=Xt(e.contentBounds(),Ie,Fe),Ue(),S()}function Re(i){var W,j,X,ie,fe;if(k.isDialogOpen()||i.ctrlKey||i.metaKey)return;if(k.isMenuOpen()){i.key==="Escape"&&(k.closeMenu(),i.preventDefault());return}if(i.key===" "&&i.target===w){r=!0,i.preventDefault();return}const d=((j=(W=i.target)==null?void 0:W.closest)==null?void 0:j.call(W,".p-frame-head"))??null;if((i.key==="Enter"||i.key===" ")&&d!==null){i.preventDefault();const re=d.getBoundingClientRect();k.contextMenuAt(re.left+re.width/2,re.top+re.height/2,d);return}if(i.key===" "&&((ie=(X=i.target)==null?void 0:X.classList)!=null&&ie.contains("p-node"))){const de=i.target.dataset.id??"",Me=e.selectedIds();e.setSelection(Me.includes(de)?Me.filter(Je=>Je!==de):[...Me,de]),Te(),i.preventDefault();return}if(i.key==="F10"&&i.shiftKey||i.key==="ContextMenu"){i.preventDefault();const re=document.activeElement??null,de=((fe=re==null?void 0:re.getBoundingClientRect)==null?void 0:fe.call(re))??{left:0,top:0,width:0,height:0};k.contextMenuAt(de.left+de.width/2,de.top+de.height/2,re);return}if(i.key==="Delete"||i.key==="Backspace"){i.preventDefault(),xe();return}if(i.altKey&&(i.key==="ArrowUp"||i.key==="ArrowDown")){i.preventDefault(),ot(i.key==="ArrowUp");return}if(i.key==="g"||i.key==="G"){k.startCreateFromSelection();return}if(i.key==="0"){nt();return}if(i.key==="="||i.key==="+"){De(1.2);return}if(i.key==="-"){De(1/1.2);return}if(i.key==="Escape"){if(k.isMenuOpen()){k.closeMenu(),Te();return}e.setSelection([]),Te();return}const m=i.shiftKey?40:8,T={ArrowLeft:[-m,0],ArrowRight:[m,0],ArrowUp:[0,-m],ArrowDown:[0,m]}[i.key];if(T!==void 0){i.preventDefault();const re=e.selectedIds();re.length>0&&(e.nudge(re,T[0],T[1]),Te(),S())}}function xe(){var g,T,W;const i=document.activeElement,d=((g=i==null?void 0:i.closest)==null?void 0:g.call(i,".p-frame-head"))??null,m=((T=i==null?void 0:i.closest)==null?void 0:T.call(i,".p-node"))??null;if(d!==null){p({type:"remove-team",name:d.dataset.frame??""});return}if(m!==null){const j=m.dataset.id??"",X=((W=e.getNode(j))==null?void 0:W.memberships.map(ie=>ie.team))??[];if(X.length===0){F("info","该节点未加入任何团队");return}if(X.length===1){p({type:"remove-member",team:X[0],ids:[j]});return}k.openMenu(window.innerWidth/2,window.innerHeight/2,{kind:"node",id:j},"leave",m);return}F("info","焦点不在节点或团队框上")}function ot(i){var re,de;const d=document.activeElement,m=((re=d==null?void 0:d.closest)==null?void 0:re.call(d,".p-node"))??null;if(m===null)return;const g=m.dataset.id??"",T=((de=e.getNode(g))==null?void 0:de.memberships)??[];if(T.length!==1)return;const W=T[0].team,j=e.teamMemberIds(W),X=j.indexOf(g),ie=i?Math.max(0,X-1):Math.min(j.length-1,X+1);if(ie===X)return;const fe=[...j];fe.splice(X,1),fe.splice(ie,0,g),p({type:"reorder",team:W,ops:qt(j,fe)})}function bt(i){i.key===" "&&(r=!1)}w.addEventListener("pointerdown",i=>Pe(i),ae),w.addEventListener("pointermove",i=>te(i),ae),w.addEventListener("pointerup",i=>Se(i),ae),w.addEventListener("wheel",i=>je(i),{...ae,passive:!1}),w.addEventListener("keydown",i=>Re(i),ae),w.addEventListener("keyup",i=>bt(i),ae),w.addEventListener("contextmenu",i=>{const d=i;if(d.preventDefault(),d.preventDefault(),we){we=!1;return}k.contextMenuAt(d.clientX,d.clientY,d.target)},ae);let gt=[];function Ht(i){var Me,Je,ze;gt=i.teams,i.peers,A=i.inFlight??[],_=i.sessions,k.setUnjoined(i.sessions.filter(y=>y.joined!==!0&&!y.id.startsWith("peer-")));const d=new Map;for(const y of i.teams)for(let ce=0;ce<y.members.length;ce++){const V=y.members[ce].id,Le=d.get(V)??[];Le.push({team:y.name,index:ce}),d.set(V,Le)}Y=new Set(d.keys());const m=new Set,g=y=>{const ce=d.get(y)??[];if(se.size===0)return ce;const V=ce.filter(Ne=>!se.has(Ne.team)),Le=[];for(const[Ne]of se){const ve=e.teamMemberIds(Ne).indexOf(y);ve>=0&&Le.push({team:Ne,index:ve})}return[...V,...Le]};let T;if(o===void 0&&!e.allNodes().some(y=>y.remote!==!0)){const y=i.sessions.filter(ce=>{var V;return ce.joined===!0&&(g(ce.id).length>0||(((V=ce.teams)==null?void 0:V.length)??0)>0)}).map(ce=>ce.id);He(),T=xo(i.teams,y,Ie>0?Ie:void 0)}for(const y of i.sessions){if(y.joined!==!0)continue;const ce=g(y.id);if(!(ce.length===0&&(y.teams===void 0||y.teams.length===0)))if(m.add(y.id),e.getNode(y.id)!==void 0)e.upsertNode({id:y.id,x:e.getNode(y.id).x,y:e.getNode(y.id).y,label:y.label,team:y.team,name:y.name,live:y.live!==!1,memberships:ce,...y.teams!==void 0&&y.teams.length>0?{teams:y.teams}:{}});else{const V=o==null?void 0:o.nodes[y.id];let Le,Ne;if(V!==void 0)Le=V.x,Ne=V.y;else{const Ce=(T==null?void 0:T.get(y.id))??an(y.id);Le=Ce.x,Ne=Ce.y}e.upsertNode({id:y.id,x:Le,y:Ne,label:y.label,team:y.team,name:y.name,live:y.live!==!1,memberships:ce,...y.teams!==void 0&&y.teams.length>0?{teams:y.teams}:{}})}}for(const y of e.nodeIds())!m.has(y)&&!y.startsWith("peer-")&&!y.startsWith("member-")&&e.removeNode(y);const W=new Set;qe=No(i.remoteTeams??[]),l.clear();for(const y of i.peers??[])l.set(Et(y.url),y.score),I.set(Et(y.url),{link:y.link,verified:y.verified});if(i.peers!==void 0){const y=e.contentBounds(),ce=Io(i.peers,y);i.peers.forEach((V,Le)=>{var rn,ln,dn,cn;const Ne=$o(V.url);W.add(Ne);const Ce=o==null?void 0:o.nodes[Ne],ve=e.getNode(Ne),ct=ve!==void 0?{x:ve.x,y:ve.y}:Ce!==void 0?{x:Ce.x,y:Ce.y}:{x:((rn=ce[Le])==null?void 0:rn.x)??200,y:((ln=ce[Le])==null?void 0:ln.y)??0},Ze=Et(V.url),wt=(cn=(dn=qe.get(Ze))==null?void 0:dn[0])==null?void 0:cn.team;e.upsertNode({id:Ne,x:ct.x,y:ct.y,label:V.url,team:"",name:V.url,peerUrl:V.url,remoteHandle:wt,live:!0,remote:!0,memberships:[]}),e.upsertScore(Ne,V.score)})}for(const y of e.nodeIds())y.startsWith("peer-")&&!W.has(y)&&e.removeNode(y);const j=new Set;for(const[y,ce]of qe){const V=e.allNodes().find(Ce=>Ce.remote===!0&&Et(Ce.peerUrl??"")===y&&!Ce.id.startsWith("member-")),Le=((V==null?void 0:V.x)??400)+190;let Ne=(V==null?void 0:V.y)??0;for(const Ce of ce){if(!Ce.team.includes("/"))continue;const ve=`member-${Ce.team.replace(/[^a-z0-9-]/gi,"-")}`;if(j.has(ve))continue;j.add(ve);const ct=o==null?void 0:o.nodes[ve],Ze=e.getNode(ve),wt=Ze!==void 0?{x:Ze.x,y:Ze.y}:ct!==void 0?{x:ct.x,y:ct.y}:{x:Le,y:Ne};Ne+=92,e.upsertNode({id:ve,x:wt.x,y:wt.y,label:Ce.team,team:Ce.team,name:Ce.name!==void 0&&Ce.name!==""?Ce.name:Ce.team,remoteHandle:Ce.team,live:!0,remote:!0,memberships:[]})}}for(const y of e.nodeIds())y.startsWith("member-")&&!j.has(y)&&e.removeNode(y);const X=new Map;for(const y of e.allNodes())y.remote!==!0||y.remoteHandle===void 0||y.remoteHandle===""||(!X.has(y.remoteHandle)||y.id.startsWith("member-"))&&X.set(y.remoteHandle,y.id);for(const y of i.teams){if(se.has(y.name))continue;const ce=[];for(const Ne of y.members){const Ce=X.get(Ne.id)??Ne.id;e.getNode(Ce)!==void 0&&ce.push(Ce)}const V=[...e.teamMemberIds(y.name)].sort().join("|"),Le=[...ce].sort().join("|");V!==Le&&e.setTeamMembers(y.name,ce)}const ie=new Map,fe=x;if(x=ie,i.peerOrg!==void 0){let y=0;const ce=new Set(i.teams.map(V=>V.name));for(const V of i.peerOrg){const Le=((Je=(Me=i.remoteTeams)==null?void 0:Me.find(ve=>ve.via===V.url))==null?void 0:Je.team.split("/")[0])??"dsh",Ne=ve=>ve.replace(/^session-/,"").slice(0,8),Ce=ve=>ve.includes("/")?`member-${ve.replace(/[^a-z0-9-]/gi,"-")}`:`member-${Le}-${Ne(ve)}`;for(const ve of V.org){if(ve.name===""||ce.has(ve.name))continue;const ct=ve.members.map(Ce).filter(wt=>e.getNode(wt)!==void 0),Ze=(ze=o==null?void 0:o.frames)==null?void 0:ze[ve.name];e.getFrame(ve.name)===void 0&&e.setFrame(ve.name,Ze!==void 0?{x:Ze.x,y:Ze.y,w:Ze.w,h:Ze.h}:{x:200+y%4*280,y:940+Math.floor(y/4)*160,w:250,h:130}),e.setTeamMembers(ve.name,ct),ie.set(ve.name,V.url),y+=1}}}for(const[y,ce]of fe)ie.has(y)||e.removeFrame(y);const re=new Map;for(const y of e.allNodes())y.remote===!0&&y.remoteHandle!==void 0&&y.remoteHandle!==""&&re.set(y.remoteHandle,y.id);const de=Fn(i.teams);for(const y of i.teams){if(e.getFrame(y.name)!==void 0||se.has(y.name))continue;const ce=o==null?void 0:o.frames[y.name];if(ce!==void 0){e.setFrame(y.name,{...ce});continue}const V=[],Le=[];for(const Ce of y.members){const ve=e.getNode(re.get(Ce.id)??Ce.id);ve!==void 0&&(Le.push(ft(ve)),de.get(ve.id)===y.name&&V.push(ft(ve)))}const Ne=V.length>0?V:Le;Ne.length>0&&e.setFrame(y.name,nn(Ne))}for(const[y]of e.allFrames())se.has(y)||!i.teams.some(ce=>ce.name===y)&&!ie.has(y)&&e.removeFrame(y);if(ee.refresh(),he(i),u&&n.kind==="none"&&e.nodeIds().length>0&&(He(),Ie>0&&Fe>0)){u=!1;let y=e.contentBounds();for(const ce of e.allNodes()){if(ce.remote!==!0)continue;const V=ft(ce);y=y===null?{minX:V.x,minY:V.y,maxX:V.x+V.w,maxY:V.y+V.h}:{minX:Math.min(y.minX,V.x),minY:Math.min(y.minY,V.y),maxX:Math.max(y.maxX,V.x+V.w),maxY:Math.max(y.maxY,V.y+V.h)}}s=Xt(y,Ie,Fe,1)}Te()}function an(i){return Dn(i,e.allNodes().filter(d=>d.remote!==!0))}function Bn(i){const d=On(i);if(d===void 0)return;o=d;const m=t.viewportStore;if(m===void 0)u=!1,n.kind==="none"&&(s=Ct({...d.viewport}));else if(!C&&n.kind==="none"){C=!0;const g=m.get(c());g!=null&&Number.isFinite(g.x)&&Number.isFinite(g.y)&&Number.isFinite(g.scale)?(s=Ct({x:g.x,y:g.y,scale:g.scale}),u=!1):c()==="wide"&&(s=Ct({...d.viewport}),u=!1)}a=-1,Te()}function Hn(){return go(s,e.positions(),e.frameRects())}function Yn(i,d){$.classList.remove("pending","saved","error"),i==="pending"&&$.classList.add("pending"),i==="saved"&&$.classList.add("saved"),i==="error"&&$.classList.add("error"),i==="error"?($.tabIndex=0,$.setAttribute("role","button"),$.setAttribute("aria-label","布局保存失败,按回车重试")):($.removeAttribute("tabindex"),$.removeAttribute("role"),$.removeAttribute("aria-label"));const m=i==="pending"?"布局待保存…":i==="saved"?`布局已保存 ${d??""}`.trimEnd():i==="error"?"保存失败 · 回车重试":"布局";oe.textContent=m}function Wn(){w.style.display="block",He(),Ue(),w.focus()}function Kn(){w.style.display="none"}function Un(){K.abort();for(const i of D)clearTimeout(i)}return{root:w,reconcile:Ht,activate:Wn,deactivate:Kn,adoptExternalLayout:Bn,snapshotDoc:Hn,setLamp:Yn,notice:F,destroy:Un,seam:{pointerDown:Pe,pointerMove:te,pointerUp:Se,wheel:je,key:Re,keyUp:bt,contextMenu(i){i.preventDefault(),k.contextMenuAt(i.clientX,i.clientY,i.target)}}}}const Ko=800;function Uo(t){let e,o=!1,s=!1,n=!1,r="idle";function a(S){S!==r&&(r=S,t.onLamp(S))}function u(){e!==void 0&&(e(),e=void 0)}function C(){u(),e=t.schedule(()=>{e=void 0,c(!1)},Ko)}async function c(S){if(o){s=!0;return}o=!0,u();const R=t.snapshot();let K;try{K=JSON.stringify(R)}catch{o=!1,a("error"),t.onHttpError("layout document is not JSON-serializable");return}try{const D=await t.send(R,{keepalive:S});if(D===null||typeof D!="object"||D.ok!==!0){a("error");const q=D!==null&&typeof D=="object"&&typeof D.error=="string"?D.error:"layout save refused";t.onHttpError(`layout save: ${q}`)}else JSON.stringify(t.snapshot())===K&&(t.onAdopt(D.layout),a("saved"))}catch(D){a("error"),t.onHttpError(`layout save unreachable: ${String((D==null?void 0:D.message)??D).slice(0,80)}`)}if(o=!1,r==="error"){n=!1;return}if(n){n=!1,c(!0);return}s&&(s=!1,a("pending"),C())}return{markDirty(){if(s=!1,a("pending"),o){s=!0;return}C()},retry(){r!=="error"||o||(a("pending"),c(!1))},flush(){if(o){n=!0,s=!0;return}u(),c(!0)},isBusy(){return o},dispose(){u()}}}function Nn(t){return typeof t.error=="string"?t.error:void 0}function Xo(t){const e=new Map;let o=0;function s(a,u){o+=1;const C=e.get(a)??Promise.resolve(),c=async()=>{try{return await u()}finally{o-=1}},S=C.then(c,c);return e.set(a,S.then(()=>{},()=>{})),S}async function n(a){let u;try{u=await t.send(a)}catch(c){const S=String((c==null?void 0:c.message)??c).slice(0,80);return t.onNotice("error",`画布不可达:${S}`),!1}if(u.status>=400)return t.onNotice("error",Nn(u.body)??`HTTP ${u.status}`),!1;if(u.body.ok===!0)return!0;const C=Nn(u.body);return C!==void 0?(t.onNotice("error",C),!1):!0}async function r(a,u){for(const C of u)if(!await n({...a,id:C}))return!1;return!0}return{createTeam(a,u,C=!1){return s(a,async()=>{if(!await n({action:"create",name:a}))return!1;for(let c=0;c<u.length;c++)if(!await n({action:"add-member",name:a,id:u[c]}))return C&&c===0&&await n({action:"remove",name:a}),!1;return!0})},addMembers(a,u){return s(a,()=>r({action:"add-member",name:a},u))},removeMembers(a,u){return s(a,()=>r({action:"remove-member",name:a},u))},runRosterOps(a,u){return s(a,async()=>{for(const C of u){const c=C.op==="remove"?{action:"remove-member",name:a,id:C.id}:{action:"add-member",name:a,id:C.id};if(!await n(c))return!1}return!0})},removeTeam(a){return s(a,()=>n({action:"remove",name:a}))},hasPending(){return o>0}}}const jn=document.getElementById("app"),Jo=(()=>{try{return window.sessionStorage.getItem("dsh_a2a_key")??""}catch{return""}})(),Gt=window.__DSH_A2A_KEY__??Jo,We=(t,e={})=>fetch(t,{...e,headers:{...e.headers??{},...Gt!==""?{"X-API-Key":Gt}:{}}});Gt===""&&We("/__dsh_a2a/owner-settings").then(t=>{if(t.status!==401)return;const e=document.createElement("div");e.className="nexus-keygate",e.style.cssText="position:fixed;inset:0;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:10px;background:#fff;z-index:9999;font:14px/1.5 system-ui,sans-serif;color:#000";const o=document.createElement("div");o.textContent="此面板经远程面打开(密钥不随页面下发)——输入控制密钥";const s=document.createElement("input");s.type="password",s.placeholder="X-API-Key",s.setAttribute("aria-label","控制密钥");const n=document.createElement("button");n.type="button",n.textContent="进入面板";const r=document.createElement("div");r.style.color="#b00";const a=()=>{const u=s.value.trim();u!==""&&fetch("/__dsh_a2a/owner-settings",{headers:{"X-API-Key":u}}).then(C=>{if(C.status===401){r.textContent="密钥不对,再试一次";return}try{window.sessionStorage.setItem("dsh_a2a_key",u)}catch{}window.location.reload()})};n.addEventListener("click",a),s.addEventListener("keydown",u=>{u.key==="Enter"&&a()}),e.append(o,s,n,r),document.body.appendChild(e)});const At=document.createElement("div");At.className="nexus-fault";jn.appendChild(At);const{fault:Qt,clear:zo}=zn({show(t){At.textContent=t,At.style.display="block"},hide(){At.style.display="none"}},t=>console.error(t));let Pt;const Mn="dsh-a2a.viewport.",Vo={get(t){try{const e=window.localStorage.getItem(Mn+t);return e===null?void 0:JSON.parse(e)}catch{return}},set(t,e){try{window.localStorage.setItem(Mn+t,JSON.stringify({x:e.x,y:e.y,scale:e.scale}))}catch{}}},lt=Wo({viewportStore:Vo,onDirty:()=>Dt.markDirty(),onLampClick:()=>Dt.retry(),onNodePick:t=>{Pt==null||Pt(t)},onCanvasAction:async t=>{const e=await qo(t);return Bt(),e}}),Dt=Uo({snapshot:()=>lt.snapshotDoc(),send:(t,e)=>We("/__dsh_a2a/canvas-layout",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"save",layout:t}),cache:"no-store",keepalive:e.keepalive}).then(async o=>await o.json()),schedule:(t,e)=>{const o=setTimeout(t,e);return()=>{clearTimeout(o)}},now:Date.now,onLamp:t=>{Zt=t;const e=new Date,o=String(e.getHours()).padStart(2,"0")+":"+String(e.getMinutes()).padStart(2,"0");lt.setLamp(t,o)},onAdopt:t=>{lt.adoptExternalLayout(t)},onHttpError:t=>Qt(t)});window.addEventListener("pagehide",()=>Dt.flush());const St=Xo({send:async t=>{const e=await We("/__dsh_a2a/canvas",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),cache:"no-store"});return{status:e.status,body:await e.json()}},onNotice:(t,e)=>lt.notice(t,e)});function qo(t){if((t.type==="add-member"||t.type==="remove-member")&&t.fleetPeer!==void 0)return(async()=>{for(const e of t.ids){const o=await We("/__dsh_a2a/fleet-canvas-op",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({peer:t.fleetPeer,op:t.type==="add-member"?"add-member":"remove-member",name:t.team,id:e}),cache:"no-store"}).catch(()=>{}),s=o!==void 0?await o.json().catch(()=>{}):void 0;if((s==null?void 0:s.ok)!==!0)return!1}return!0})();switch(t.type){case"create-team":return St.createTeam(t.name,t.ids,t.created);case"add-member":return St.addMembers(t.team,t.ids);case"remove-member":return St.removeMembers(t.team,t.ids);case"remove-team":return St.removeTeam(t.name);case"reorder":return St.runRosterOps(t.team,t.ops);case"join-network":case"leave-network":return Go(t.type==="join-network"?"join":"leave",t.id)}}async function Go(t,e){const o=await We(`/__dsh_a2a/${t}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:e}),cache:"no-store"}).catch(()=>{});return o!==void 0&&o.ok}let Zt="idle",Rt=!1,Sn,Jt=!1;async function Qo(){const t=await We("/__dsh_a2a/canvas-layout",{cache:"no-store"});if(!t.ok)throw new Error(`/__dsh_a2a/canvas-layout ${t.status}`);return(await t.json()).layout??null}const jt=ho({now:()=>Date.now(),async ownerSettingsRead(){try{return await(await We("/__dsh_a2a/owner-settings")).json()}catch{return{ok:!1,error:"unreachable"}}},async ownerSettingsWrite(t){try{return await(await We("/__dsh_a2a/owner-settings",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t)})).json()}catch{return{ok:!1,error:"unreachable"}}},async abandon(t,e){try{return(await We("/__dsh_a2a/tasks/abandon",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({task_id:t,reason:e})})).ok}catch{return!1}},copy(t){var e;(e=navigator.clipboard)==null||e.writeText(t).catch(()=>{})},async canvasOp(t,e,o){try{const s=await We("/__dsh_a2a/canvas",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({action:t,name:e,id:o})}),n=await s.json().catch(()=>({}));return s.ok&&n.ok!==!1?!0:(console.warn(`canvas ${t} ${e}: ${n.error??`HTTP ${s.status}`}`),!1)}catch{return!1}},async dispatchQuick(t,e){try{const o=await We("/__dsh_a2a/dispatch",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({team:t,message:e})}),s=await o.json().catch(()=>({}));return{ok:o.ok&&s.ok===!0,task_id:s.task_id,reply:s.reply,error:s.error??`HTTP ${o.status}`}}catch(o){return{ok:!1,error:o instanceof Error?o.message:String(o)}}},async sessionLog(t){try{const e=await We(`/__dsh_a2a/session-log?id=${encodeURIComponent(t)}`),o=await e.json().catch(()=>({}));return{ok:e.ok&&o.ok===!0,messages:o.messages,error:o.error??(e.ok?void 0:`HTTP ${e.status}`)}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}},async sessionLogList(){try{const t=await We("/__dsh_a2a/session-log"),e=await t.json().catch(()=>({}));return{ok:t.ok&&e.ok===!0,sessions:e.sessions,count:typeof e.count=="number"?e.count:void 0,error:e.error??(t.ok?void 0:`HTTP ${t.status}`)}}catch(t){return{ok:!1,error:t instanceof Error?t.message:String(t)}}},async remoteSessionLog(t){try{const e=new URLSearchParams;t.team!==void 0&&e.set("team",t.team),t.peer!==void 0&&e.set("peer",t.peer),t.id!==void 0&&e.set("id",t.id),t.limit!==void 0&&e.set("limit",String(t.limit));const o=await We(`/__dsh_a2a/remote-session-log?${e.toString()}`),s=await o.json().catch(()=>({}));return{ok:o.ok&&s.ok===!0,messages:s.messages,sessions:s.sessions,error:s.error??(o.ok?void 0:`HTTP ${o.status}`),via:s.via}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}},board:{root:lt.root,activate:()=>lt.activate(),deactivate:()=>lt.deactivate(),available:()=>Rt}});jn.appendChild(jt.root);Pt=t=>{jt.openNodeChat(t)};if(new URLSearchParams(window.location.search).get("mode")==="plan"){const t=window.setInterval(()=>{Rt&&(jt.selectTab("board"),window.clearInterval(t))},300);window.setTimeout(()=>window.clearInterval(t),3e4)}async function Bt(){var t;try{const e=await We("/__dsh_a2a/state",{cache:"no-store"});if(!e.ok)throw new Error(`/__dsh_a2a/state ${e.status}`);const o=await e.json();if(zo(),Rt=o.canvas!==void 0,jt.update(o),Rt)try{const c=await Qo(),S=JSON.stringify(c??null);S!==Sn&&(Sn=S,(Zt==="idle"||Zt==="saved")&&!Dt.isBusy()&<.adoptExternalLayout(c)),Jt=!0}catch(c){if(!Jt){Qt(`canvas layout 获取失败:${String(c)}`);return}}else Jt=!0;const s=(o.sessions??[]).map(c=>({...c,joined:c.joined===!0})),n=((t=o.canvas)==null?void 0:t.teams)??[],r=(o.peers??[]).filter(c=>c!==null&&typeof c=="object"&&typeof c.url=="string"),a=(o.inFlight??[]).filter(c=>c!==null&&typeof c=="object"&&typeof c.team=="string"&&typeof c.peer=="string"&&Number.isFinite(c.startedAt)),u=(o.remote??[]).filter(c=>c!==null&&typeof c=="object"&&typeof c.team=="string"&&typeof c.via=="string").map(c=>({team:c.team,name:c.name,via:c.via,workspace:c.workspace,...typeof c.origin=="string"&&c.origin!==""?{origin:c.origin}:{},...Array.isArray(c.teams)&&c.teams.length>0?{teams:c.teams.filter(S=>typeof S=="string"&&S!=="")}:{}})),C=(o.peerOrg??[]).filter(c=>c!==null&&typeof c=="object").filter(c=>typeof c.url=="string"&&Array.isArray(c.org)).map(c=>({url:c.url,org:c.org.filter(S=>S!==null&&typeof S=="object").filter(S=>typeof S.team=="string"&&S.team!=="").map(S=>({name:typeof S.name=="string"?S.name:"",team:S.team,members:Array.isArray(S.members)?S.members.filter(R=>typeof R=="string"):[]}))}));lt.reconcile({sessions:s,teams:n,peerCount:r.length,peers:r,inFlight:a,remoteTeams:u,peerOrg:C})}catch(e){Qt(`state 轮询失败:${String(e)}`)}}Bt();window.setInterval(()=>{document.hidden||Bt()},3e3);document.addEventListener("visibilitychange",()=>{document.hidden||Bt()});
|
|
@@ -0,0 +1 @@
|
|
|
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-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;text-overflow:ellipsis;white-space:nowrap}#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{font-size:11px;color:var(--ink-muted);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#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-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:8px 12px;display:grid;gap: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{left:8px;right:8px;top:8px;overflow-x:auto;scrollbar-width:none}#dsh-plan .p-toolbar>*{flex:none}#dsh-plan .p-status{left:8px;right:auto;top:58px;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-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-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:help}.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:1px 9px;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-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-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-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}
|
|
@@ -18,8 +18,8 @@ html,body{margin:0;height:100%;background:var(--n-bg);color:var(--n-ink);
|
|
|
18
18
|
font-family:"Segoe UI",system-ui,sans-serif;}
|
|
19
19
|
#app{width:100%;height:100%;position:relative}
|
|
20
20
|
</style>
|
|
21
|
-
<script type="module" crossorigin src="./assets/index-
|
|
22
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
21
|
+
<script type="module" crossorigin src="./assets/index-DszoLz8i.js"></script>
|
|
22
|
+
<link rel="stylesheet" crossorigin href="./assets/index-uQf7NwjF.css">
|
|
23
23
|
</head>
|
|
24
24
|
<body>
|
|
25
25
|
<div id="app"></div>
|