@nelsonlongxiang/dsh-open-a2a-net 0.6.42 → 0.6.43

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.
@@ -17,7 +17,21 @@
17
17
  * @module @nelsonlongxiang/dsh-open-a2a-net/canvas-store
18
18
  */
19
19
  /** On-disk shape: ordered team entries, each an ordered member id list. */
20
+ export interface SuspendedCanvasMember {
21
+ readonly team: string;
22
+ readonly member: string;
23
+ readonly localSessionId: string;
24
+ readonly reason: 'leave' | 'archive' | 'remove';
25
+ readonly at: string;
26
+ readonly token: string;
27
+ }
28
+ /** A bare session handle is not a CLI identity or a qualified owner selector. */
29
+ export declare function legacyBareMember(id: string): boolean;
20
30
  export interface CanvasSnapshot {
31
+ readonly formatVersion?: number;
32
+ readonly revision?: number;
33
+ readonly memberOwners?: Readonly<Record<string, string>>;
34
+ readonly suspendedMembers?: readonly SuspendedCanvasMember[];
21
35
  readonly teams: ReadonlyArray<{
22
36
  readonly name: string;
23
37
  readonly members: readonly string[];
@@ -52,16 +66,27 @@ export declare function validRemoteMemberRef(id: string): boolean;
52
66
  * registry knowledge: callers validate join state and resolve members.
53
67
  */
54
68
  export declare class CanvasStore {
69
+ private readonly options;
55
70
  /** Team entries in creation order; members in add order (routing priority). */
56
71
  private teams;
57
72
  private cliHome;
58
73
  private cliHomeCleared;
74
+ private suspended;
75
+ private revision;
76
+ private committed;
77
+ private memberOwners;
78
+ private disk;
79
+ private readOnlyReason;
80
+ private lastWriteError;
81
+ private failedSuspension;
59
82
  private readonly path;
60
83
  private readonly listeners;
61
84
  /**
62
85
  * @param path - the snapshot file; an empty path keeps the store in memory.
63
86
  */
64
- constructor(path: string);
87
+ constructor(path: string, options?: {
88
+ legacyBareMembers?: boolean;
89
+ });
65
90
  /**
66
91
  * Observe changes: the listener runs after every write that changed the
67
92
  * store (never on restore). A throwing listener cannot break the write.
@@ -73,13 +98,35 @@ export declare class CanvasStore {
73
98
  private restore;
74
99
  /** Persist the current snapshot (no-op without a path), then tell the listeners. */
75
100
  private persist;
101
+ private serialize;
76
102
  private write;
103
+ private replaceFile;
104
+ private lockInfo;
77
105
  /** Every team name, in creation order. */
78
106
  list(): readonly string[];
79
107
  /** Whether the named team exists. */
80
108
  hasTeam(name: string): boolean;
81
109
  /** The named team's member ids in routing-priority order (a copy). */
82
110
  membersOf(name: string): readonly string[];
111
+ /** Inspection only: never use raw rows for routing, authorization or counts. */
112
+ rawMembersOf(name: string): readonly string[];
113
+ isSuspended(name: string, member: string): boolean;
114
+ suspensionOf(name: string, member: string): readonly SuspendedCanvasMember[];
115
+ state(): {
116
+ revision: number;
117
+ suspendedMembers: readonly SuspendedCanvasMember[];
118
+ error?: string;
119
+ lock?: unknown;
120
+ directoryFsync: string;
121
+ };
122
+ ownerKeyOf(member: string): string | undefined;
123
+ /** Durably revoke canvas consent BEFORE join/agent/roster state is removed. */
124
+ revokeLocal(id: string, ownQualified: string | undefined, inferredBare: string | undefined, reason: SuspendedCanvasMember['reason'], team?: string): boolean;
125
+ /** Owner-only CAS. The caller supplies the exact slot and the complete current suspension records. */
126
+ regulateSuspended(action: 'restore' | 'delete', team: string, member: string, revision: unknown, expected: unknown): {
127
+ ok: boolean;
128
+ error?: string;
129
+ };
83
130
  /** Frozen, operator-linked CLI home; undefined means unknown or ambiguous. */
84
131
  cliHomeOf(handle: string): string | undefined;
85
132
  pinnedCliHomes(): ReadonlyArray<readonly [string, string]>;
@@ -77,6 +77,8 @@ export interface Config {
77
77
  * closed, it signs and accepts the audience-bound form only.
78
78
  */
79
79
  readonly originClaimUnboundWindow: boolean;
80
+ /** #335: preserve unsuspended legacy bare member inference until the owner closes the window. */
81
+ readonly canvasLegacyBareMembers: boolean;
80
82
  /**
81
83
  * Extra origins this host answers to as an OriginClaim audience, beyond
82
84
  * its card URL and the address a request arrives on (port-mapped or
@@ -126,6 +126,8 @@ export interface AdminFaceDeps extends Pick<CanvasNotifyDeps, 'verifyOriginClaim
126
126
  readonly sessionTeamOf: (agent: Agent) => string;
127
127
  /** gh#131: the `<zone>/<id8>` handle a canvas may hold for this local session, if it reads as this session. */
128
128
  readonly ownCanvasHandleOf: (id: string) => string | undefined;
129
+ readonly revokeCanvasMember: (id: string, reason: 'leave' | 'archive' | 'remove', name?: string) => boolean;
130
+ readonly canvasMigrationState: () => Record<string, unknown>;
129
131
  /** gh#131: the local session a remote-shaped member ref reads as, if unambiguous. */
130
132
  readonly localSessionOfHandle: (ref: string) => string | undefined;
131
133
  /** gh#152: the session's canvas teams read through the local lens — a handle-stored membership of this session counts. */
@@ -299,6 +299,13 @@ const bench = createWorkbench({
299
299
  return { ...body, ok: res.ok && body.ok === true }
300
300
  } catch (error) { return { ok: false, error: String(error) } }
301
301
  },
302
+ async regulateSuspended(action, name, id, revision, expected) {
303
+ try {
304
+ const response = await controlFetch('/__dsh_a2a/canvas', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ action, name, id, revision, expected }) })
305
+ const body = await response.json() as { ok?: boolean; error?: string }
306
+ return { ok: response.ok && body.ok === true, error: body.error }
307
+ } catch (error) { return { ok: false, error: String(error) } }
308
+ },
302
309
  async canvasOp(action, name, id, home) {
303
310
  // Same control route the planning board's wire uses; the inspector's
304
311
  // member writes are one id at a time, so no serial fan-out needed.
@@ -128,6 +128,7 @@ export interface RemoteRow {
128
128
  * handle (`zone/id8`) — remote members are routed by the directory, never
129
129
  * woken locally (0.6.6 unified team model). */
130
130
  export interface CanvasMemberRow {
131
+ readonly provenance?: 'legacy-inferred' | 'unknown'
131
132
  readonly id: string
132
133
  readonly team?: string
133
134
  readonly joined?: boolean
@@ -160,7 +161,7 @@ export interface StateBody {
160
161
  readonly zone?: string
161
162
  readonly version?: string
162
163
  readonly sessions?: readonly SessionRow[]
163
- readonly canvas?: { teams?: readonly CanvasTeamRow[] }
164
+ readonly canvas?: { teams?: readonly CanvasTeamRow[]; revision?: number; retainedMembers?: ReadonlyArray<{ team: string; member: string; suspended: boolean; records: readonly unknown[] }> }
164
165
  /** gh#20 W-A/W-C: the peer row carries the link badge source, the host
165
166
  * rail's label/version/last-contact facts (absent on older hosts). */
166
167
  readonly peers?: ReadonlyArray<{
@@ -221,6 +222,7 @@ export interface WorkbenchDeps {
221
222
  * local session id or a zone-qualified remote handle. True on success. */
222
223
  canvasOp(action: 'add-member' | 'remove-member', name: string, id: string, home?: string): Promise<boolean>
223
224
  cliHomeOptions?(name: string, id: string): Promise<CliHomeOptions>
225
+ regulateSuspended?(action: 'restore-suspended' | 'delete-suspended', name: string, id: string, revision: number, expected: readonly unknown[]): Promise<{ ok: boolean; error?: string }>
224
226
  /** Quick dispatch (0.6.9): POST /__dsh_a2a/dispatch as a human gesture —
225
227
  * one message to a routing team, async delivery, receipt lands in the
226
228
  * ledger. Optional — without it the 快派 form hides. */
@@ -981,7 +983,7 @@ export function createWorkbench(deps: WorkbenchDeps): Workbench {
981
983
  for (const member of fresh.members) {
982
984
  const row = el('div', 'wb-member-row')
983
985
  const dot = member.cliHeld === true ? '本机持有,无需指定' : member.remote === true ? (member.cliHome === null ? '◇ 远端 · home 未确定' : '◇ 远端') : member.live === true ? '● 现场' : member.joined === true ? '○ 冷启' : '· 未入网'
984
- row.appendChild(el('span', 'wb-member-dot')).textContent = dot
986
+ row.appendChild(el('span', 'wb-member-dot')).textContent = dot + (member.provenance ? ' · 来源未确认' + (member.provenance === 'legacy-inferred' ? '(兼容推断)' : '') : '')
985
987
  const label = el('span', 'wb-member-label')
986
988
  const session = (last?.sessions ?? []).find(s => s.id === member.id)
987
989
  label.textContent = member.remote === true ? member.id : (session !== undefined ? displayName(session) : member.id)
@@ -1011,6 +1013,26 @@ export function createWorkbench(deps: WorkbenchDeps): Workbench {
1011
1013
  card.appendChild(form)
1012
1014
  }
1013
1015
  }
1016
+ const retained = (last?.canvas?.retainedMembers ?? []).filter(r => r.team === fresh.name)
1017
+ for (const slot of retained) {
1018
+ const row = el('div', 'wb-member-row')
1019
+ row.appendChild(el('span', 'wb-member-dot')).textContent = slot.suspended ? '已暂停 · 不参与路由' : '来源未确认 · 窗口关闭'
1020
+ row.appendChild(el('span', 'wb-member-label')).textContent = slot.member
1021
+ if (slot.suspended && deps.regulateSuspended && last?.canvas?.revision !== undefined) {
1022
+ for (const action of ['restore-suspended', 'delete-suspended'] as const) {
1023
+ const button = el('button', 'wb-member-remove'); button.type = 'button'
1024
+ button.textContent = action === 'restore-suspended' ? '显式恢复' : '删除暂停位'
1025
+ const revision = last.canvas.revision
1026
+ button.addEventListener('click', async () => {
1027
+ button.disabled = true
1028
+ const result = await deps.regulateSuspended!(action, fresh.name, slot.member, revision, slot.records)
1029
+ if (!result.ok) { button.disabled = false; button.title = result.error ?? '状态已变,请刷新后重试' }
1030
+ })
1031
+ row.appendChild(button)
1032
+ }
1033
+ }
1034
+ card.appendChild(row)
1035
+ }
1014
1036
  // Add-member form: static DOM re-mounted per poll (draftForm trick) —
1015
1037
  // rebuilt only when the inspected team changes.
1016
1038
  if (canvasForm?.name !== fresh.name) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nelsonlongxiang/dsh-open-a2a-net",
3
- "version": "0.6.42",
3
+ "version": "0.6.43",
4
4
  "description": "Open A2A network plugin for DeepSeek Harness: signed agent cards, decentralized peer/zone discovery, direct routing model tools, and joinable session nodes with a sidebar control",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -1,9 +0,0 @@
1
- var To=Object.defineProperty;var _o=(e,t,o)=>t in e?To(e,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):e[t]=o;var Et=(e,t,o)=>_o(e,typeof t!="symbol"?t+"":t,o);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))s(n);new MutationObserver(n=>{for(const i of n)if(i.type==="childList")for(const r of i.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&s(r)}).observe(document,{childList:!0,subtree:!0});function o(n){const i={};return n.integrity&&(i.integrity=n.integrity),n.referrerPolicy&&(i.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?i.credentials="include":n.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function s(n){if(n.ep)return;n.ep=!0;const i=o(n);fetch(n.href,i)}})();const ln=6e4;function Oo(e,t,o=Date.now){let s=-ln;return{fault(n){const i=o();i-s>=ln&&(t(`[nexus] ${n}`),s=i),e.show(n)},clear(){e.hide(),s=-ln}}}function lt(e){return e.name??e.team??e.label??""}function ao(e,t){var i,r;const o=(c,l)=>c!==void 0&&c.trim()!==""?{name:c,remote:l}:void 0,s=(e.sessions??[]).find(c=>c.team===t);if(s!==void 0)return o(lt(s),!1);const n=(e.remote??[]).find(c=>c.team===t);return n!==void 0?o(lt(n),!0):o((r=(((i=e.canvas)==null?void 0:i.teams)??[]).find(c=>c.team===t))==null?void 0:r.name,!1)}function Fo(e,t){const o=ao(e,t);return o===void 0?t:o.remote?`${o.name}(远端)`:o.name}function zt(e,t,o,s=""){const n=ao(t,o);if(e.textContent=`${s}${(n==null?void 0:n.name)??o}`,e.title=o,(n==null?void 0:n.remote)===!0){const i=e.appendChild(document.createElement("span"));i.className="wb-row-remote",i.textContent="远端",i.title="名字由对端自行发布"}}const Po=60*6e4;function $t(e){var t;return e.direction==="inbound"||e.direction===void 0&&((t=e.peer)==null?void 0:t.startsWith("local:"))===!0}function Tn(e){var t;return((t=e.peer)==null?void 0:t.startsWith("local:"))===!0?e.peer.slice(6):void 0}function Dt(e,t){return e.settleable!==void 0?e.settleable===!1:t-e.startedAt>=Po}function hn(e,t){const o=(e.tasks??[]).filter(r=>r.receiptExpected!==!1),s=o.filter(r=>!$t(r)&&Dt(r,t)),n=o.filter(r=>$t(r)&&Dt(r,t)),i=e.tasksDead??[];return{stale:s,owedOverdue:n,deadLetters:i.filter(r=>r.reason!=="fire-forget"),expired:i.filter(r=>r.reason==="fire-forget")}}function ke(e,t){const o=document.createElement(e);return t!==void 0&&(o.className=t),o}function _n(e,t){const o=Math.max(0,Math.round((t-e)/1e3));if(o<90)return`${o}s`;const s=Math.round(o/60);if(s<90)return`${s}m`;const n=Math.round(s/60);return n<48?`${n}h`:`${Math.round(n/24)}d`}function jt(e,t,o,s,n){const i=ke("div",`wb-led-tile${n!==void 0?` is-${n}`:""}`);i.title=s,i.appendChild(ke("span","wb-led-tile-v")).textContent=String(o),i.appendChild(ke("span","wb-led-tile-k")).textContent=t,e.appendChild(i)}const bn=[{key:"completed",label:"完成",tone:"completed"},{key:"sync_completed",label:"同步完成",tone:"completed"},{key:"rejected",label:"拒绝",tone:"rejected"},{key:"failed",label:"失败",tone:"failed"},{key:"expired",label:"过期",tone:"abandoned"},{key:"abandoned",label:"放弃",tone:"abandoned"},{key:"unknown",label:"结论不明",tone:"unclassified"},{key:"unclassified",label:"未分类",tone:"unclassified"}];function Do(e,t,o){const s=ke("div","wb-led-split"),n=ke("div","wb-led-split-bar");n.setAttribute("role","img");const i=ke("div","wb-led-split-legend"),r=new Set(bn.map(u=>u.key)),c=bn.map(u=>[u.tone,u.label,t[u.key]??0]);for(const[u,b]of Object.entries(t))r.has(u)||c.push(["other",u,b]);const l=[];for(const[u,b,m]of c){if(m<=0)continue;const x=ke("span",`wb-led-seg is-${u}`);x.style.width=`${Math.max(2,m/o*100)}%`,n.appendChild(x);const N=ke("span","wb-led-split-item");N.appendChild(ke("i",`wb-led-swatch is-${u}`)),N.appendChild(document.createTextNode(`${b} ${m}`)),i.appendChild(N),l.push(`${b} ${m}`)}n.setAttribute("aria-label",`归档结局:${l.join(",")}`),s.append(n,i),e.appendChild(s)}function Ro(e,t){var Me;e.replaceChildren();const{state:o,now:s}=t,n=o.tasks??[],i=o.tasksDead??[],r=o.archivedCount??0,c=hn(o,s),l=n.filter(D=>D.receiptExpected===!1),u=n.filter(D=>D.receiptExpected!==!1),b=u.filter(D=>$t(D)),m=u.filter(D=>!$t(D)),x=c.stale,N=m.filter(D=>!Dt(D,s)),Y=c.stale.length,re=ke("div","wb-led-tiles");jt(re,"待回执",u.length,`要回执、仍未结算的任务(含陈旧与本机欠对方的入站行)${l.length>0?`;另有免回执 ${l.length} 条不计`:""}`),jt(re,"陈旧",Y,"我方派发、要回执、已等待 ≥1h 仍未回执(可催办);本机欠对方的入站行在「待本机回执」组另计,免回执行不算陈旧",Y>0?"warn":void 0),jt(re,"死信",c.deadLetters.length,"超过 24h TTL 仍未结算(unconsumed);需清账(abandon)才能移出。免回执到期另列,不算死信",c.deadLetters.length>0?"danger":void 0),jt(re,"已归档",r,"已离开台账并留档的任务(结算、拒绝或放弃),用于审计"),e.appendChild(re),r>0&&o.archivedSplit!==void 0&&Do(e,o.archivedSplit,r);const V=(D,U)=>{const ce=ke("div",`wb-led-card is-${U.tone}`),Re=ke("div","wb-led-card-head");Re.appendChild(ke("span",`wb-led-dir${U.inbound?" is-in":""}`)).textContent=U.inbound?"↙":"↗";const Ee=ke("span","wb-led-brief");Ee.textContent=U.brief!==void 0&&U.brief!==""?U.brief:"(无摘要——派发未带 brief)",(U.brief===void 0||U.brief==="")&&Ee.classList.add("is-missing"),Re.appendChild(Ee),ce.appendChild(Re);const le=ke("div","wb-led-meta"),He=le.appendChild(ke("span","wb-led-team"));U.inbound?U.sender!==void 0?zt(He,o,U.sender,"来自 "):He.textContent="来自 对端":zt(He,o,U.team,"发往 "),U.inbound&&zt(le.appendChild(ke("span","wb-led-to")),o,U.team,"至 "),le.appendChild(ke("span")).textContent=U.atText,le.appendChild(ke("span","wb-led-task")).textContent=U.taskId;for(const fe of U.chips)le.appendChild(ke("span","wb-led-chip")).textContent=fe;if(ce.appendChild(le),ce.title=`${U.taskId}
2
- ${U.team}`,U.dead!==void 0){const fe=U.dead,q=fe.reason==="fire-forget",de=ke("button",`wb-btn wb-led-abandon${q?" is-quiet":""}`);de.type="button",de.textContent=q?"移出":"清账",de.title=q?"可选:把这条已过期的免回执记录移出台账(不是失败,不处理也无妨)":"从台账移出这条死信(abandon)",de.addEventListener("click",ee=>{ee.stopPropagation(),de.disabled=!0,t.abandon(fe.taskId,"workbench dead-letter cleanup").then(te=>{de.disabled=!1,de.textContent=te?"已清":"失败"})}),ce.appendChild(de)}if(t.canOpenTeam(U.team)){ce.classList.add("is-link"),ce.setAttribute("role","button"),ce.tabIndex=0,ce.setAttribute("aria-label",`${Ee.textContent},打开 ${U.team} 的对话`);const fe=()=>{t.openTeam(U.team)};ce.addEventListener("click",fe),ce.addEventListener("keydown",q=>{(q.key==="Enter"||q.key===" ")&&(q.preventDefault(),fe())})}D.appendChild(ce)},M=(D,U,ce,Re)=>{if(U===0)return null;const Ee=ke("div",`wb-led-group is-${ce}`);Ee.dataset.group=D;const le=ke("div","wb-led-group-head");return le.appendChild(ke("span")).textContent=`${D} · ${U}`,le.appendChild(ke("span","wb-led-group-hint")).textContent=Re,Ee.appendChild(le),e.appendChild(Ee),Ee},C=(D,U)=>{const ce=$t(D);return{brief:D.brief,team:D.team,sender:Tn(D),taskId:D.taskId,atText:`${_n(D.startedAt,s)} 前${ce?"收到":"派发"}`,inbound:ce,tone:U,chips:[...D.settleable===!0?["可结算"]:[],...D.receiptExpected===!1?["无回执债"]:[],...ce?["入站"]:[],...D.status!=="pending"?[D.status]:[]]}},S=(D,U,ce)=>({brief:D.brief,team:D.team,sender:Tn(D),taskId:D.taskId,atText:`${_n(D.deadAt,s)} 前${ce}`,inbound:$t(D),tone:U,dead:D,chips:D.reason!==void 0&&D.reason!==""&&D.reason!=="unspecified"&&D.reason!=="fire-forget"?[D.reason]:[]}),E=M("死信",c.deadLetters.length,"danger","需清账");if(E!==null)for(const D of[...c.deadLetters].sort((U,ce)=>ce.deadAt-U.deadAt))V(E,S(D,"danger","死信"));const G=M("陈旧",x.length,"warn","我方派发 ≥1 小时仍无回执,可催办");if(G!==null)for(const D of[...x].sort((U,ce)=>U.startedAt-ce.startedAt))V(G,C(D,"warn"));const y=c.owedOverdue.length,f=M("待本机回执",b.length,y>0?"warn":"quiet",y>0?`对方在等本机回执 · ${y} 条超过 1 小时`:"对方在等本机回执");if(f!==null)for(const D of[...b].sort((U,ce)=>U.startedAt-ce.startedAt))V(f,C(D,Dt(D,s)?"warn":"quiet"));const _=M("等待回执",N.length,"quiet","1 小时内");if(_!==null)for(const D of[...N].sort((U,ce)=>ce.startedAt-U.startedAt))V(_,C(D,"quiet"));const p=M("免回执",l.length,"muted","不等回执,24h 后自动归档");if(p!==null)for(const D of l)V(p,C(D,"muted"));const R=M("已过期(免回执)",c.expired.length,"muted","正常记账,不是失败");if(R!==null)for(const D of[...c.expired].sort((U,ce)=>ce.deadAt-U.deadAt))V(R,S(D,"muted","过期"));n.length+i.length===0&&(e.appendChild(ke("div","wb-led-empty")).textContent="台账为空——没有待回执的任务");const j=o.idempotency,K=(Me=o.reconcile)==null?void 0:Me.state;if(j!==void 0||K!==void 0){const D=ke("details","wb-led-forensics wb-forensics");D.appendChild(ke("summary")).textContent="取证";const U=ke("div","wb-led-forensics-body");j!==void 0&&(U.appendChild(ke("div")).textContent=`幂等 claims ${j.claimsFresh??0} · replays ${j.replays??0} · conflicts ${j.conflicts??0}`),K!==void 0&&(U.appendChild(ke("div")).textContent=`reconcile ${K}`),D.appendChild(U),e.appendChild(D)}const we=u.length+c.deadLetters.length;return{badge:we>0?String(we):"",tone:c.deadLetters.length>0?"danger":Y>0||y>0?"warn":void 0}}const Tt=4e3,Ho=32;function ye(e,t){const o=document.createElement(e);return t!==void 0&&(o.className=t),o}function Bt(e,t,o=""){const s=ye("button",`wb-icon-btn wb-chat-act ${o}`.trim());return s.type="button",s.setAttribute("aria-label",e),s.title=e,s.textContent=t,s}function dn(e,t){const o=Math.max(0,Math.round((t-e)/1e3));if(o<60)return"刚刚";const s=Math.round(o/60);if(s<60)return`${s} 分钟前`;const n=Math.round(s/60);return n<48?`${n} 小时前`:`${Math.round(n/24)} 天前`}function jo(e){return e>=1e6?`${(e/1e6).toFixed(1)} MB`:e>=1e3?`${Math.round(e/1e3)} KB`:`${e} B`}function mn(e){const t=e.kind==="session"||e.kind==="remote"?e.team:void 0;return t!==void 0&&t!==""?t:void 0}function On(e){return e.kind==="remote"?`remote:${e.team}`:`${e.kind}:${e.id}`}function Bo(e){let t=null,o=null,s=!1,n=!1;const i=new Map,r=new Map,c=new Map,l=new Map,u=new Set,b=new Map,m=new Map,x=ye("aside","wb-chat");x.setAttribute("aria-label","对话");const N=ye("div","wb-chat-head"),Y=Bt("返回会话列表","‹","wb-chat-back"),re=ye("span","wb-chat-dot"),V=ye("div","wb-chat-titles"),M=ye("span","wb-chat-title"),C=ye("span","wb-chat-sub");V.append(M,C);const S=Bt("刷新对话","↻","wb-chat-refresh"),E=Bt("会话详情","ⓘ","wb-chat-info-btn");E.setAttribute("aria-expanded","false");const G=Bt("关闭对话","✕","wb-chat-close");N.append(Y,re,V,S,E,G);const y=ye("div","wb-chat-info");y.hidden=!0;const f=ye("div","wb-chat-thread");f.setAttribute("role","log"),f.setAttribute("aria-live","polite"),f.tabIndex=0;const _=ye("div","wb-chat-notice"),p=ye("div","wb-chat-log"),R=ye("div","wb-chat-sent");f.append(_,p,R);const j=ye("div","wb-chat-foot");x.append(N,y,f,j),Y.addEventListener("click",()=>{(t==null?void 0:t.kind)==="peer"&&(t.picked=void 0,Ie())}),S.addEventListener("click",()=>{if(t===null)return;const d=K(t);d!==void 0&&i.delete(d),t.kind==="peer"&&t.picked===void 0&&t.url!==void 0&&c.delete(`peer:${t.url}`),de(!0)}),E.addEventListener("click",()=>{n=!n,y.hidden=!n,E.setAttribute("aria-expanded",String(n))}),G.addEventListener("click",()=>ft()),f.addEventListener("scroll",()=>{const d=t!==null?K(t):void 0;d!==void 0&&r.set(d,f.scrollTop)}),document.addEventListener("keydown",d=>{if(d.key!=="Escape"||!x.classList.contains("is-open"))return;const A=d.target;if(A instanceof HTMLElement){if(!x.contains(A)){const I=A instanceof HTMLTextAreaElement||A instanceof HTMLInputElement||A.isContentEditable,Q=A.closest(".wb-stage-board")!==null;if(I||Q)return}ft()}});function K(d){if(d.kind==="session"||d.kind==="log")return e.sessionLog!==void 0?`local:${d.id}`:void 0;if(d.kind==="remote")return e.remoteSessionLog!==void 0?`remote:${d.team}`:void 0;if(d.picked!==void 0&&d.url!==void 0&&e.remoteSessionLog!==void 0)return`peer:${d.url}:${d.picked}`}function we(d){var A,I,Q;return d.kind==="session"||d.kind==="log"?((A=e.sessionLog)==null?void 0:A.call(e,d.id))??Promise.resolve({ok:!1,error:"sessionLog unavailable"}):d.kind==="remote"?((I=e.remoteSessionLog)==null?void 0:I.call(e,{team:d.team}))??Promise.resolve({ok:!1,error:"remoteSessionLog unavailable"}):((Q=e.remoteSessionLog)==null?void 0:Q.call(e,{peer:d.url,id:d.picked}))??Promise.resolve({ok:!1,error:"remoteSessionLog unavailable"})}function Me(){const d=t;if(d===null)return;const A=d.kind==="log"||d.kind==="remote"||d.kind==="session"&&d.live===!1;re.className=`wb-chat-dot ${d.kind==="peer"?"is-peer":A?"is-cold":"is-live"}`,re.title=d.kind==="peer"?"对端主机":d.kind==="log"?"只读日志":d.kind==="remote"?"远端会话":d.live===!1?"冷会话":"在线",M.textContent=d.kind==="peer"&&d.picked!==void 0?`…${d.picked.slice(-12)}`:d.title,C.textContent=d.kind==="peer"&&d.picked!==void 0?d.title:d.sub,Y.hidden=!(d.kind==="peer"&&d.picked!==void 0)}function D(d,A){const I=ye("div","wb-kv");I.appendChild(ye("span","wb-kv-k")).textContent=d,I.appendChild(ye("span","wb-kv-v")).textContent=A,y.appendChild(I)}function U(){var A,I,Q;y.replaceChildren();const d=t;d!==null&&(d.kind==="session"?(D("会话",d.id),d.team!==void 0&&D("路由",d.team),D("来源","本机会话日志")):d.kind==="log"?(D("会话",d.id),D("来源","本机会话日志(不在网络目录)")):d.kind==="remote"?(D("路由",d.team),((A=d.row)==null?void 0:A.origin)!==void 0&&D("来源",d.row.origin),((I=d.row)==null?void 0:I.via)!==void 0&&D("经",d.row.via),((Q=d.row)==null?void 0:Q.workspace)!==void 0&&D("工作区",d.row.workspace)):(D("对端",d.url??d.sub),d.picked!==void 0&&D("会话",d.picked),D("来源","经本机代理读取对端 /a2a/log")))}function ce(d){return d.kind==="log"?"只读日志 —— 此会话当前不在网络目录(可能已归档或未入网)。":d.kind==="remote"?e.remoteSessionLog!==void 0?"远端会话 —— 经本机代理从对端 /a2a/log 读取最近对话。":"远端节点的对话记录在对端机器上;本页的代理读取面未启用。":d.kind==="peer"?d.url===void 0||e.remoteSessionLog===void 0?`对端主机节点(${d.sub})—— 会话记录存放在对端机器上,本页只读本机会话日志。`:d.picked===void 0?"对端主机 —— 选择一个会话阅读(经本机代理读取对端 /a2a/log)。":"":e.sessionLog===void 0?"本页未接入会话日志读取,只显示从这里发出的消息。":""}function Re(){return f.scrollHeight-f.scrollTop-f.clientHeight<=Ho}function Ee(d){const A=()=>{f.scrollTop=f.scrollHeight};A(),requestAnimationFrame(A)}function le(d,A){const I=ye("div",`wb-chat-empty${A==="error"?" is-error":""}`);return I.textContent=d,I}function He(d,A){const I=d==="user",Q=ye("div",`wb-msg ${I?"wb-msg-user":"wb-msg-assistant"}`),X=ye("span","wb-msg-who");X.textContent=I?"问":"答";const me=ye("div","wb-msg-text");return me.textContent=A,Q.append(X,me),Q}function fe(d){if(p.replaceChildren(),d===void 0){p.appendChild(le("读取中…"));return}if(d.ok!==!0||d.messages===void 0){p.appendChild(le(`无法读取(${d.error??"未知错误"})`,"error"));return}if(d.messages.length===0){p.appendChild(le("暂无对话记录"));return}for(const A of d.messages)p.appendChild(He(A.role,A.text))}function q(d,A){if(p.replaceChildren(),A===void 0){p.appendChild(le("读取中…"));return}if(A.ok!==!0||A.sessions===void 0){p.appendChild(le(`无法读取(${A.error??"未知错误"})`,"error"));return}if(A.sessions.length===0){p.appendChild(le("对端没有可读会话"));return}const I=ye("div","wb-chat-sessions"),Q=e.now();for(const X of A.sessions){const me=ye("button","wb-chat-session");me.type="button",me.appendChild(ye("span","wb-chat-session-id")).textContent=`…${X.id.slice(-12)}`;const ge=[X.mtimeMs!==void 0?dn(X.mtimeMs,Q):"",jo(X.sizeBytes)].filter(Boolean).join(" · ");me.appendChild(ye("span","wb-chat-session-meta")).textContent=ge,me.title=X.id,me.addEventListener("click",()=>{(t==null?void 0:t.kind)!=="peer"||t.url!==d||(t.picked=X.id,Ie())}),I.appendChild(me)}p.appendChild(I)}function de(d=!1){const A=t;if(A===null)return;if(_.textContent=ce(A),_.hidden=_.textContent==="",A.kind==="peer"&&A.picked===void 0){if(A.url===void 0||e.remoteSessionLog===void 0){p.replaceChildren();return}const X=A.url,me=`peer:${X}`;if(!d&&c.has(me)){q(X,c.get(me));return}c.set(me,void 0),q(X,void 0),e.remoteSessionLog({peer:X}).then(ge=>{c.set(me,ge),(t==null?void 0:t.kind)==="peer"&&t.url===X&&t.picked===void 0&&q(X,ge)},ge=>{const ve={ok:!1,error:ge instanceof Error?ge.message:String(ge)};c.set(me,ve),(t==null?void 0:t.kind)==="peer"&&t.url===X&&t.picked===void 0&&q(X,ve)});return}const I=K(A);if(I===void 0){p.replaceChildren(),Je(!0);return}const Q=()=>{const X=r.get(I);X===void 0||d?Ee():(f.scrollTop=X,requestAnimationFrame(()=>{t!==null&&K(t)===I&&(f.scrollTop=X)}))};if(!d&&i.has(I)&&i.get(I)!==void 0){fe(i.get(I)),Je(!0),Q();return}d&&r.delete(I),i.set(I,void 0),fe(void 0),Je(!0),we(A).then(X=>{var me;i.set(I,X),(X==null?void 0:X.ok)===!0&&X.messages!==void 0&&((me=e.onTranscript)==null||me.call(e,A,X.messages)),!(t===null||K(t)!==I)&&(fe(X),Je(),Q())},X=>{const me={ok:!1,error:X instanceof Error?X.message:String(X)};i.set(I,me),t!==null&&K(t)===I&&fe(me)})}function ee(d){return((o==null?void 0:o.tasks)??[]).filter(A=>A.team===d)}function te(d){return((o==null?void 0:o.tasksDead)??[]).filter(A=>A.team===d)}let Ce="";function Be(d){return d.reason==="fire-forget"?{text:"已过期(免回执)",tone:"muted",hint:"免回执消息到 24h TTL 归档,属正常记账"}:{text:"死信",tone:"danger",hint:d.reason!==void 0&&d.reason!=="unspecified"?`${d.reason}:超过 24h TTL 仍未结算,需在台账清账`:"超过 24h TTL 仍未结算,需在台账清账"}}function Ye(d,A){const I=d.direction==="inbound";if(d.receiptExpected===!1)return{text:I?"来信 · 无需回执":"已送达 · 无回执",tone:"muted",hint:"免回执消息:不等回执,24h 后自动归档"};const Q=Dt(d,A),X=I?Q?"待本机回执 · 超 1 小时":"待本机回执":Q?"陈旧":"待回执",me=d.status!=="pending"?` · ${d.status}`:"";return{text:`${X}${me}`,tone:Q?"warn":"wait",hint:`${I?"对方等待本机回执;":""}${I?"收到":"派发"}于 ${dn(d.startedAt,A)}`}}function qe(d,A){const I=`结算于 ${dn(d.resolvedAt,A)}`;if(d.receiptExpected===!1&&d.endedBy==="abandoned")return d.late===!0?{text:"已移出(免回执) · 回执迟到",tone:"warn",hint:`${I};免回执消息本机移出后对方回执才到,结局不改写`}:{text:"已移出(免回执)",tone:"muted",hint:`${I};免回执消息,本机移出台账,不是失败`};if(d.endedBy==="abandoned"||d.endedBy==="cancelled"){const ge=d.endedBy==="cancelled"?"撤回":"放弃";return d.late===!0?{text:`已${ge} · 回执迟到`,tone:"warn",hint:`${I};本机${ge}之后对方回执才到,结局不改写`}:{text:`已${ge}`,tone:"muted",hint:`${I};本机${ge},未等到回执`}}if(d.endedBy==="echo")return{text:"已结算 · 内容回显",tone:"ok",hint:`${I};对方回了内容但未带正式回执,按内容回显结算`};if(d.endedBy===void 0&&d.outcome==="abandoned")return{text:"已放弃(本机或对方)",tone:"muted",hint:`${I};本机放弃或撤回,或对方回执报告放弃`};const Q=d.summary!==void 0&&d.summary!==""?` · ${d.summary}`:"";if(d.outcome==="abandoned")return{text:"已回执 · 对方放弃",tone:"warn",hint:`${I};对方回执报告放弃${Q}`};const X=bn.find(ge=>ge.key===d.outcome),me=(X==null?void 0:X.tone)==="completed"?"ok":(X==null?void 0:X.tone)==="failed"?"danger":(X==null?void 0:X.tone)==="rejected"?"warn":"muted";return d.outcome==="unclassified"?{text:"已回执",tone:"ok",hint:`${I};回执未带结论${Q}`}:{text:`已回执 · ${(X==null?void 0:X.label)??d.outcome}`,tone:me,hint:`${I}${Q}`}}function ut(d,A,I){const Q=te(A).find(ge=>ge.taskId===d);if(Q!==void 0)return Be(Q);const X=ee(A).find(ge=>ge.taskId===d);if(X!==void 0)return Ye(X,I);const me=((o==null?void 0:o.archived)??[]).find(ge=>ge.taskId===d&&ge.team===A);return me!==void 0?qe(me,I):u.has(d)?{text:"已离开台账",tone:"muted",hint:"已结算、放弃或撤回之一;主机未给出这条的结局(旧主机,或已超出最近 64 条归档)"}:{text:"已派发",tone:"muted",hint:"异步送达;回执到达后进台账"}}function kt(d){const A=e.now(),I=l.get(d)??[],Q=new Set(I.map(ne=>ne.taskId).filter(ne=>ne!==void 0)),X=ne=>ne!==void 0&&ne!==""?ne:"(无摘要)",me=ee(d).filter(ne=>!Q.has(ne.taskId)).map(ne=>({at:ne.startedAt,side:ne.direction==="inbound"?"theirs":"mine",text:X(ne.brief),status:Ye(ne,A),taskId:ne.taskId})),ge=te(d).filter(ne=>!Q.has(ne.taskId)).map(ne=>{var Te;const We=ne.direction??b.get(ne.taskId)??(((Te=ne.peer)==null?void 0:Te.startsWith("local:"))===!0?"inbound":void 0);return{at:ne.startedAt,side:We==="inbound"?"theirs":We==="outbound"?"mine":"system",text:X(ne.brief),status:Be(ne),taskId:ne.taskId}}),ve=I.map(ne=>({at:ne.at,side:"mine",text:ne.text,status:ne.state==="sending"?{text:"发送中…",tone:"muted"}:ne.state==="failed"?{text:`失败:${ne.error??"未知原因"}`,tone:"danger"}:ne.taskId!==void 0?ut(ne.taskId,d,A):{text:"已派发",tone:"muted"},taskId:ne.taskId}));return[...me,...ge,...ve].sort((ne,We)=>ne.at-We.at)}function Je(d=!1){const A=t,I=A!==null?mn(A):void 0,Q=I!==void 0?kt(I):[],X=JSON.stringify([I??"",...Q.map(ve=>[ve.taskId??"",ve.side,ve.text,ve.status.text])]);if(!d&&X===Ce)return;Ce=X;const me=Re();if(R.replaceChildren(),Q.length===0)return;const ge=ye("div","wb-chat-divider");ge.textContent="台账往来 · 异步送达,回执进台账",R.appendChild(ge);for(const ve of Q){const ne=ve.side==="mine"?"wb-msg wb-msg-user wb-msg-out":ve.side==="theirs"?"wb-msg wb-msg-assistant wb-msg-in":"wb-msg wb-msg-ledger",We=ye("div",ne);We.appendChild(ye("span","wb-msg-who")).textContent=ve.side==="mine"?"我":ve.side==="theirs"?"对方":"台账记录",We.appendChild(ye("div","wb-msg-text")).textContent=ve.text;const Te=ye("div","wb-msg-meta");ve.taskId!==void 0&&(Te.appendChild(ye("span","wb-msg-task")).textContent=ve.taskId);const Xe=ye("span",`wb-msg-status is-${ve.status.tone}`);Xe.textContent=ve.status.text,ve.status.hint!==void 0&&(Xe.title=ve.status.hint),Te.appendChild(Xe),We.appendChild(Te),R.appendChild(We)}me&&Ee()}function Qe(d){const A=d.text.value.length;d.note.classList.remove("is-error"),d.note.textContent=A>Tt*.9?`${A}/${Tt}`:"Enter 发送 · Shift+Enter 换行",A>Tt&&d.note.classList.add("is-error"),d.submit.disabled=d.text.value.trim()===""||A>Tt}function vt(d){d.style.height="auto",d.style.height=`${Math.min(d.scrollHeight,160)}px`}function St(d){const A=ye("form","wb-dispatch-form wb-chat-composer"),I=document.createElement("textarea");I.className="wb-dispatch-text",I.rows=1,I.placeholder="发一句话任务给这个节点…",I.setAttribute("aria-label","发送消息");const Q=ye("button","wb-dispatch-submit");Q.type="submit",Q.textContent="发送",Q.setAttribute("aria-label","发送");const X=ye("div","wb-dispatch-note");X.setAttribute("aria-live","polite");const me=ye("div","wb-chat-composer-row");me.append(I,Q),A.append(me,X);const ge={team:d,form:A,text:I,note:X,submit:Q};return I.addEventListener("input",()=>{vt(I),Qe(ge)}),I.addEventListener("keydown",ve=>{ve.key!=="Enter"||ve.shiftKey||ve.ctrlKey||ve.altKey||ve.metaKey||ve.isComposing||(ve.preventDefault(),A.requestSubmit())}),A.addEventListener("submit",ve=>{ve.preventDefault();const ne=I.value.trim();if(ne===""||ne.length>Tt||e.dispatchQuick===void 0)return;const We={text:ne,at:e.now(),state:"sending"},Te=l.get(d)??[];Te.push(We),l.set(d,Te),I.value="",vt(I),Qe(ge),I.focus({preventScroll:!0}),Je(),Ee(),e.dispatchQuick(d,ne).then(Xe=>Xe,Xe=>({ok:!1,error:Xe instanceof Error?Xe.message:String(Xe)})).then(Xe=>{Xe.ok===!0?(We.state="sent",We.taskId=Xe.task_id,X.classList.remove("is-error"),X.textContent=`已派发${Xe.task_id!==void 0?` · ${Xe.task_id}`:""} · 回执将入台账`):(We.state="failed",We.error=Xe.error??"未知原因",I.value===""&&(I.value=ne,vt(I)),X.classList.add("is-error"),X.textContent=`失败:${We.error}`,Q.disabled=I.value.trim()===""),t!==null&&mn(t)===d&&Je()})}),Qe(ge),ge}function Se(){const d=t;if(j.replaceChildren(),d===null)return;const A=mn(d);if(A!==void 0&&e.dispatchQuick!==void 0){let Q=m.get(A);Q===void 0&&(Q=St(A),m.set(A,Q)),j.appendChild(Q.form),s&&(s=!1,Q.text.focus({preventScroll:!0}));return}s=!1;const I=ye("div","wb-chat-readonly");I.textContent=d.kind==="log"?"只读日志:此会话不在网络目录,不能从这里派发。":d.kind==="peer"?"对端主机:选择会话阅读;要派发请打开它的远端会话节点。":"此节点没有可派发的路由。",j.appendChild(I)}function Ie(){Me(),U(),de(),Se()}function tt(d){const A=t!==null&&On(t)===On(d);t=d,A||(s=!0),Ie(),x.classList.add("is-open")}function ft(){t=null,x.classList.remove("is-open")}function At(d){o=d;for(const I of(d==null?void 0:d.tasks)??[])u.add(I.taskId),b.set(I.taskId,I.direction==="inbound"?"inbound":"outbound");const A=t;if(A!==null){if(A.kind==="session"&&d!==null){const I=(d.sessions??[]).find(Q=>Q.id===A.id);I!==void 0&&(A.title=lt(I),A.live=I.live)}Me(),Je()}}return{root:x,open:tt,close:ft,isOpen:()=>t!==null,update:At}}function Yo(e,t,o){const s=document.createElement("section"),n=document.createElement("h4");n.textContent="会话席位名(仅人工设定)",s.appendChild(n);const i=document.createElement("p");i.className="wb-hint",i.textContent="稳定展示名,不改变会话标题、路由句柄或准入。留空并保存可清除。",s.appendChild(i);const r=document.createElement("select");r.setAttribute("aria-label","选择命名的本机会话");for(const N of new Set([...e.map(Y=>Y.id),...Object.keys(t)])){const Y=e.find(V=>V.id===N),re=document.createElement("option");re.value=N,re.textContent=(t[N]??(Y==null?void 0:Y.name)??(Y==null?void 0:Y.label)??N)+" · "+N,r.appendChild(re)}const c=document.createElement("input");c.type="text",c.maxLength=64,c.setAttribute("aria-label","人工席位名"),c.placeholder="例如:开发席";const l=document.createElement("button");l.type="submit",l.textContent="保存席位名",l.className="wb-member-submit";const u=document.createElement("form");u.className="wb-member-add",u.append(r,c,l);const b=document.createElement("p");b.className="wb-hint",b.setAttribute("role","status"),b.setAttribute("aria-live","polite");let m=!1;const x=()=>{c.value=t[r.value]??"",l.disabled=m||r.value===""};return r.addEventListener("change",x),x(),u.addEventListener("submit",async N=>{if(N.preventDefault(),m||r.value==="")return;const Y=r.value,re=c.value.trim(),V={...t};re===""?delete V[Y]:V[Y]=re,m=!0,l.disabled=!0,r.disabled=!0,c.disabled=!0;try{const M=await o(V);M.ok?(delete t[Y],re!==""&&(t[Y]=re),b.textContent="席位名已保存;目录将随状态刷新。"):b.textContent=M.error??"保存失败"}catch(M){b.textContent="保存失败:"+String(M)}finally{m=!1,r.disabled=!1,c.disabled=!1,x()}}),s.append(u,b),s}function Wo(e,t){const o=document.createElement("form");o.className="wb-cli-home";const s=document.createElement("button");s.type="button",s.textContent="指定 home",s.className="wb-member-submit";const n=document.createElement("select");n.className="wb-member-pick",n.setAttribute("aria-label","选择 CLI home 主机"),n.hidden=!0;const i=document.createElement("button");i.type="submit",i.textContent="确认 home",i.className="wb-member-submit",i.hidden=!0,i.disabled=!0;const r=document.createElement("div");r.className="wb-hint",r.setAttribute("role","status"),r.setAttribute("aria-live","polite"),r.textContent="home 未确定;点击指定 home 现读已链接主机名片。";let c=!1;return s.addEventListener("click",async()=>{var l;if(!c){c=!0,s.disabled=!0,i.disabled=!0,r.textContent="正在现读主机名片…";try{const u=await e();if(!u.ok)throw Error(u.error??"候选读取失败");if(u.held){s.hidden=!0,n.hidden=!0,i.hidden=!0,n.replaceChildren(),r.textContent="本机持有,无需指定";return}n.replaceChildren(new Option("请选择 home 主机…","",!0,!0));for(const m of u.homes??[])n.appendChild(new Option(m,m));n.hidden=!1,i.hidden=!1,s.textContent="刷新候选";const b=((l=u.homes)==null?void 0:l.length)??0;r.textContent=(u.unreadable?"有 "+u.unreadable+" 台对端名片读不到;":"")+(b>1?"多台已链接主机列出该句柄,请显式选择。":b===1?"找到 1 台已链接主机;仍需你显式确认。":"当前没有已链接且列出该句柄的可选主机。")}catch(u){r.textContent="读取失败:"+String(u),n.hidden=!0,i.hidden=!0}finally{c=!1,s.disabled=!1}}}),n.addEventListener("change",()=>{i.disabled=c||n.value===""}),o.addEventListener("submit",async l=>{if(l.preventDefault(),!(c||n.value==="")){c=!0,s.disabled=!0,n.disabled=!0,i.disabled=!0;try{r.textContent=await t(n.value)?"home 已指定:"+n.value:"指定失败:主机可能已离线或不再列出该句柄,请刷新后重选。"}catch(u){r.textContent="指定失败:"+String(u)}finally{c=!1,s.disabled=!1,n.disabled=!1,i.disabled=n.value===""}}}),o.append(s,n,i,r),o}const co="dsh-a2a.rail.tab";function Xo(){try{return window.localStorage.getItem(co)}catch{return null}}function Ko(e){try{window.localStorage.setItem(co,e)}catch{}}function Uo(e,t={}){var V;const o=document.createElement("aside");o.className="wb-rail";const s=document.createElement("div");s.className="wb-tabs",s.setAttribute("role","tablist"),s.setAttribute("aria-label","工作台侧栏");const n=document.createElement("div");n.className="wb-tabpanels",o.append(s,n);const i=new Map,r=new Map,c=new Map,l=new Set;for(const M of e){const C=document.createElement("button");C.type="button",C.className="wb-tab",C.id=`wb-tab-${M.key}`,C.dataset.sec=M.key,C.setAttribute("role","tab"),C.setAttribute("aria-controls",`wb-panel-${M.key}`);const S=document.createElement("span");S.className="wb-tab-label",S.textContent=M.label;const E=document.createElement("span");E.className="wb-tab-badge",C.append(S,E),C.addEventListener("click",()=>N(M.key)),s.appendChild(C);const G=document.createElement("section");G.className="wb-tabpanel",G.id=`wb-panel-${M.key}`,G.dataset.sec=M.key,G.setAttribute("role","tabpanel"),G.setAttribute("aria-labelledby",C.id),G.tabIndex=-1,n.appendChild(G),i.set(M.key,C),r.set(M.key,G),c.set(M.key,E)}const u=()=>e.map(M=>M.key).filter(M=>!l.has(M)),b=Xo();let m=((V=e.find(M=>M.key===b))==null?void 0:V.key)??e[0].key;s.addEventListener("keydown",M=>{const C=u(),S=C.indexOf(m);let E;M.key==="ArrowRight"?E=C[(S+1)%C.length]:M.key==="ArrowLeft"?E=C[(S-1+C.length)%C.length]:M.key==="Home"?E=C[0]:M.key==="End"&&(E=C[C.length-1]),E!==void 0&&(M.preventDefault(),N(E,{focus:!0}))});function x(){for(const M of e){const C=M.key===m,S=i.get(M.key);S.setAttribute("aria-selected",String(C)),S.tabIndex=C?0:-1,S.classList.toggle("is-active",C),S.hidden=l.has(M.key),r.get(M.key).hidden=!C}}function N(M,C={}){var E;if(l.has(M))return;const S=M!==m;m=M,Ko(M),x(),C.focus===!0&&i.get(M).focus(),S&&((E=t.onChange)==null||E.call(t,M))}function Y(M,C,S){const E=c.get(M);E.textContent=C,E.className=`wb-tab-badge${S!==void 0?` is-${S}`:""}`}function re(M,C){C?l.add(M):l.delete(M),l.has(m)&&(m=u()[0]??e[0].key),x()}return x(),{root:o,panel:M=>r.get(M),select:N,selected:()=>m,setBadge:Y,setHidden:re}}const gn="application/x-dsh-session";function qo(e,t){e.draggable=!0,e.classList.add("is-draggable"),e.title=`${e.title===""?t:e.title} · 可拖入画布队`,e.addEventListener("dragstart",o=>{o.dataTransfer!==null&&(o.dataTransfer.setData(gn,t),o.dataTransfer.effectAllowed="copy")})}function zo(e,t){const o=n=>n.dataTransfer!==null&&[...n.dataTransfer.types].includes(gn),s=n=>{for(const[i,r]of t.frames())r.classList.toggle("drop-target",i===n)};e.addEventListener("dragover",n=>{if(!o(n))return;const i=t.frameAt(n.clientX,n.clientY);s(i),i!==void 0&&(n.preventDefault(),n.dataTransfer.dropEffect="copy")},t.signal),e.addEventListener("dragleave",n=>{o(n)&&(n.relatedTarget===null||!e.contains(n.relatedTarget))&&s(void 0)},t.signal),e.ownerDocument.addEventListener("dragend",()=>s(void 0),t.signal),e.addEventListener("drop",n=>{if(!o(n))return;s(void 0);const i=t.frameAt(n.clientX,n.clientY),r=n.dataTransfer.getData(gn);i===void 0||r===""||(n.preventDefault(),t.drop(i,r))},t.signal)}const Jo=[{key:"all",label:"全部",hint:"不过滤:目录全部条目"},{key:"local",label:"本机",hint:"本机会话节点(现场 + 冷启动)"},{key:"canvas",label:"队",hint:"画布队(人类手工分配的组队)"},{key:"remote",label:"远端",hint:"远端会话队(来自对端卡片)"},{key:"logs",label:"日志",hint:"本机日志:不在网络目录里的会话档案"}];function ot(e,t){const o=document.createElement(e);return t!==void 0&&(o.className=t),o}function Yt(...e){const t=[];for(const o of e)o!==void 0&&(typeof o=="string"?t.push(o):t.push(...o));return t.join(" ").toLowerCase()}function Vo(e,t){const o=Math.max(0,Math.round((t-e)/1e3));if(o<60)return"刚刚";const s=Math.round(o/60);if(s<60)return`${s} 分钟前`;const n=Math.round(s/60);return n<48?`${n} 小时前`:`${Math.round(n/24)} 天前`}function Fn(e){return e>=1e6?`${(e/1e6).toFixed(1)} MB`:e>=1e3?`${Math.round(e/1e3)} KB`:`${e} B`}function Go(e,t){const o=new Date(t);o.setHours(0,0,0,0);const s=o.getTime();return e>=s?"今天":e>=s-864e5?"昨天":"更早"}function Qo(e,t){var S,E,G;e.replaceChildren();const{state:o,search:s,filter:n}=t,i=s!==""||n!=="all",r=(y,f)=>(n==="all"||n===y)&&(s===""||f.includes(s)),c=(y,f,_)=>{const p=ot("div","wb-dir-group"),R=ot("div","wb-dir-head");return R.appendChild(ot("span","wb-dir-head-label")).textContent=`${y} · ${f}`,_!==void 0&&(R.appendChild(ot("span","wb-dir-head-note")).textContent=_),p.appendChild(R),e.appendChild(p),p},l=(y,f,_,p,R,j,K)=>{const we=ot("button","wb-item");we.type="button",we.appendChild(ot("span",`wb-dot ${f}`)).textContent=_;const Me=ot("span","wb-item-text");return Me.appendChild(ot("span","wb-item-label")).textContent=p,R!==""&&(Me.appendChild(ot("span","wb-item-sub")).textContent=R),we.appendChild(Me),K!==void 0&&(we.title=K),we.addEventListener("click",j),y.appendChild(we),we},u=(y,f)=>{if(f===void 0||f.length===0)return;const _=ot("span","wb-item-badge"),p=f.map(R=>R.slice(R.lastIndexOf("/")+1));_.textContent=`▤ ${p.slice(0,2).join(" ")}${p.length>2?` +${p.length-2}`:""}`,_.title=`画布队:${f.join(" · ")}`,y.appendChild(_)},b=(o.sessions??[]).filter(y=>r("local",Yt(lt(y),y.team,y.label,y.id,y.canvasTeams))),m=b.filter(y=>y.live===!0),x=b.filter(y=>y.live!==!0);if(b.length>0){const y=c("本机会话",b.length,x.length>0?`${m.length} 在线 · ${x.length} 冷`:void 0);for(const f of[...m,...x]){const _=f.live===!0,p=f.nodePromptMissing===!0,R=l(y,_?"wb-dot-live":"wb-dot-cold",_?"●":"○",lt(f),_?f.team:`冷 · ${f.team}`,()=>t.openChat({kind:"session",id:f.id,title:lt(f),sub:f.team,team:f.team,live:f.live}),f.id);if(p){R.classList.add("is-node-prompt-missing");const j=ot("span","wb-node-warning");j.textContent="本会话的组装不含节点段",(S=R.querySelector(".wb-item-text"))==null||S.appendChild(j)}u(R,f.canvasTeams),qo(R,f.id)}}const N=(((E=o.canvas)==null?void 0:E.teams)??[]).filter(y=>r("canvas",Yt(y.name,y.team,y.members.map(f=>f.team??f.id))));if(N.length>0){const y=c("画布队",N.length);for(const f of N){const _=f.members.filter(p=>p.remote===!0).length;l(y,"wb-dot-canvas","▤",f.name,`${f.members.length} 成员${_>0?` · ${_} 远端`:""}`,()=>t.selectCanvas(f),f.team)}}const Y=(o.remote??[]).filter(y=>r("remote",Yt(lt(y),y.team,y.origin,y.workspace,y.canvasTeams)));if(Y.length>0){const y=c("远端节点",Y.length);for(const f of Y){const _=l(y,"wb-dot-remote","◇",lt(f),f.origin!==void 0&&f.origin!==""?f.origin:f.team,()=>t.openChat({kind:"remote",team:f.team,title:lt(f),sub:f.team,row:f}),f.team);if(f.unreachable===!0){_.classList.add("is-unreachable");const p=ot("span","wb-unreachable-note");p.textContent="对端未应答(显示的是最后已知状态)",(G=_.querySelector(".wb-item-text"))==null||G.appendChild(p)}u(_,f.canvasTeams)}}const re=new Set((o.sessions??[]).map(y=>y.id)),V=t.logs.filter(y=>!re.has(y.id)&&r("logs",Yt(y.id,t.titles.get(y.id))));if(V.length>0){const y=t.logTotal!==void 0&&t.logTotal>t.logs.length,f=c("本机日志",V.length,y?`显示 ${t.logs.length} / 共 ${t.logTotal}`:void 0);let _="";for(const p of[...V].sort((R,j)=>j.mtimeMs-R.mtimeMs)){const R=Go(p.mtimeMs,t.now);R!==_&&(_=R,f.appendChild(ot("div","wb-dir-day")).textContent=R);const j=t.titles.get(p.id),K=l(f,"wb-dot-log","❐",j??`会话 …${p.id.slice(-12)}`,`${Vo(p.mtimeMs,t.now)} · ${Fn(p.sizeBytes)}`,()=>t.openChat({kind:"log",id:p.id,title:j??`…${p.id.slice(-12)}`,sub:"本机日志"}),`${p.id}
3
- ${new Date(p.mtimeMs).toLocaleString()} · ${Fn(p.sizeBytes)}`);j===void 0&&K.classList.add("is-untitled")}}b.length+N.length+Y.length+V.length===0&&(e.appendChild(ot("div","wb-dir-empty")).textContent=i?"无匹配条目":"目录为空");const M=o.sessions??[];return`${M.filter(y=>y.live===!0).length}/${M.length}`}const lo="dsh-a2a.logtitles",Zo=300,Pn=60;function es(){try{const e=window.localStorage.getItem(lo),t=e===null?null:JSON.parse(e);if(t!==null&&typeof t=="object")return new Map(Object.entries(t).filter(o=>typeof o[1]=="string"))}catch{}return new Map}function ts(e,t,o){const s=o.find(r=>r.role==="user"&&r.text.trim()!=="")??o.find(r=>r.text.trim()!=="");if(s===void 0)return!1;const n=s.text.trim().split(`
4
- `)[0].trim(),i=n.length>Pn?`${n.slice(0,Pn-1)}…`:n;if(e.get(t)===i)return!1;for(e.delete(t),e.set(t,i);e.size>Zo;)e.delete(e.keys().next().value);try{window.localStorage.setItem(lo,JSON.stringify(Object.fromEntries(e)))}catch{}return!0}function ht(e){return e.name??e.team??e.label??""}function _t(e,t){const o=Math.max(0,Math.round((t-e)/1e3));if(o<90)return`${o}s`;const s=Math.round(o/60);if(s<90)return`${s}m`;const n=Math.round(s/60);return n<48?`${n}h`:`${Math.round(n/24)}d`}function T(e,t){const o=document.createElement(e);return t!==void 0&&(o.className=t),o}function Dn(e,t,o){const s=T("div","wb-kv");s.appendChild(T("span","wb-kv-k")).textContent=t,s.appendChild(T("span","wb-kv-v")).textContent=o,e.appendChild(s)}function ns(e){try{return new URL(e).host}catch{return e}}const os=[{key:"directory",label:"目录"},{key:"hosts",label:"主机"},{key:"ledger",label:"台账"},{key:"activity",label:"活动"},{key:"plan",label:"规划"}];function ss(e){const t=e.board;let o="data",s,n=null,i="",r="all",c=null;const l=new Map;let u=null,b=[],m;const x=es();let N=!1;const Y=T("div","wb");Y.setAttribute("data-testid","wb-root");const re=T("header","wb-header"),V=T("button","wb-icon-btn wb-menu");V.type="button",V.dataset.testid="wb-menu",V.setAttribute("aria-label","打开目录抽屉"),V.textContent="☰",V.addEventListener("click",()=>Y.classList.toggle("is-rail-open")),re.appendChild(V);const M=T("div","wb-title");M.appendChild(T("span","wb-title-main")).textContent="A2A 工作台";const C=T("span","wb-badge");M.appendChild(C),re.appendChild(M);const S=T("button","wb-icon-btn wb-owner-btn");S.type="button",S.dataset.testid="wb-owner-btn",S.setAttribute("aria-label","主人设置"),S.title="主人设置:席位名 / 入网白名单 / 可见性 / 发布",S.textContent="⚙",S.addEventListener("click",()=>{A=!A,Q()}),re.appendChild(S);const E=T("div","wb-header-stats");re.appendChild(E);const G=T("button","wb-icon-btn wb-rail-toggle");G.type="button",G.dataset.testid="wb-rail-toggle",G.setAttribute("aria-label","折叠/展开侧栏"),G.textContent="◧",G.addEventListener("click",()=>{Y.classList.toggle("is-rail-collapsed"),o==="canvas"&&t!==void 0&&t.activate()}),re.appendChild(G);const y=T("div","wb-body"),f=Uo(os),_=f.root,p=T("div","wb-directory"),R=T("div","wb-dir-tools"),j=document.createElement("input");j.className="wb-search",j.type="search",j.placeholder="搜索:名称 / 队 / 会话 / 节点",j.setAttribute("aria-label","统一搜索目录"),j.addEventListener("input",()=>{i=j.value.trim().toLowerCase(),qe()}),R.appendChild(j);const K=T("div","wb-filters");for(const k of Jo){const w=T("button","wb-filter");w.type="button",w.textContent=k.label,w.dataset.filter=k.key,w.title=k.hint,w.addEventListener("click",()=>{r=k.key,qe()}),K.appendChild(w)}R.appendChild(K),f.panel("directory").appendChild(R),f.panel("directory").appendChild(p);const we=T("section","wb-pane"),Me=T("section","wb-pane"),D=T("section","wb-pane"),U=T("section","wb-pane"),ce=[["ledger",we],["activity",Me],["plan",D],["hosts",U]],Re=T("main","wb-stage"),Ee=T("section","wb-stage-board");t!==void 0&&(Ee.appendChild(t.root),Re.appendChild(Ee));const le=T("div","wb-data"),He=T("aside","wb-inspector"),fe=T("div","wb-inspector-head");fe.appendChild(T("span","wb-inspector-title")).textContent="详情";const q=T("button","wb-icon-btn");q.type="button",q.setAttribute("aria-label","关闭详情"),q.textContent="✕",q.addEventListener("click",()=>Ye(void 0)),fe.appendChild(q),He.appendChild(fe);const de=T("div","wb-inspector-body");He.appendChild(de);const ee=Bo({now:e.now,sessionLog:e.sessionLog,remoteSessionLog:e.remoteSessionLog,dispatchQuick:e.dispatchQuick,onTranscript:(k,w)=>{k.kind!=="log"&&k.kind!=="session"||ts(x,k.id,w)&&qe()}});Re.appendChild(le),y.appendChild(_),y.appendChild(Re),y.appendChild(He),y.appendChild(ee.root),Y.appendChild(re),Y.appendChild(y);function te(k){for(const[w,H]of ce){const $=k==="canvas"?f.panel(w):le;f.setHidden(w,k!=="canvas"),H.parentElement!==$&&$.appendChild(H)}}function Ce(){const w=t!==void 0&&t.available()?"canvas":"data";Y.dataset.mode=w,Ee.classList.toggle("is-hidden",w!=="canvas"),le.classList.toggle("is-hidden",w==="canvas"),te(w),w!==o&&(t!==void 0&&(w==="canvas"?t.activate():t.deactivate()),o=w)}function Be(k){for(;k.firstChild!==null;)k.removeChild(k.firstChild);return k}function Ye(k){s=k,((k==null?void 0:k.kind)!=="canvas"||(c==null?void 0:c.name)!==k.row.name)&&(c=null),(k==null?void 0:k.kind)!=="canvas"&&(u=null),me(),Y.classList.remove("is-rail-open")}function qe(){for(let w=0;w<K.children.length;w++){const H=K.children[w];H.classList.toggle("is-active",H.dataset.filter===r)}if(n===null){p.replaceChildren(T("div","wb-muted")),p.firstElementChild.textContent="载入中…",f.setBadge("directory","");return}const k=Qo(p,{state:n,logs:b,logTotal:m,titles:x,search:i,filter:r,now:e.now(),openChat:ne,selectCanvas:w=>Ye({kind:"canvas",row:w})});f.setBadge("directory",k)}function ut(){const k=Be(U);if(n===null){f.setBadge("hosts","");return}const w=e.now(),H=[...n.peers??[]].sort(($,L)=>{const O=se=>se.link==="linked"?0:1;return O($)-O(L)||(L.score??0)-($.score??0)});if(f.setBadge("hosts",H.length>0?`${H.filter($=>$.link==="linked").length}/${H.length}`:""),H.length===0){k.appendChild(T("div","wb-nodelist-empty")).textContent="暂无 tracked peer——配 peers 种子或等 referral 到达";return}for(const $ of H){const L=ns($.url),O=T("div","wb-host-row"),se=T("span","wb-host-lamp"),ae=$.lastContactAt,Z=ae===void 0?void 0:w-ae,xe=$.lastContactOk;Z===void 0?se.classList.add("is-unknown"):xe===!1&&Z<=5*6e4?se.classList.add("is-fail"):Z<=6e4?se.classList.add("is-live"):Z<=5*6e4?se.classList.add("is-warm"):se.classList.add("is-cold"),se.title=ae===void 0?"尚无接触记录":`最近接触 ${_t(ae,w)}${xe===!1?"(失败)":xe===!0?"(成功)":""}`,O.appendChild(se),O.appendChild(T("span","wb-host-name")).textContent=$.name!==void 0&&$.name!==""?$.name:L;const _e=T("span",`wb-host-badge ${$.link==="linked"?"is-linked":"is-stranger"}`);_e.textContent=`${$.link==="linked"?"linked":"stranger"} ${$.verified===!0?"✓":"✗"}`,_e.title=$.link==="linked"?`已建立运营者链接(互种或 canvas 引用);${$.verified===!0?"验签有效":"尚未持有验签通过的卡片"}`:"无运营者关系(验签 ≠ 关系)",O.appendChild(_e),$.version!==void 0&&$.version!==""&&(O.appendChild(T("span","wb-host-ver")).textContent=$.version),O.appendChild(T("span","wb-host-url mono")).textContent=L,O.setAttribute("role","button"),O.tabIndex=0,O.title=`${$.url} · score ${String($.score??0)}`;const J=()=>{ne({kind:"peer",id:`peer-${L}`,title:$.name!==void 0&&$.name!==""?$.name:L,sub:L,url:$.url})};O.addEventListener("click",J),O.addEventListener("keydown",Pe=>{(Pe.key==="Enter"||Pe.key===" ")&&(Pe.preventDefault(),J())}),k.appendChild(O)}}function kt(){if(n===null){we.replaceChildren(),f.setBadge("ledger","");return}const k=n,w=$=>{const L=(k.sessions??[]).find(se=>se.team===$);if(L!==void 0)return{kind:"session",id:L.id,title:ht(L),sub:L.team,team:L.team,live:L.live};const O=(k.remote??[]).find(se=>se.team===$);if(O!==void 0)return{kind:"remote",team:O.team,title:ht(O),sub:O.team,row:O}},H=Ro(we,{state:k,now:e.now(),abandon:($,L)=>e.abandon($,L),canOpenTeam:$=>w($)!==void 0,openTeam:$=>{const L=w($);return L===void 0?!1:(ne(L),!0)}});f.setBadge("ledger",H.badge,H.tone)}function Je(k,w,H){zt(k.appendChild(T("span","wb-row-team")),w,H)}function Qe(){var se;const k=Be(Me);if(n===null)return;const w=e.now(),H=n.inFlight??[];f.setBadge("activity",H.length>0?String(H.length):"",H.length>0?"accent":void 0);const $=T("div","wb-pane-head");if($.textContent=`在途 ${H.length} · 活动 ${((se=n.activity)==null?void 0:se.length)??0}`,k.appendChild($),H.length>0){const ae=T("div","wb-pane-subhead");ae.textContent="在途路由",k.appendChild(ae);for(const Z of H){const xe=T("div","wb-row");xe.appendChild(T("span","wb-row-dir")).textContent="→",Je(xe,n,Z.team),xe.appendChild(T("span","wb-row-meta")).textContent=`${Z.peer} · ${_t(Z.startedAt,w)}`,k.appendChild(xe)}}const L=T("div","wb-pane-subhead");L.textContent="活动环(最新在前)",k.appendChild(L);const O=n.activity??[];if(O.length===0){k.appendChild(T("div","wb-muted")).textContent="暂无活动";return}for(const ae of O){const Z=T("div","wb-row"),xe=T("span","wb-row-dir");xe.textContent=ae.dir==="fwd"?"⇢":ae.dir==="out"?"→":"←",ae.ok!==!0&&xe.classList.add("is-fail"),Z.appendChild(xe),Je(Z,n,ae.team),Z.appendChild(T("span","wb-row-meta")).textContent=`${ae.peer} · ${_t(ae.ts,w)}`,Z.appendChild(T("span","wb-row-badges")).textContent=ae.ok===!0?"":"失败",k.appendChild(Z)}}function vt(k){var se,ae;const w=e.now(),H=[],$=hn(k,w);$.deadLetters.length>0&&H.push({severity:"high",text:`清账 ${$.deadLetters.length} 条死信(目标早已离开或死信化,无回执可期)`});for(const Z of $.stale){const xe=Z.brief===void 0||Z.brief===""?"":`「${Z.brief}」`;H.push({severity:"normal",text:`催办 ${Z.taskId} → ${Fo(k,Z.team)}(等待 ${_t(Z.startedAt,w)} 无回执)${xe}`,brief:`a2a_route 催收回执:task ${Z.taskId}(team ${Z.team})${xe===""?"":`原任务「${Z.brief}」`}已派发 ${_t(Z.startedAt,w)},请回报结果或回执。`})}const L=(k.sessions??[]).filter(Z=>Z.live!==!0).map(Z=>ht(Z));if(L.length>0){const Z=L.slice(0,3).join("、")+(L.length>3?` 等 ${L.length} 个`:"");H.push({severity:"normal",text:`冷会话 ${L.length} 个(${Z}):在 GUI 打开即可唤醒加入面`})}for(const Z of((se=k.reconcile)==null?void 0:se.rows)??[])if(Z.needsRepair===!0){const xe=(k.sessions??[]).find(J=>J.id===Z.id),_e=xe!==void 0?`${ht(xe)}(${Z.id})`:Z.id;H.push({severity:"high",text:`reconcile 需修复:${_e} ${Z.error}`})}const O=((ae=k.idempotency)==null?void 0:ae.conflicts)??0;return O>0&&H.push({severity:"high",text:`幂等冲突 ${O} 例:人工核查 UNIQUE-ization 流量`}),H}function St(){const k=Be(D);if(n===null)return;const w=vt(n);f.setBadge("plan",w.length>0?String(w.length):"",w.some(L=>L.severity==="high")?"danger":void 0);const H=T("div","wb-pane-head");H.textContent=w.length===0?"网络健康——无待办行动":`待办行动 ${w.length}`,k.appendChild(H);for(const L of w){const O=T("div",`wb-action${L.severity==="high"?" wb-action-high":""}`);if(O.appendChild(T("span","wb-action-text")).textContent=L.text,L.brief!==void 0){const se=T("button","wb-btn");se.type="button",se.textContent="复制催办",se.addEventListener("click",()=>e.copy(L.brief??"")),O.appendChild(se)}k.appendChild(O)}const $=T("div","wb-pane-subhead");$.textContent="派单起草(复制后在任一会话粘贴执行)",k.appendChild($),k.appendChild(Se)}const Se=T("div","wb-draft"),Ie=document.createElement("select");Ie.className="wb-select";const tt=document.createElement("textarea");tt.className="wb-textarea",tt.rows=3,tt.placeholder="任务正文:目标、验收、期限…";const ft=T("button","wb-btn wb-btn-primary");ft.type="button",ft.textContent="复制任务书",ft.addEventListener("click",()=>{const k=Ie.value,w=tt.value.trim();k===""||w===""||e.copy(`a2a_route 派单 → ${k}:
5
- ${w}`)}),Se.appendChild(Ie),Se.appendChild(tt),Se.appendChild(ft);function At(){var L;const k=Ie.value;Be(Ie);const w=document.createElement("option");if(w.value="",w.textContent="选择目标队…",Ie.appendChild(w),n===null)return;const H=n,$=new Map;for(const O of H.sessions??[])O.team!==void 0&&O.team!==""&&$.set(O.team,`${ht(O)}(会话队)`);for(const O of((L=H.canvas)==null?void 0:L.teams)??[])$.set(O.team,`${O.name}(canvas 队)`);for(const O of H.remote??[])$.set(O.team,`${ht(O)}(远端)`);for(const[O,se]of $){const ae=document.createElement("option");ae.value=O,ae.textContent=`${se} · ${O}`,Ie.appendChild(ae)}k!==""&&$.has(k)&&(Ie.value=k)}let d,A=!1,I=null;function Q(){var k;me(),A&&((k=e.ownerSettingsRead)==null||k.call(e).then(w=>{if(A){if(w.ok!==!0){I=null,me();return}d=void 0,I={seatNames:w.seatNames??{},teamJoinAllowlist:w.teamJoinAllowlist??[],teamScopeInfo:w.teamScopeInfo!==!1,announce:w.announce===!0,announceRestartPending:w.announceRestartPending===!0},me()}}))}function X(k){const w=T("div","wb-card"),H=T("div","wb-inspector-head");H.appendChild(T("span","wb-inspector-title")).textContent="主人设置";const $=T("button","wb-icon-btn");if($.type="button",$.setAttribute("aria-label","关闭主人设置"),$.textContent="✕",$.addEventListener("click",()=>{A=!1,me()}),H.appendChild($),w.appendChild(H),e.ownerSettingsRead===void 0){const pe=T("div","wb-hint");pe.textContent="此宿主未提供主人设置面(旧版本)——升级后可用。",w.appendChild(pe),k.appendChild(w);return}if(I===null){const pe=T("div","wb-hint");pe.textContent="读取中…",w.appendChild(pe),k.appendChild(w);return}const L=I;d??(d=Yo((n==null?void 0:n.sessions)??[],L.seatNames,async pe=>{var it;const Oe=await((it=e.ownerSettingsWrite)==null?void 0:it.call(e,{seatNames:pe}));return Oe!=null&&Oe.ok?(L.seatNames=pe,{ok:!0}):{ok:!1,error:(Oe==null?void 0:Oe.error)??"保存失败"}})),w.appendChild(d);const O=T("div","wb-side-head");O.textContent="入网白名单(精确团队名)",w.appendChild(O);for(const pe of L.teamJoinAllowlist){const Oe=T("div","wb-member-row");Oe.appendChild(T("span","wb-member-label")).textContent=pe;const it=T("button","wb-member-remove");it.type="button",it.textContent="移除",it.addEventListener("click",()=>{var It;(It=e.ownerSettingsWrite)==null||It.call(e,{teamJoinAllowlist:L.teamJoinAllowlist.filter(cn=>cn!==pe)}).then(()=>Q())}),Oe.appendChild(it),w.appendChild(Oe)}const se=T("div","wb-member-add"),ae=T("input","wb-member-manual");ae.type="text",ae.placeholder="dsh/团队名(精确,无通配)",ae.setAttribute("aria-label","新增白名单团队名");const Z=T("button","wb-member-submit");Z.type="button",Z.textContent="加入";const xe=()=>{var Oe;const pe=ae.value.trim();pe===""||L.teamJoinAllowlist.includes(pe)||(Oe=e.ownerSettingsWrite)==null||Oe.call(e,{teamJoinAllowlist:[...L.teamJoinAllowlist,pe]}).then(()=>Q())};Z.addEventListener("click",xe),ae.addEventListener("keydown",pe=>{pe.key==="Enter"&&xe()}),se.append(ae,Z),w.appendChild(se);const _e=T("div","wb-side-head");_e.textContent="目录可见性(teamScopeInfo)",w.appendChild(_e);const J=T("div","wb-member-row"),Pe=T("button","wb-member-submit");Pe.type="button",Pe.textContent=L.teamScopeInfo?"已开:仅显示已加入团队(点击放开为全舰队可见)":"已关:全舰队可见(点击收窄为已加入团队)",Pe.addEventListener("click",()=>{var pe;(pe=e.ownerSettingsWrite)==null||pe.call(e,{teamScopeInfo:!L.teamScopeInfo}).then(()=>Q())}),J.appendChild(Pe),w.appendChild(J);const Ze=T("div","wb-hint");Ze.textContent="精度说明:teamScopeInfo 只管「目录显示范围」。关上它不会解锁任何通信准入——会话入网(S3)与目标级路由(F5)规则原样生效。",w.appendChild(Ze);const et=T("div","wb-side-head");et.textContent="节点发布(announce)",w.appendChild(et);const pt=T("div","wb-member-row"),Ve=T("button","wb-member-submit");if(Ve.type="button",Ve.textContent=L.announce?"已开:本节点发布签名卡(点击关闭)":"已关:本节点不发布(点击开启——重启宿主后生效)",Ve.addEventListener("click",()=>{var pe;(pe=e.ownerSettingsWrite)==null||pe.call(e,{announce:!L.announce}).then(()=>Q())}),pt.appendChild(Ve),w.appendChild(pt),L.announceRestartPending){const pe=T("div","wb-hint");pe.textContent="有 announce 变更待生效:重启宿主后按新配置发布。",w.appendChild(pe)}k.appendChild(w)}function me(){var $;const k=Be(de);if(A){He.classList.add("is-open"),X(k);return}if(He.classList.toggle("is-open",s!==void 0),s===void 0)return;const w=s,H=T("div","wb-card");if(w.kind==="canvas"){const L=((($=n==null?void 0:n.canvas)==null?void 0:$.teams)??[]).find(J=>J.name===w.row.name)??w.row;Dn(H,"Canvas 队",L.name),Dn(H,"路由队",L.team);const O=T("div","wb-side-head");if(O.textContent=`成员 · ${L.members.length}`,H.appendChild(O),L.members.length===0){const J=T("div","wb-muted");J.textContent="空队——用下方表单添加成员",H.appendChild(J)}for(const J of L.members){const Pe=T("div","wb-member-row"),Ze=J.cliHeld===!0?"本机持有,无需指定":J.remote===!0?J.cliHome===null?"◇ 远端 · home 未确定":"◇ 远端":J.live===!0?"● 现场":J.joined===!0?"○ 冷启":"· 未入网";Pe.appendChild(T("span","wb-member-dot")).textContent=Ze;const et=T("span","wb-member-label"),pt=((n==null?void 0:n.sessions)??[]).find(pe=>pe.id===J.id);et.textContent=J.remote===!0?J.id:pt!==void 0?ht(pt):J.id,et.title=J.cliHeld===!0?"本机持有,无需指定":J.cliHome!==void 0?J.cliHome??"home 未确定":J.team??J.id,Pe.appendChild(et);const Ve=T("button","wb-member-remove");if(Ve.type="button",Ve.textContent="移除",Ve.addEventListener("click",async()=>{Ve.disabled=!0,await e.canvasOp("remove-member",L.name,J.id)||(Ve.disabled=!1)}),Pe.appendChild(Ve),H.appendChild(Pe),J.cliHomeCleared===!0){const pe=T("div","wb-hint");pe.textContent="本机落户已清除旧 home 钉;户口离线后也不会恢复旧钉。",H.appendChild(pe)}if(J.cliHome===null&&J.cliHeld!==!0&&e.cliHomeOptions!==void 0){const pe=JSON.stringify([L.name,J.id]);let Oe=l.get(pe);Oe===void 0&&(Oe=Wo(()=>e.cliHomeOptions(L.name,J.id),it=>e.canvasOp("add-member",L.name,J.id,it)),l.set(pe,Oe)),H.appendChild(Oe)}}if((c==null?void 0:c.name)!==L.name){const J=T("form","wb-member-add"),Pe=document.createElement("select");Pe.className="wb-member-pick",Pe.setAttribute("aria-label","选择成员");const Ze=document.createElement("input");Ze.type="text",Ze.className="wb-member-manual",Ze.placeholder="或输入远端句柄 zone/id8",Ze.setAttribute("aria-label","远端成员句柄");const et=T("button","wb-member-submit");et.type="submit",et.textContent="添加",J.appendChild(Pe),J.appendChild(Ze),J.appendChild(et),J.addEventListener("submit",async pt=>{pt.preventDefault();const Ve=Ze.value.trim(),pe=Ve!==""?Ve:Pe.value;if(pe==="")return;et.disabled=!0;const Oe=await e.canvasOp("add-member",L.name,pe);et.disabled=!1,Oe&&(Ze.value="")}),c={name:L.name,form:J,pick:Pe,manual:Ze}}const se=c.pick,ae=se.value;Be(se),se.appendChild(new Option("本机会话(现场/冷启动)…","",!0,!0));const Z=new Set(L.members.map(J=>J.id));for(const J of(n==null?void 0:n.sessions)??[])Z.has(J.id)||se.appendChild(new Option(`${ht(J)} — 本机`,J.id));let xe=!1;for(const J of(n==null?void 0:n.remote)??[])J.team.includes("/")&&(Z.has(J.team)||(xe||(se.appendChild(new Option("远端会话队(目录卡片)…","",!0,!1)),xe=!0),se.appendChild(new Option(`${ht(J)} — 远端`,J.team))));xe||se.appendChild(new Option("(暂无可拉入的远端会话队——见下方说明)","",!0,!1)),ae!==""&&Array.from(se.options).some(J=>J.value===ae)&&(se.value=ae),H.appendChild(c.form);const _e=T("div","wb-hint");_e.textContent="成员由人类在此手工分配(agent 不可自组队)。远端成员走对端目录路由,不做本机冷唤醒;地址由目录在派发时重解析。远端下拉只列 zone/id8 会话句柄——若为空,说明目录里还没有已链接对端的会话队(未链接的对端只给最小卡);此时可在输入框手输句柄(如 dsh/xxxxxxxx)先把人拉进来,句柄本身即链接手势。",H.appendChild(_e),e.dispatchQuick!==void 0&&H.appendChild(ve(L.team))}k.appendChild(H)}function ge(k){const w=T("form","wb-dispatch-form"),H=document.createElement("textarea");H.className="wb-dispatch-text",H.placeholder="一句话任务…(≤4000 字符,异步送达,回执进台账)",H.setAttribute("aria-label","快派消息");const $=T("button","wb-dispatch-submit");$.type="submit",$.textContent="发送";const L=T("div","wb-dispatch-note");return w.appendChild(H),w.appendChild($),w.appendChild(L),H.addEventListener("keydown",O=>{O.key!=="Enter"||O.shiftKey||O.ctrlKey||O.altKey||O.metaKey||O.isComposing||(O.preventDefault(),$.disabled||w.requestSubmit())}),w.addEventListener("submit",async O=>{var Z;O.preventDefault();const se=H.value.trim();if(se===""||$.disabled)return;$.disabled=!0,L.textContent="派发中…";let ae;try{ae=await(((Z=e.dispatchQuick)==null?void 0:Z.call(e,k,se))??Promise.resolve({ok:!1,error:"dispatch unavailable"}))}catch(xe){ae={ok:!1,error:xe instanceof Error?xe.message:String(xe)}}$.disabled=!1,ae.ok===!0&&(H.value=""),H.focus({preventScroll:!0}),L.textContent=ae.ok===!0?`已派发${ae.task_id!==void 0?` · ${ae.task_id}`:""} · 回执将入台账(待回执)`:`失败:${ae.error??"未知原因"}`}),{form:w,text:H,note:L}}function ve(k){const w=T("div","wb-dispatch"),H=T("div","wb-side-head");return H.textContent="快派",w.appendChild(H),(u==null?void 0:u.team)!==k&&(u={team:k,...ge(k)}),w.appendChild(u.form),w}function ne(k){ee.open(k),Y.classList.remove("is-rail-open")}function We(k){if(n===null)return;const w=(n.sessions??[]).find($=>$.id===k);if(w!==void 0){ne({kind:"session",id:k,title:ht(w),sub:w.team,team:w.team,live:w.live});return}if(k.startsWith("peer-")){const $=k.slice(5),L=(n.peers??[]).find(O=>O.url.includes($));ne({kind:"peer",id:k,title:L!==void 0?L.url:$,sub:$,url:L==null?void 0:L.url});return}b.find($=>$.id===k)!==void 0&&ne({kind:"log",id:k,title:`…${k.slice(-12)}`,sub:"档案"})}function Te(){var Z,xe;C.textContent=(n==null?void 0:n.version)!==void 0?`v${n.version}`:"",C.hidden=(n==null?void 0:n.version)===void 0;const k=Be(E);if(n===null)return;const w=[],H=hn(n,e.now()),$=H.deadLetters.length;$>0&&w.push({text:`死信 ${$}`,tone:"danger",title:"超过 24h TTL 仍未结算的任务(unconsumed),需在台账清账",tab:"ledger",group:"死信"});const L=H.stale.length;L>0&&w.push({text:`陈旧 ${L}`,tone:"warn",title:"我方派发、要回执、已等待 ≥1h 仍未回执(可催办;免回执行不算)",tab:"ledger",group:"陈旧"});const O=H.owedOverdue.length;O>0&&w.push({text:`欠回执 ${O}`,tone:"warn",title:"对方投递给本机、已等待本机回执超过 1 小时",tab:"ledger",group:"待本机回执"});const se=((Z=n.idempotency)==null?void 0:Z.conflicts)??0;se>0&&w.push({text:`幂等冲突 ${se}`,tone:"danger",title:"同一幂等键对应了不同载荷,需人工核查",tab:"ledger",group:"取证"});const ae=(((xe=n.reconcile)==null?void 0:xe.rows)??[]).filter(_e=>_e.needsRepair===!0).length;if(ae>0&&w.push({text:`需修复 ${ae}`,tone:"danger",title:"reconcile 无法自动恢复的会话,见行动计划",tab:"plan"}),w.length===0){k.appendChild(T("span","wb-header-ok")).textContent="● 无异常";return}for(const _e of w){const J=T("button",`wb-alert wb-alert-${_e.tone}`);J.type="button",J.textContent=_e.text,J.title=`${_e.title}(点击查看)`,J.addEventListener("click",()=>Xe(_e.tab,_e.group)),k.appendChild(J)}}function Xe(k,w){var L;const H=ce.find(([O])=>O===k)[1];o==="canvas"&&(Y.classList.add("is-rail-open"),f.select(k,{focus:!1}));const $=w===void 0?H:w==="取证"?H.querySelector("details.wb-led-forensics"):Array.from(H.querySelectorAll(".wb-led-group")).find(O=>O.dataset.group===w)??null;$!==null&&($ instanceof HTMLDetailsElement&&($.open=!0),(L=$.scrollIntoView)==null||L.call($,{block:"start",behavior:"smooth"}))}function Lt(k){var H;const w=new Set((((H=k==null?void 0:k.canvas)==null?void 0:H.teams)??[]).flatMap($=>$.members.filter(L=>L.cliHome===null&&L.cliHeld!==!0).map(L=>JSON.stringify([$.name,L.id]))));for(const $ of l.keys())w.has($)||l.delete($);n=k,e.sessionLogList!==void 0&&!N&&(N=!0,e.sessionLogList().then($=>{b=$.ok&&$.sessions!==void 0?$.sessions:[],m=$.ok?$.count:void 0}).catch(()=>{}).finally(()=>{N=!1,qe()})),Te(),qe(),At(),ut(),kt(),ee.update(k),Qe(),St(),me(),Ce()}function nt(k){if(k==="board"){Ce();return}f.select(k)}return Lt(null),{root:Y,update:Lt,mode:()=>o,selectTab:nt,openNodeChat:We}}const bt=1e6,Cn=.25,kn=3,mo=256,uo=96;function Mt(e){const t=typeof e=="number"?e:Number.NaN;if(Number.isFinite(t))return Math.max(-bt,Math.min(bt,Math.round(t)))}function fo(e){if(e===null||typeof e!="object")return;const t=e,o=Mt(t.x),s=Mt(t.y);return o===void 0||s===void 0?void 0:{x:o,y:s}}function is(e){const t=fo(e);if(t===void 0)return;const o=e,s=Mt(o.w),n=Mt(o.h);if(!(s===void 0||n===void 0||s<=0||n<=0))return{...t,w:Math.min(s,bt),h:Math.min(n,bt)}}const po=e=>e!==""&&!e.includes("/")&&(e.startsWith("roster:")?e.length>7&&e.length<=47:e.length<=40);function ho(e){if(e===null||typeof e!="object")return;const t=e;if(t.version!==1)return;const o=t.viewport;if(o===null||typeof o!="object")return;const s=o,n=Mt(s.x),i=Mt(s.y),r=s.scale,c=typeof r=="number"?r:Number.NaN;if(n===void 0||i===void 0||!Number.isFinite(c))return;const l=Math.max(Cn,Math.min(kn,c)),u={};if(t.nodes!==null&&typeof t.nodes=="object")for(const[m,x]of Object.entries(t.nodes)){if(typeof m!="string"||m===""||m.length>128)continue;const N=fo(x);if(N!==void 0&&(u[m]=N),Object.keys(u).length>=mo)break}const b={};if(t.frames!==null&&typeof t.frames=="object")for(const[m,x]of Object.entries(t.frames)){if(!po(m))continue;const N=is(x);if(N!==void 0&&(b[m]=N),Object.keys(b).length>=uo)break}return{version:1,viewport:{x:n,y:i,scale:l},nodes:u,frames:b}}function rs(e,t,o){const s=r=>Math.max(-bt,Math.min(bt,Math.round(r))),n={};for(const[r,c]of t)if(!(typeof r!="string"||r===""||r.length>128)&&(n[r]={x:s(c.x),y:s(c.y)},Object.keys(n).length>=mo))break;const i={};for(const[r,c]of o){if(!po(r))continue;const l=s(c.w),u=s(c.h);if(!(l<=0||u<=0)&&(i[r]={x:s(c.x),y:s(c.y),w:Math.min(l,bt),h:Math.min(u,bt)},Object.keys(i).length>=uo))break}return{version:1,viewport:{x:s(e.x),y:s(e.y),scale:Math.max(Cn,Math.min(kn,e.scale))},nodes:n,frames:i}}function bo(e){let t=2166136261;for(let o=0;o<e.length;o++)t^=e.charCodeAt(o),t=Math.imul(t,16777619)>>>0;return t>>>0}const Ue=172,De=56,xt=[150,290,430],at=16;function as(e){const t=bo(e),o=Math.floor(t/at)%xt.length,n=t%at/at*Math.PI*2+o*(Math.PI/at),i=xt[o];return{x:Math.round(Math.cos(n)*i),y:Math.round(Math.sin(n)*i*.6)}}function go(e){const t=new Map;for(const o of e)for(const s of o.members)t.has(s.id)||t.set(s.id,o.name);return t}const Rn=64,Hn=24,jn=20,cs=4,Bn=24,Yn=44,ls=24;function ds(e,t,o=Number.POSITIVE_INFINITY){const s=new Set(t),n=go(e),i=e.map(m=>[...new Set(m.members.map(x=>x.id))].filter(x=>s.has(x)&&n.get(x)===m.name));i.push(t.filter(m=>!n.has(m)));const r=new Map;let c=0,l=0,u=0,b=0;for(const m of i){if(m.length===0)continue;const x=Math.min(3,Math.max(m.length>1?2:1,Math.ceil(Math.sqrt(m.length)))),N=Math.ceil(m.length/x),Y=Math.max(260,x*Ue+(x-1)*Hn+Bn*2),re=Math.max(160,N*De+(N-1)*jn+Yn+ls);b>0&&(b%cs===0||c+Y>o)&&(c=0,l+=u+Rn,u=0),m.forEach((V,M)=>{const C=M%x,S=Math.floor(M/x);r.set(V,{x:c+Bn+Ue/2+C*(Ue+Hn),y:l+Yn+De/2+S*(De+jn)})}),c+=Y+Rn,u=Math.max(u,re),b+=1}return r}const Wt=12;function vo(e,t){const o=l=>t.every(u=>Math.abs(u.x-l.x)>=Ue+Wt||Math.abs(u.y-l.y)>=De+Wt),s=as(e);if(o(s))return s;const n=bo(e),i=at*xt.length,r=Math.floor(n/at)%xt.length*at+n%at;for(let l=1;l<i;l++){const u=(r+l)%i,b=Math.floor(u/at),m=u%at/at*Math.PI*2+b*(Math.PI/at),x=xt[b],N={x:Math.round(Math.cos(m)*x),y:Math.round(Math.sin(m)*x*.6)};if(o(N))return N}const c=xt[xt.length-1];for(let l=0;;l++)for(let u=0;u<6;u++){const b={x:Math.round(-c+u*(Ue+Wt)),y:Math.round(c*.6+De*2+l*(De+Wt))};if(o(b))return b}}function mt(e){return{x:e.x-Ue/2,y:e.y-De/2,w:Ue,h:De}}function En(e){if(e.length===0)return{x:0,y:0,w:260,h:160};let t=Number.POSITIVE_INFINITY,o=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY,n=Number.NEGATIVE_INFINITY;for(const b of e)t=Math.min(t,b.x),o=Math.min(o,b.y),s=Math.max(s,b.x+b.w),n=Math.max(n,b.y+b.h);const i=24,r=44,c=24,l=Math.max(260,Math.round(s-t+i*2)),u=Math.max(160,Math.round(n-o+r+c));return{x:Math.round(t-i),y:Math.round(o-r),w:l,h:u}}class Nn{constructor(){Et(this,"revisionCounter",0);Et(this,"nodes",new Map);Et(this,"frames",new Map);Et(this,"selection",new Set);Et(this,"viewport",{x:0,y:0,scale:1})}get revision(){return this.revisionCounter}getNode(t){return this.nodes.get(t)}allNodes(){return[...this.nodes.values()]}nodeIds(){return[...this.nodes.keys()]}getFrame(t){return this.frames.get(t)}allFrames(){return[...this.frames.entries()]}isSelected(t){return this.selection.has(t)}selectedIds(){return[...this.selection]}bump(){this.revisionCounter+=1}dragNodes(t,o,s){let n=!1;for(const i of t){const r=this.nodes.get(i);r!==void 0&&(r.x+=o,r.y+=s,n=!0)}n&&this.bump()}beginFrameDrag(t){const o=this.frames.get(t);if(o!==void 0)return{name:t,rect:{...o}}}applyFrameDrag(t,o,s){const n=this.frames.get(t.name);n!==void 0&&(n.x=t.rect.x+o,n.y=t.rect.y+s,this.bump())}nudge(t,o,s){this.dragNodes(t,o,s)}marqueeSelect(t,o){o||this.selection.clear();for(const s of this.nodes.values()){const n=mt(s);n.x<t.x+t.w&&n.x+n.w>t.x&&n.y<t.y+t.h&&n.y+n.h>t.y&&this.selection.add(s.id)}this.bump()}setSelection(t){this.selection=new Set(t),this.bump()}upsertNode(t){const o=this.nodes.get(t.id);if(o===void 0){this.nodes.set(t.id,t),this.bump();return}o.label=t.label,o.name=t.name,o.description=t.description,o.live=t.live,o.memberships=t.memberships,this.bump()}removeNode(t){this.nodes.delete(t)&&(this.selection.delete(t),this.bump())}setFrame(t,o){this.frames.set(t,o),this.bump()}removeFrame(t){this.frames.delete(t)&&this.bump()}upsertScore(t,o){const s=this.nodes.get(t);s===void 0||s.score===o||(s.score=o,this.bump())}positions(){const t=new Map;for(const[o,s]of this.nodes)t.set(o,{x:s.x,y:s.y});return t}frameRects(){const t=new Map;for(const[o,s]of this.frames)t.set(o,{...s});return t}teamMemberIds(t){const o=[];for(const s of this.nodes.values()){const n=s.memberships.find(i=>i.team===t);n!==void 0&&o.push({id:s.id,index:n.index})}return o.sort((s,n)=>s.index-n.index).map(s=>s.id)}setTeamMembers(t,o){for(const s of this.nodes.values()){const n=s.memberships.filter(r=>r.team!==t),i=o.indexOf(s.id);i>=0&&n.push({team:t,index:i}),s.memberships=n}this.bump()}contentBounds(){let t=Number.POSITIVE_INFINITY,o=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY,n=Number.NEGATIVE_INFINITY;const i=r=>{t=Math.min(t,r.x),o=Math.min(o,r.y),s=Math.max(s,r.x+r.w),n=Math.max(n,r.y+r.h)};for(const r of this.nodes.values())r.remote!==!0&&i(mt(r));for(const r of this.frames.values())i(r);return t===Number.POSITIVE_INFINITY?null:{minX:t,minY:o,maxX:s,maxY:n}}static fromState(t){const o=new Nn,s=ho(t.layout),n=new Map;for(const i of t.teams)for(let r=0;r<i.members.length;r++){const c=i.members[r].id,l=n.get(c)??[];l.push({team:i.name,index:r}),n.set(c,l)}for(const i of t.sessions){if(i.joined!==!0)continue;const r=s==null?void 0:s.nodes[i.id];let c,l;if(r!==void 0&&typeof r.x=="number"&&typeof r.y=="number")c=r.x,l=r.y;else{const u=vo(i.id,[...o.nodes.values()]);c=u.x,l=u.y}o.nodes.set(i.id,{id:i.id,x:c,y:l,label:i.label,team:i.team,name:i.name,description:i.description,live:i.live!==!1,memberships:n.get(i.id)??[]})}for(const i of t.teams){const r=s==null?void 0:s.frames[i.name];if(r!==void 0){o.frames.set(i.name,{x:r.x,y:r.y,w:r.w,h:r.h});continue}const c=[];for(const l of i.members){const u=o.nodes.get(l.id);u!==void 0&&c.push(mt(u))}c.length>0&&o.frames.set(i.name,En(c))}return o.viewport=s!==void 0?{...s.viewport}:{x:0,y:0,scale:1},o}}const ms=24,yo=-13,us=yo+ms;function fs(e,t,o){const s=[],n=new Set;for(const i of e){const r=t.get(i.name);if(r===void 0)continue;const c=r.x+r.w/2,l=r.y+us;for(const u of i.members){const b=o.get(u.id);if(b===void 0)continue;const m=n.has(u.id);n.add(u.id),s.push({x1:c,y1:l,x2:b.x,y2:b.y-De/2,dashed:m,team:i.name,id:u.id})}}return s}function ps(e,t){for(;e.firstChild!==null;)e.firstChild.remove();const o=t.allFrames().map(([s])=>({name:s,members:t.teamMemberIds(s).map(n=>({id:n}))}));for(const s of fs(o,new Map(t.allFrames()),t.positions())){const n=document.createElementNS("http://www.w3.org/2000/svg","line");n.setAttribute("class","e-member"+(s.dashed?" dashed":"")),n.setAttribute("x1",String(s.x1)),n.setAttribute("y1",String(s.y1)),n.setAttribute("x2",String(s.x2)),n.setAttribute("y2",String(s.y2)),e.appendChild(n)}}function hs(e){return`peer-${dt(e).replace(/[^A-Za-z0-9.:\[\]-]/g,"-")}`}function dt(e){try{return new URL(e).host}catch{return e}}function bs(e){const t=new Map;for(const o of e){const s=o.via!==void 0&&o.via!==""?dt(o.via):"",n=t.get(s)??[];n.push(o),t.set(s,n)}return t}const gs=140,vs=200,ys=90,ws=20,Xt=60;function xs(e,t){const o=t!==null?t.maxX+gs:vs,s=t!==null?t.minY:0;return e.map((n,i)=>({url:n.url,score:n.score,x:o,y:s+i*ys}))}function Cs(e,t,o,s){const n=new Map;for(const r of e){if(!t.has(r.team))continue;const c=`${r.team}\0${r.peer}`,l=n.get(c);l===void 0?n.set(c,{team:r.team,peer:r.peer,startedAt:r.startedAt,count:1}):(l.startedAt=Math.min(l.startedAt,r.startedAt),l.count+=1)}const i=[];for(const r of n.values()){const c=t.get(r.team);if(c===void 0)continue;const l=o.find(b=>{try{return new URL(b.url).host===r.peer}catch{return!1}});if(l===void 0)continue;const u=Math.max(0,Math.round((s-r.startedAt)/1e3));i.push({x1:c.x,y1:c.y,x2:l.x,y2:l.y,label:`a2a_route · ${r.peer} · ${u}s`+(r.count>1?` ×${r.count}`:"")})}return i}function ks(e,t){const o=t!==null?{x:t.maxX+ws,y:e.length>0?(e[0].y+e[e.length-1].y)/2:(t.minY+t.maxY)/2}:{x:-80,y:0};return e.map((s,n)=>({x1:o.x,y1:o.y,x2:s.x,y2:s.y,label:n===0?"gns referral":""}))}function Es(e,t){if(e===null&&t.length===0)return null;let o=e!==null?e.minX:Number.POSITIVE_INFINITY,s=e!==null?e.minY:Number.POSITIVE_INFINITY,n=e!==null?e.maxX:Number.NEGATIVE_INFINITY,i=e!==null?e.maxY:Number.NEGATIVE_INFINITY;for(const r of t)o=Math.min(o,r.x-Xt),s=Math.min(s,r.y-Xt),n=Math.max(n,r.x+Xt),i=Math.max(i,r.y+Xt);return{minX:o,minY:s,maxX:n,maxY:i}}const Ns=11;function $s(e,t){let o=[],s=[],n=[];function i(c){for(const b of o)b.remove();o=[];const l=t.allNodes().filter(b=>b.remote===!0).map(b=>({url:b.peerUrl??b.id.slice(5),score:b.score,x:b.x,y:b.y}));s=l;const u=t.contentBounds();if(u!==null){const b=new Map;for(const[m,x]of t.allFrames())b.set(m,{name:m,x:x.x+x.w/2,y:x.y+Ns});for(const m of Cs(n,b,l,c))o.push(...r(m,"e-activity",m.label));for(const m of ks(l,u))o.push(...r(m,"e-federal",m.label))}}function r(c,l,u){const b=document.createElementNS("http://www.w3.org/2000/svg","line");b.setAttribute("class",l),b.setAttribute("x1",String(c.x1)),b.setAttribute("y1",String(c.y1)),b.setAttribute("x2",String(c.x2)),b.setAttribute("y2",String(c.y2)),e.appendChild(b);const m=[b];if(u!==""){const x=document.createElementNS("http://www.w3.org/2000/svg","text");x.setAttribute("class","edge-label mono"),x.setAttribute("x",String((c.x1+c.x2)/2+14)),x.setAttribute("y",String((c.y1+c.y2)/2+18)),x.textContent=u,e.appendChild(x),m.push(x)}return m}return{render:i,flyTo(c){return c(),s},placements:()=>s,setInFlight:c=>{n=c}}}function wo(e,t){const o=new Map,s=new Set;for(const n of e){if(n.joined!==!0)continue;const i=n.team.lastIndexOf("/");if(i<=0||n.team.slice(i+1)!==n.id.replace(/^session-/,"").slice(0,8))continue;const r=n.team;t.has(r)||s.has(r)||(o.has(r)?(o.delete(r),s.add(r)):o.set(r,n.id))}return o}function Ms(e,t,o,s){var r;const n=t.get(e);return n!==void 0?n:e.includes("/")?`member-${e.replace(/[^a-z0-9-]/gi,"-")}`:`member-${((r=o==null?void 0:o.find(c=>c.via===s))==null?void 0:r.team.split("/")[0])??"dsh"}-${e.replace(/^session-/,"").slice(0,8)}`}function Ss(e){const t=new Map;for(const o of e)for(let s=0;s<o.members.length;s++){const n=o.members[s].id,i=t.get(n)??[];i.push({team:o.name,index:s}),t.set(n,i)}return t}function As(e,t,o){const s=wo(t,new Set((o??[]).map(i=>i.team))),n=new Set;for(const i of e)for(const r of i.org)for(const c of r.members){const l=s.get(c);l!==void 0&&n.add(l)}return n}const Wn={x:0,y:0,scale:1};function Zt(e){return Math.max(Cn,Math.min(kn,e))}function Nt(e){const t=Number.isFinite(e.scale)?e.scale:1,o=Number.isFinite(e.x)?e.x:0,s=Number.isFinite(e.y)?e.y:0;return{x:o,y:s,scale:Zt(t)}}function ct(e,t,o){return{x:e.x+t/e.scale,y:e.y+o/e.scale}}function un(e,t,o){return{x:e.x+t/e.scale,y:e.y+o/e.scale,scale:e.scale}}function Xn(e,t,o,s){const n=Zt(e.scale*t);return n===e.scale?e:{x:e.x+o/e.scale-o/n,y:e.y+s/e.scale-s/n,scale:n}}const Ls=680,Is=.8,Ts=.6,Kn=16;function $n(e,t,o,s=Number.POSITIVE_INFINITY){if(e===null||t<=0||o<=0)return Wn;const n=e.maxX-e.minX,i=e.maxY-e.minY;if(!(n>0)||!(i>0))return Wn;const r=.9*Math.min(t/n,o/i),c=Math.min(s,r),l=t<Ls?Is:Ts;if(r<l){const b=Zt(Math.min(s,l));return{x:e.minX-Kn/b,y:e.minY-Kn/b,scale:b}}const u=Zt(c);return{x:(e.minX+e.maxX)/2-t/(2*u),y:(e.minY+e.maxY)/2-o/(2*u),scale:u}}function _s(e){return`translate(${-e.x*e.scale}px, ${-e.y*e.scale}px) scale(${e.scale})`}function Un(e,t){let o=e===null?null:{...e,minY:e.minY+yo};for(const s of t){if(s.remote!==!0)continue;const n=mt(s);o=o===null?{minX:n.x,minY:n.y,maxX:n.x+n.w,maxY:n.y+n.h}:{minX:Math.min(o.minX,n.x),minY:Math.min(o.minY,n.y),maxX:Math.max(o.maxX,n.x+n.w),maxY:Math.max(o.maxY,n.y+n.h)}}return o}function qn(e,t,o,s){const n=s>0&&s<o/2?s:0,i=$n(e,t,o-n,1);return n===0||e===null?i:{...i,y:i.y-n/i.scale}}function zn(...e){const t=Math.max(0,...e.map(o=>o.offsetHeight>0?o.offsetTop+o.offsetHeight:0));return t>0?t+8:0}function Rt(e){return e.type==="join-network"||e.type==="leave-network"?"$network":e.type==="create-team"||e.type==="remove-team"?e.name:e.team}function Os(e,t){if(t.type==="create-team"){const n=t.ids.map(i=>e.getNode(i)).filter(i=>i!==void 0).map(i=>mt(i));return n.length>0&&e.setFrame(t.name,En(n)),e.setTeamMembers(t.name,t.ids),()=>{e.setTeamMembers(t.name,e.teamMemberIds(t.name).filter(i=>!t.ids.includes(i))),e.removeFrame(t.name)}}if(t.type==="add-member"){const n=e.teamMemberIds(t.team),i=t.ids.filter(r=>!n.includes(r));return e.setTeamMembers(t.team,[...n,...i]),()=>{e.setTeamMembers(t.team,e.teamMemberIds(t.team).filter(r=>!i.includes(r)))}}if(t.type==="remove-member"){const n=e.teamMemberIds(t.team);return e.setTeamMembers(t.team,n.filter(i=>!t.ids.includes(i))),()=>{const i=e.teamMemberIds(t.team);e.setTeamMembers(t.team,[...i,...t.ids.filter(r=>!i.includes(r))])}}if(t.type==="remove-team"){const n=e.teamMemberIds(t.name),i=e.getFrame(t.name),r=i!==void 0?{...i}:void 0;return e.setTeamMembers(t.name,[]),e.removeFrame(t.name),()=>{r!==void 0&&e.setFrame(t.name,r),e.setTeamMembers(t.name,n)}}if(t.type==="join-network"||t.type==="leave-network")return()=>{};const o=e.teamMemberIds(t.team);let s=[...o];for(const n of t.ops)n.op==="remove"?s=s.filter(i=>i!==n.id):s.push(n.id);return e.setTeamMembers(t.team,s),()=>{let n=e.teamMemberIds(t.team);for(let i=0;i<o.length;i++){const r=o[i];n[i]!==r&&n.includes(r)&&(n=n.filter(c=>c!==r),n.push(r))}e.setTeamMembers(t.team,n)}}function Jn(e,t,o,s,n){if(o||s(),!(t.type==="remove-team"&&o||t.type==="create-team"&&!o&&t.created===!0)||n===void 0||e.getFrame(Rt(t))!==void 0)return n;const r={...n.frames};return delete r[Rt(t)],{...n,frames:r}}function vn(e,t){const o=[...e],s=[];for(let n=0;n<t.length;n++){const i=t[n];o[n]!==i&&o.includes(i)&&(s.push({op:"remove",id:i}),s.push({op:"add",id:i}),o.splice(o.indexOf(i),1),o.push(i))}return s}function Fs(e,t){return e.teamMemberIds(t).map(o=>{var s;return{id:o,y:((s=e.getNode(o))==null?void 0:s.y)??0}}).sort((o,s)=>o.y-s.y).map(o=>o.id)}function Kt(e,t){let o,s=Number.POSITIVE_INFINITY;for(const[n,i]of e){if(t.x<i.x||t.x>i.x+i.w||t.y<i.y||t.y>i.y+i.h)continue;const r=i.w*i.h;r<s&&(o=n,s=r)}return o}const Vn=[9133302,3900150,1357990,16096779,15485081,8702998];function Ps(e){let t=0;for(let c=0;c<e.length;c++)t=(t*31+e.charCodeAt(c)&268435455)>>>0;const o=Vn[t%Vn.length],s="#"+o.toString(16).padStart(6,"0"),n=o>>16&255,i=o>>8&255,r=o&255;return{line:s,bg:`rgba(${n},${i},${r},0.05)`}}const en="roster:",xo=e=>e.startsWith(en)?e.slice(en.length):void 0,Ft=e=>en+e,tn=e=>{const t=xo(e);return t===void 0?e:`网络队 · roster · ${t}`};function Ds(e,t){return e.flatMap(o=>{if(t===""||!o.team.startsWith(t+"/")||!Array.isArray(o.members))return[];const s=o.team.slice(t.length+1);return s===""||s.length>40||s.includes("/")||s.startsWith(en)||s.includes("*")?[]:[{name:Ft(s),team:o.team,kind:"roster",members:o.members.filter(n=>typeof n=="string"&&n!=="").map(n=>({id:n}))}]})}function Rs(e){const{root:t,netBtn:o,signal:s,model:n}=e,i=y=>e.isRoster(y)?tn(y):y;function r(){return n.selectedIds().map(y=>{var f;return{id:y,y:((f=n.getNode(y))==null?void 0:f.y)??0}}).sort((y,f)=>y.y-f.y).map(y=>y.id)}function c(){if(l!==null)return;const y=r().filter(f=>{const _=n.getNode(f);return _===void 0?!1:_.remote!==!0||_.remoteHandle!==void 0&&_.remoteHandle!==""});if(y.length<2){e.notice("info","框选至少 2 个会话节点");return}u(y)}let l=null;function u(y){const f=document.createElement("div");f.className="p-dialog";const _=document.createElement("div");_.className="p-dialog-panel",_.setAttribute("role","dialog"),_.setAttribute("aria-modal","true"),_.setAttribute("aria-labelledby","p-dialog-title");const p=document.createElement("div");p.id="p-dialog-title",p.className="p-dialog-title",p.textContent=`组建团队(${y.length} 个节点,自上而下即优先级)`;const R={value:"canvas"},j=document.createElement("div");j.className="p-dialog-kind",j.setAttribute("role","radiogroup"),j.setAttribute("aria-label","团队类型");const K=document.createElement("div");K.className="p-dialog-hint";const we={canvas:"canvas 队:画布上的协作组,可以加入远端成员。",roster:"roster 网络队:只收本机已入网的会话;队名会写进属主的精确允许名单。"},Me=["canvas","roster"].map(ee=>{const te=document.createElement("button");return te.type="button",te.dataset.kind=ee,te.setAttribute("role","radio"),te.textContent=ee==="canvas"?"canvas 队":"roster 网络队",te.addEventListener("click",()=>D(ee)),j.appendChild(te),te});function D(ee){R.value=ee;for(const te of Me){const Ce=te.dataset.kind===ee;te.setAttribute("aria-checked",String(Ce)),te.tabIndex=Ce?0:-1}K.textContent=we[ee],ce.textContent=""}j.addEventListener("keydown",ee=>{var Ce;const te=ee;["ArrowLeft","ArrowRight","ArrowUp","ArrowDown"].includes(te.key)&&(te.preventDefault(),D(R.value==="canvas"?"roster":"canvas"),(Ce=Me.find(Be=>Be.dataset.kind===R.value))==null||Ce.focus())});const U=document.createElement("input");U.className="p-dialog-input",U.maxLength=40,U.setAttribute("aria-label","团队名");const ce=document.createElement("div");ce.className="p-dialog-err",ce.setAttribute("aria-live","polite");const Re=document.createElement("div");Re.className="p-dialog-row";const Ee=document.createElement("button");Ee.type="button",Ee.textContent="组建";const le=document.createElement("button");le.type="button",le.textContent="取消",Re.append(Ee,le),D("canvas"),_.append(p,j,K,U,ce,Re),f.appendChild(_),t.appendChild(f);const He=document.activeElement,fe=()=>{f.remove(),l=null,He==null||He.focus()},q=()=>{const ee=U.value.trim();return ee===""||ee.length>40||ee.includes("/")||ee.startsWith("roster:")||R.value==="roster"&&ee.includes("*")||/^\d+$/.test(ee)?"队名需 1..40 字,不含“/”、通配符或保留前缀,不为纯数字":R.value==="roster"&&n.getFrame(ee)!==void 0?"同名 canvas 队已存在,不能创建 roster 队":R.value==="roster"&&n.getFrame(Ft(ee))!==void 0&&!e.isRoster(Ft(ee))?"roster 框名已被 canvas 或镜像队占用":R.value==="canvas"&&n.getFrame(Ft(ee))!==void 0?"同名 roster 队已存在,不能创建 canvas 队":R.value==="roster"&&y.some(te=>{var Ce;return((Ce=n.getNode(te))==null?void 0:Ce.remote)===!0||!e.joined(te)})?"roster 仅接受本机已入网的会话":null},de=()=>{const ee=q();if(ee!==null){ce.textContent=ee,U.focus();return}const te=R.value==="roster"?Ft(U.value.trim()):U.value.trim();if(fe(),n.getFrame(te)!==void 0){e.notice("info",`已加入现有团队「${R.value==="roster"?tn(te):te}」`),e.emit({type:"add-member",team:te,ids:y});return}e.emit({type:"create-team",name:te,ids:y,created:!0,...R.value==="roster"?{roster:!0}:{}})};Ee.addEventListener("click",de),le.addEventListener("click",fe),U.addEventListener("keydown",ee=>{const te=ee;te.key==="Enter"&&(te.preventDefault(),de()),te.key==="Escape"&&(te.preventDefault(),fe())}),f.addEventListener("keydown",ee=>{const te=ee;if(te.key==="Escape"){te.preventDefault(),te.stopPropagation(),fe();return}if(te.key!=="Tab")return;te.preventDefault();const Ce=Array.from(_.querySelectorAll('input, select, button:not([tabindex="-1"])')),Be=Ce.indexOf(document.activeElement),Ye=te.shiftKey?Ce[(Be-1+Ce.length)%Ce.length]:Ce[(Be+1)%Ce.length];Ye==null||Ye.focus()},s),l={wrap:f,restoreFocus:He},U.focus()}let b=null,m="root",x=null,N=null,Y=[];function re(){N==null||N.remove(),N=null}function V(){var _;if(N!==null){re();return}if(Y.length===0)return;const y=document.createElement("div");y.className="p-menu p-netmenu",y.setAttribute("role","menu"),y.setAttribute("aria-label","未入网会话");for(const p of Y)y.appendChild(C(`${p.name!==void 0&&p.name!==""?p.name:p.label} — 入网`,!0,()=>{re(),e.emit({type:"join-network",id:p.id})}));N=y,t.appendChild(y);const f=o.getBoundingClientRect();y.style.left=`${String(Math.min(f.left,window.innerWidth-220))}px`,y.style.top=`${String(Math.max(8,f.top-(Y.length*30+10)))}px`,y.addEventListener("keydown",p=>{p.key==="Escape"&&(p.stopPropagation(),re(),o.focus())}),(_=y.querySelector("button"))==null||_.focus(),document.addEventListener("pointerdown",p=>{if(N===null)return;const R=p.target;R!==null&&(R.closest(".p-netmenu")!==null||R===o||o.contains(R))||re()},s)}function M(){b==null||b.remove(),b=null,m="root",x!==null&&x.isConnected?x.focus():t.focus(),x=null}function C(y,f,_){const p=document.createElement("button");return p.type="button",p.setAttribute("role","menuitem"),p.textContent=y,f?p.addEventListener("click",()=>{M(),_()}):(p.disabled=!0,p.setAttribute("aria-disabled","true")),p}function S(y,f,_,p="root",R){var Me,D,U,ce,Re,Ee,le,He;R!==void 0&&(x=R),x===null&&(x=e.anchorFor(_)),b==null||b.remove(),m=p;const j=document.createElement("div");j.className="p-menu",j.setAttribute("role","menu"),j.setAttribute("aria-label","团队操作");let K=[];if(_.kind==="frame")K=[C(`解散团队「${i(_.name)}」`,!0,()=>e.emit({type:"remove-team",name:_.name}))];else{const fe=_.id;if(p==="root"){const q=C("组成团队…",n.selectedIds().length>=2,()=>u(r()));q.title="先框选或 Shift 加选至少 2 个节点",K.push(q);const de=((Me=n.getNode(fe))==null?void 0:Me.memberships.map(ee=>ee.team))??[];e.teams().length>0&&(K.push(C("加入团队 ▸",!0,()=>S(y,f,_,"join"))),de.length>0&&K.push(C("置顶路由 ▸",!0,()=>S(y,f,_,"promote")))),de.length>0&&K.push(C("离队 ▸",!0,()=>S(y,f,_,"leave"))),((D=n.getNode(fe))==null?void 0:D.remote)!==!0&&K.push(C("退网",!0,()=>e.emit({type:"leave-network",id:fe})))}else{K.push(C("‹ 返回",!0,()=>S(y,f,_,"root")));for(const q of e.teams())if(p==="join"){const de=((U=n.getNode(fe))==null?void 0:U.memberships.some(Ce=>Ce.team===q.name))??!0,ee=!e.isRoster(q.name)||e.joined(fe)&&((ce=n.getNode(fe))==null?void 0:ce.remote)!==!0,te=C(de?`${i(q.name)}(已加入)`:i(q.name),!de&&ee,()=>e.emit({type:"add-member",team:q.name,ids:[fe]}));ee||(te.title="roster 只接受本机已入网会话"),K.push(te)}else if(p==="leave"){const de=((Re=n.getNode(fe))==null?void 0:Re.memberships.some(ee=>ee.team===q.name))??!1;K.push(C(i(q.name),de,()=>e.emit({type:"remove-member",team:q.name,ids:[fe]})))}else{const de=((Ee=n.getNode(fe))==null?void 0:Ee.memberships.some(ee=>ee.team===q.name))??!1;if(e.isRoster(q.name))continue;K.push(C(i(q.name),de,()=>{const ee=n.teamMemberIds(q.name),te=[fe,...ee.filter(Ce=>Ce!==fe)];e.emit({type:"reorder",team:q.name,ops:vn(ee,te)})}))}if(p==="leave"){const q=new Set(e.teams().map(de=>de.name));for(const de of((le=n.getNode(fe))==null?void 0:le.memberships)??[])q.has(de.team)||K.push(C(i(de.team),!0,()=>e.emit({type:"remove-member",team:de.team,ids:[fe]})))}}}j.append(...K),j.style.left=`${Math.min(y,window.innerWidth-200)}px`;const we=K.length*30+8;j.style.top=`${Math.max(8,Math.min(f,window.innerHeight-we-8))}px`,j.addEventListener("keydown",fe=>{var te,Ce,Be,Ye;const q=fe,de=Array.from(j.querySelectorAll("[role=menuitem]")),ee=de.indexOf(document.activeElement);q.key==="ArrowDown"?(q.preventDefault(),(te=de[(ee+1+de.length)%de.length])==null||te.focus()):q.key==="ArrowUp"?(q.preventDefault(),(Ce=de[(ee-1+de.length)%de.length])==null||Ce.focus()):q.key==="Home"?(q.preventDefault(),(Be=de[0])==null||Be.focus()):q.key==="End"?(q.preventDefault(),(Ye=de[de.length-1])==null||Ye.focus()):q.key==="Escape"&&(q.preventDefault(),q.stopPropagation(),m!=="root"?S(y,f,_,"root"):M())}),t.appendChild(j),b=j,(He=K[0])==null||He.focus()}function E(y,f,_){if(l!==null)return;const p=(_==null?void 0:_.closest(".p-node"))??null;if(p!==null){const K=n.getNode(p.dataset.id??"");if((K==null?void 0:K.remote)===!0&&(K.remoteHandle===void 0||K.remoteHandle===""))return}const R=p,j=(_==null?void 0:_.closest(".p-frame-head"))??null;if(R!==null){const K=R.dataset.id??"";n.isSelected(K)||n.setSelection([K]),x=R,S(y,f,{kind:"node",id:K})}else j!==null&&(x=j,S(y,f,{kind:"frame",name:j.dataset.frame??""}))}function G(y){Y=y,o.textContent=`未入网${Y.length>0?`(${String(Y.length)})`:""}`,o.disabled=Y.length===0,o.setAttribute("aria-disabled",String(Y.length===0)),Y.length===0&&re()}return{menuItem:C,isMenuOpen:()=>b!==null,isDialogOpen:()=>l!==null,closeMenu:M,openMenu:S,contextMenuAt:E,openNameDialog:u,startCreateFromSelection:c,toggleNetMenu:V,setUnjoined:G}}function Hs(e,t){const o=t.trim().toLowerCase();return o===""?[]:e.filter(s=>s.name.toLowerCase().includes(o)||s.team.toLowerCase().includes(o)||(s.host??"").toLowerCase().includes(o)).slice(0,8)}function js(e,t){return e.allNodes().map(o=>{const s=o.id.slice(5),n=o.id.startsWith("member-")?o.name!==void 0&&o.name!==""?o.name:o.team:o.remote===!0?s:t(o);return{id:o.id,name:n,team:o.team,...o.remote===!0?{host:s}:{}}})}function Bs(e,t=1200){e!==void 0&&(e.classList.add("pulse"),setTimeout(()=>e.classList.remove("pulse"),t))}function Ys(e){return t=>{const o=e.model.getNode(t);if(o===void 0)return;const s=e.viewSize();e.setVp($n({minX:o.x,minY:o.y,maxX:o.x+Ue,maxY:o.y+De},s.w,s.h,1)),e.applyViewport(),e.markDirty(),Bs(e.cardEl(t))}}function Ws(e,t,o,s){const n=Xs({onPick:s});return e.appendChild(n.root),{...n,refresh:()=>n.setIndex(js(t,o))}}function Xs(e){const t=document.createElement("div");t.className="p-search";const o=document.createElement("input");o.type="search",o.className="p-search-input",o.placeholder="🔍 搜索(Ctrl+K)",o.title="搜索名字 / 句柄 / 宿主(Ctrl+K 聚焦,Esc 清空)",o.setAttribute("aria-label","搜索画板节点:名字、句柄或宿主");const s=document.createElement("div");s.className="p-search-list";let n=[],i=[],r=0;const c=()=>{s.style.display="none",s.textContent=""},l=()=>{if(s.textContent="",i.length===0){c();return}i.forEach((m,x)=>{const N=document.createElement("div");N.className="p-search-hit"+(x===r?" active":""),N.dataset.id=m.id,N.textContent=m.name===m.team?m.name:`${m.name} · ${m.team}`,N.addEventListener("mousedown",Y=>{Y.preventDefault(),e.onPick(m.id),u()}),s.appendChild(N)}),s.style.display="block"},u=()=>{o.value="",i=[],c()},b=()=>{i=Hs(n,o.value),r=0,l()};return o.addEventListener("input",b),o.addEventListener("keydown",m=>{if(m.key==="Escape"){u(),o.blur(),m.stopPropagation();return}if(m.key==="ArrowDown"||m.key==="ArrowUp"){if(i.length===0)return;m.preventDefault(),r=(r+(m.key==="ArrowDown"?1:i.length-1))%i.length,l();return}m.key==="Enter"&&i.length>0&&(m.preventDefault(),e.onPick(i[r].id),u())}),t.append(o,s),{root:t,setIndex(m){n=m,o.value!==""&&b()},focus(){o.focus(),o.select()},clear(){u()}}}const Ut=28,Gn=16,Qn=14,Zn=48,Ks=4,Us=180,qs=90,zs=1600;function Js(e){const t=e.wrapWidth??zs,o=e.frames.map(l=>{const u=Math.max(l.soleIds.length,1),b=Math.min(Ks,Math.max(1,Math.ceil(Math.sqrt(u)))),m=Math.ceil(u/b),x=Math.max(Us,Ut*2+b*Ue+(b-1)*Gn),N=Math.max(qs,Ut*2+m*De+(m-1)*Qn);return{name:l.name,w:x,h:N,rows:m,perRow:b,soleIds:l.soleIds}}),s=[],n=[];let i=0,r=0,c=0;for(const l of o){i>0&&i+l.w>t&&(i=0,r+=c+Zn,c=0);const u={x:i,y:r,w:l.w,h:l.h};s.push({name:l.name,rect:u});const b=u.x+Ut+Ue/2;let m=u.y+Ut+De/2;l.soleIds.forEach((x,N)=>{const Y=N%l.perRow;N>0&&Y===0&&(m+=De+Qn),n.push({id:x,x:b+Y*(Ue+Gn),y:m})}),i+=l.w+Zn,c=Math.max(c,l.h)}return{frames:s,seats:n}}function Vs(e,t){const o=[];for(const[n,i]of e.allFrames()){if(t.has(n))continue;const r=e.teamMemberIds(n).map(c=>e.getNode(c)).filter(c=>c!==void 0).filter(c=>c.memberships.length===1).map(c=>c.id);o.push({name:n,rect:i,soleIds:r})}if(o.length===0)return!1;const s=Js({frames:o});for(const n of s.frames)e.setFrame(n.name,n.rect);for(const n of s.seats){const i=e.getNode(n.id);i!==void 0&&e.dragNodes([n.id],n.x-i.x,n.y-i.y)}return!0}function Gs(e,t){if(e===void 0)return;const o=dt(e);return{text:t?`同步中… · ${o}`:`镜像 · ${o}`,title:t?`已把改动交给属主 ${o},等待它确认`:`这个团队属于 ${o},这里显示的是它的镜像;拖入或移出成员会经中继交给 ${o} 执行`,syncing:t}}const Qs=1e4;function Zs(e=Date.now){const t=(s,n)=>`${s}\0${n}`,o=new Map;return{fork(s,n){return o.set(t(n,s.name),{url:n,name:s.name}),{...s,fleetPeer:n}},settled(s,n){if(s.type!=="remove-team"||s.name===void 0||s.fleetPeer===void 0)return;const i=o.get(t(s.fleetPeer,s.name));i!==void 0&&(n?i.acceptedAt=e():o.delete(t(s.fleetPeer,s.name)))},hides(s,n){return o.has(t(n,s))},sweep(s){var n;for(const[i,r]of o)(!(((n=s.find(l=>l.url===r.url))==null?void 0:n.org.some(l=>l.name===r.name))===!0)||r.acceptedAt!==void 0&&e()-r.acceptedAt>Qs)&&o.delete(i)}}}const Ct=24,ei=200,Jt=(e,t)=>e.x<t.x+t.w&&t.x<e.x+e.w&&e.y<t.y+t.h&&t.y<e.y+e.h;function ti(e,t){const o=t.x+t.w+Ct-e.x,s=t.x-Ct-(e.x+e.w),n=t.y+t.h+Ct-e.y,i=t.y-Ct-(e.y+e.h),r=Math.abs(o)<=Math.abs(s)?o:s,c=Math.abs(n)<=Math.abs(i)?n:i;return Math.abs(r)<=Math.abs(c)?{dx:r,dy:0}:{dx:0,dy:c}}function ni(e,t,o,s){const n=e.beginFrameDrag(t);n!==void 0&&e.applyFrameDrag(n,o,s)}function oi(e,t,o){let s=!1;for(let n=0;n<ei;n++){const i=e.allFrames();let r;for(let M=0;M<i.length&&r===void 0;M++)for(let C=M+1;C<i.length;C++){const[S,E]=i[M],[G,y]=i[C];if(!(t.has(S)&&t.has(G))&&Jt(E,y)){r=[S,E,G,y];break}}if(r===void 0)return s;const[c,l,u,b]=r,m=M=>t.has(M)?2:M===o?1:0,[x,N,Y]=m(c)<m(u)?[c,l,b]:[u,b,l],{dx:re,dy:V}=ti(N,Y);ni(e,x,re,V),s=!0}return s}const gt=28,Vt=16,nn=14;function si(e){const t=[];for(let o=e.y+gt;o+De<=e.y+e.h-gt;o+=De+nn)for(let s=e.x+gt;s+Ue<=e.x+e.w-gt;s+=Ue+Vt)t.push({x:s+Ue/2,y:o+De/2});return t}function ii(e){let t=!1;const o=e.allFrames(),s=new Map(o);for(const n of e.allNodes()){const i=new Set(n.memberships.map(V=>V.team)),r=o.find(([V,M])=>!i.has(V)&&Jt(mt(n),M));if(r===void 0)continue;const c=r[1],l=V=>{const M=mt(V);return o.every(([C,S])=>i.has(C)||!Jt(M,S))&&e.allNodes().every(C=>C.id===n.id||!Jt(M,mt(C)))},b=n.memberships.map(V=>s.get(V.team)).filter(V=>V!==void 0).flatMap(si).find(l),m={x:c.x+c.w+Ct+Ue/2,y:n.y},x={x:n.x,y:c.y+c.h+Ct+De/2},N=Math.max(...o.map(([,V])=>V.x+V.w))+Ct+Ue/2,Y=Array.from({length:2*e.allNodes().length+1},(V,M)=>({x:N,y:c.y+De/2+M*(De+nn)})),re=b??[m,x,...Y].find(l)??Y[Y.length-1];e.dragNodes([n.id],re.x-n.x,re.y-n.y),t=!0}return t}function qt(e,t,o){const s=oi(e,t,o),n=ii(e);return s||n}function ri(e){for(const[t,o]of e.allFrames()){const s=e.teamMemberIds(t).map(u=>e.getNode(u)).filter(u=>u!==void 0).filter(u=>u.memberships.length===1);if(s.length===0)continue;const n=Math.max(1,Math.floor((o.w-2*gt+Vt)/(Ue+Vt))),i=Math.ceil(s.length/n),r=gt*2+i*De+(i-1)*nn;r>o.h&&e.setFrame(t,{...o,h:Math.min(r,o.h+400)});const c=o.x+gt+Ue/2;let l=o.y+gt+De/2;s.forEach((u,b)=>{const m=b%n;b>0&&m===0&&(l+=De+nn);const x=c+m*(Ue+Vt);e.dragNodes([u.id],x-u.x,l-u.y)})}}const ai=30;function ci(e){const t=[],o=()=>({nodes:new Map(e.allNodes().map(i=>[i.id,{x:i.x,y:i.y}])),frames:new Map(e.allFrames().map(([i,r])=>[i,{...r}]))}),s=i=>e.allNodes().some(r=>{const c=i.nodes.get(r.id);return c!==void 0&&(c.x!==r.x||c.y!==r.y)})||e.allFrames().some(([r,c])=>{const l=i.frames.get(r);return l!==void 0&&(l.x!==c.x||l.y!==c.y||l.w!==c.w||l.h!==c.h)}),n=i=>{for(const r of e.allNodes()){const c=i.nodes.get(r.id);c!==void 0&&(c.x!==r.x||c.y!==r.y)&&e.dragNodes([r.id],c.x-r.x,c.y-r.y)}for(const[r,c]of e.allFrames()){const l=i.frames.get(r);l!==void 0&&(l.x!==c.x||l.y!==c.y||l.w!==c.w||l.h!==c.h)&&e.setFrame(r,{...l})}};return{capture:o,commit(i){s(i)&&(t.push(i),t.length>ai&&t.shift())},undo(){const i=t.pop();return i===void 0?!1:(n(i),!0)},revert(i){return s(i)?(n(i),!0):!1},get depth(){return t.length}}}function li(e){const{root:t,trigger:o,signal:s,model:n}=e;let i=null,r="",c=null;function l(){c==null||c.remove(),c=null}function u(){l(),i==null||i.remove(),i=null}function b(){if(i!==null){u();return}const C=document.createElement("div");C.className="p-menu p-nodelist",C.setAttribute("role","dialog"),C.setAttribute("aria-label","节点清单"),i=C,t.appendChild(C);const S=o.getBoundingClientRect();C.style.left=`${String(Math.min(S.left,window.innerWidth-340))}px`,C.style.top=`${String(Math.max(8,S.top-320))}px`,C.addEventListener("keydown",E=>{E.key==="Escape"&&(E.stopPropagation(),u(),o.focus())}),m()}function m(){var _;const C=i;if(C===null)return;l(),C.textContent="";const S=document.createElement("div");S.className="p-nodelist-head";const E=document.createElement("span");E.className="p-nodelist-title",E.textContent="节点";const G=document.createElement("select");G.className="p-nodesel",G.setAttribute("aria-label","选择 host 或对等节点");const y=document.createElement("option");y.value="",y.textContent="本机",G.appendChild(y);for(const[p,R]of e.facts().remoteTeams){if(p==="")continue;const j=document.createElement("option");j.value=p,j.textContent=((_=R[0])==null?void 0:_.origin)!==void 0&&R[0].origin!==""?`${R[0].origin}(${p})`:p,G.appendChild(j)}r!==""&&!e.facts().remoteTeams.has(r)&&(r=""),G.value=r,G.addEventListener("change",()=>{r=G.value,m()}),S.append(E,G);const f=document.createElement("div");f.className="p-nodelist-body",C.append(S,f),r===""?V(f):M(f,e.facts().remoteTeams.get(r)??[])}function x(C,S){const E=document.createElement("span");return E.className="p-nodedot"+(S!==!0?" off":C===!1?" cold":""),E}function N(C,S){const E=document.createElement("button");return E.type="button",E.className="p-listbtn",E.textContent=C,E.addEventListener("click",G=>{G.stopPropagation(),S()}),E}function Y(C,S){const E=document.createElement("div");if(E.className="p-nodelist-group",E.textContent=C,S!==void 0){const G=document.createElement("span");G.className="p-nodelist-note",G.textContent=S,E.appendChild(G)}return E}function re(C,S){var y,f;l();const E=document.createElement("div");E.className="p-menu",E.setAttribute("role","menu"),E.setAttribute("aria-label","加入团队");for(const _ of e.facts().teams){const p=((y=n.getNode(S))==null?void 0:y.memberships.some(R=>R.team===_.name))??!1;E.appendChild(e.menuItem(p?`${_.name}(已加入)`:_.name,!p,()=>{u(),e.emit({type:"add-member",team:_.name,ids:[S]})}))}E.appendChild(e.menuItem("新团队…",!0,()=>{u(),e.openNameDialog([S])})),c=E,t.appendChild(E);const G=C.getBoundingClientRect();E.style.left=`${String(Math.min(G.right+4,window.innerWidth-180))}px`,E.style.top=`${String(Math.max(8,G.top-60))}px`,E.addEventListener("keydown",_=>{_.key==="Escape"&&(_.stopPropagation(),l(),C.focus())}),(f=E.querySelector("button"))==null||f.focus()}function V(C){var f,_;const S=new Set(e.facts().canvasMemberIds);for(const p of e.facts().sessions)p.teams!==void 0&&p.teams.length>0&&S.add(p.id);const E=e.facts().sessions.filter(p=>p.joined===!0&&!S.has(p.id)),G=e.facts().sessions.filter(p=>p.joined!==!0),y=e.facts().sessions.filter(p=>p.joined===!0&&S.has(p.id));C.appendChild(Y(`未组队 (${String(E.length)})`,"无网络能力"));for(const p of E){const R=document.createElement("div");R.className="p-noderow";const j=document.createElement("span");j.className="p-nodename",j.textContent=p.name!==void 0&&p.name!==""?p.name:p.label,j.title=p.team;const K=document.createElement("span");K.className="p-nonet",K.textContent="无网络能力";const we=N("入队▸",()=>re(we,p.id));R.append(x(p.live,!0),j,K,we,N("退网",()=>{u(),e.emit({type:"leave-network",id:p.id})})),C.appendChild(R)}C.appendChild(Y(`未入网 (${String(G.length)})`));for(const p of G){const R=document.createElement("div");R.className="p-noderow";const j=document.createElement("span");j.className="p-nodename",j.textContent=p.name!==void 0&&p.name!==""?p.name:p.label,j.title=p.id,R.append(x(p.live,!1),j,N("入网",()=>{u(),e.emit({type:"join-network",id:p.id})})),C.appendChild(R)}C.appendChild(Y(`已组队 (${String(y.length)})`,"画布展示"));for(const p of y){const R=document.createElement("div");R.className="p-noderow";const j=document.createElement("span");j.className="p-nodename",j.textContent=p.name!==void 0&&p.name!==""?p.name:p.label,j.title=p.team;const K=((f=n.getNode(p.id))==null?void 0:f.memberships.length)??0,we=((_=p.teams)==null?void 0:_.length)??0,Me=document.createElement("span");Me.className="p-teamcount",Me.textContent=`队×${String(Math.max(K,0)+we)}`,R.append(x(p.live,!0),j,Me,N("定位",()=>{e.locate(p.id)})),C.appendChild(R)}if(e.facts().sessions.length===0){const p=document.createElement("div");p.className="p-nodelist-empty",p.textContent="无会话节点",C.appendChild(p)}}function M(C,S){var y;const E=S.filter(f=>f.teams===void 0||f.teams.length===0),G=S.filter(f=>f.teams!==void 0&&f.teams.length>0);C.appendChild(Y(`未组队 (${String(E.length)})`,"无网络能力 · 只读"));for(const f of E){const _=document.createElement("div");_.className="p-noderow";const p=document.createElement("span");p.className="p-nodename",p.textContent=f.name!==void 0&&f.name!==""?f.name:f.team,p.title=f.team;const R=document.createElement("span");R.className="p-nonet",R.textContent="无网络能力",_.append(x(!0,!0),p,R),C.appendChild(_)}C.appendChild(Y(`已组队 (${String(G.length)})`,"只读"));for(const f of G){const _=document.createElement("div");_.className="p-noderow";const p=document.createElement("span");p.className="p-nodename",p.textContent=f.name!==void 0&&f.name!==""?f.name:f.team,p.title=f.team;const R=document.createElement("span");R.className="p-teamcount",R.textContent=`队×${String(((y=f.teams)==null?void 0:y.length)??0)}`,_.append(x(!0,!0),p,R),C.appendChild(_)}if(S.length===0){const f=document.createElement("div");f.className="p-nodelist-empty",f.textContent="该节点未发布会话",C.appendChild(f)}}return document.addEventListener("pointerdown",C=>{if(i===null)return;const S=C.target;if(S===null){u();return}S.closest(".p-nodelist")!==null||S.closest(".p-menu")!==null||S===o||o.contains(S)||u()},s),{toggle:b,close:u,refresh:()=>{i!==null&&m()}}}function di(e){let t=e;const o=t.search(/\|| ```|^```/);return o>=0&&(t=t.slice(0,o)),t.replace(/\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/(^|\s)#{1,6}\s+/g,"$1").replace(/\*\*|__|`/g,"").replace(/\s+/g," ").trim()}function mi(e,t){const o=e.map(i=>i.name!==void 0&&i.name!==""?i.name:i.team),s=o.slice(0,2).join("、"),n=o.length>2?` +${o.length-2}`:"";return(t!==void 0?`score ${t} · `:"")+`${e.length} 远端团队`+(s!==""?`:${s}${n}`:"")}function ui(e,t,o){if(e.id.startsWith("member-"))return{title:e.name!==void 0&&e.name!==""?e.name:e.team,sub:e.team,tip:e.team};if(e.remote===!0){const l=e.id.slice(5),u=t.length===1&&t[0].name!==void 0&&t[0].name!==""?t[0].name:void 0,b=mi(t,o);return u!==void 0?{title:u,sub:`${l} · ${b}`,tip:`${u}
6
- ${l}
7
- ${b}`}:{title:l,sub:b,tip:`${l}
8
- ${b}`}}const s=lt(e),n=e.team+(e.name!==void 0&&e.name!==""?" · "+e.name:""),i=di(e.description??""),r=i!==""?i:n===s?"":e.team,c=(e.memberships.length>1?` · 跨队×${e.memberships.length}`:"")+(e.teams!==void 0&&e.teams.length>0?` · 网络队×${e.teams.length}`:"");return{title:s,sub:r+c,tip:i!==""?`${n}
9
- ${i}`:n}}function fi(e){if((e==null?void 0:e.status)===void 0)return"";const t=e.status==="running"?"工作中":"空闲";return typeof e.queued=="number"&&e.queued>0?`${t} · 排队 ${String(e.queued)}`:t}function pi(e){const t=document.createElement("div");t.className="p-node",t.dataset.id=e,t.tabIndex=0;const o=document.createElement("div");o.className="nm";const s=document.createElement("span");s.className="dot";const n=document.createElement("span");n.className="nm-text",o.append(s,n);const i=document.createElement("div");i.className="sub mono";const r=document.createElement("span");r.className="prio mono";const c=document.createElement("span");c.className="work";const l=document.createElement("div");return l.className="sub-row",l.append(i,c),t.append(o,l,r),t}function hi(e,t,o){if(t.remote===!0){const s=(o==null?void 0:o.link)==="linked"?"lnk-linked":(o==null?void 0:o.link)==="stranger"?"lnk-stranger":"";e.className!==`prio mono ${s}`.trim()&&(e.className=`prio mono ${s}`.trim());const n=o===void 0?"":o.verified===!0?"✓":"✗",i=(t.id.startsWith("member-")?"成员":(o==null?void 0:o.link)??"peer")+n;e.textContent!==i&&(e.textContent=i)}else{e.className!=="prio mono"&&(e.className="prio mono");const s=t.memberships[0]!==void 0?`P${t.memberships[0].index}`:"";e.textContent!==s&&(e.textContent=s)}}const eo="dsh-a2a.board.legend";function bi(){const e=document.createElement("details");e.className="p-legend";const t=document.createElement("summary");t.textContent="图例",t.title="边的含义(点击展开 / 收起)";const o=document.createElement("div");o.className="p-legend-rows";const s=(n,i,r)=>{const c=document.createElement("span"),l=document.createElement("i");n&&(l.className="dashed"),r!==void 0&&(l.style.borderTopColor=r),c.append(l,document.createTextNode(i)),o.appendChild(c)};s(!1,"成员边(星形,框→成员)"),s(!0,"跨队多属(虚线)"),s(!0,"roster 网络队框(双线边框)"),s(!1,"活动边(inFlight 路由,瞬时)","var(--accent)"),s(!0,"联邦线(→peer)","var(--federal)"),e.append(t,o);try{e.open=window.localStorage.getItem(eo)==="open"}catch{}return e.addEventListener("toggle",()=>{try{window.localStorage.setItem(eo,e.open?"open":"closed")}catch{}}),e}const Gt="对端未应答(显示的是最后已知状态)";function to(e){const t=new Set;for(const s of e.remoteTeams??[])s.unreachable===!0&&s.via&&t.add(dt(s.via));for(const s of e.peerOrg??[])s.unreachable===!0&&t.add(dt(s.url));const o=new Set;for(const s of e.remoteTeams??[])s.via&&t.has(dt(s.via))&&o.add(`member-${s.team.replace(/[^a-z0-9-]/gi,"-")}`);return{hosts:t,members:o}}function gi(e,t){e.classList.toggle("is-unreachable",t);const o=e.querySelector(".p-frame-unreachable");if(t&&o===null){const s=document.createElement("span");s.className="p-frame-unreachable",s.textContent=Gt,e.appendChild(s)}else t||o==null||o.remove()}function vi(e){return e<680?"narrow":e<1024?"medium":"wide"}function yi(e){const t=new Nn;let o,s={...t.viewport},n={kind:"none"},i=!1,r=-1,c=!0,l=!1;const u=ci(t);let b,m=!1;const x=()=>vi(globalThis.innerWidth||qe),N=()=>{var a;(a=e.viewportStore)==null||a.set(x(),s),e.onDirty()},Y=e.now??Date.now,re=new AbortController,V=[];let M=null,C=!1;const S={signal:re.signal},E=document.createElement("section");E.id="dsh-plan",E.setAttribute("role","tabpanel"),E.setAttribute("aria-label","A2A 规划画布"),E.tabIndex=0,E.style.display="none";const G=document.createElement("div");G.className="p-grid";const y=document.createElement("div");y.className="p-world";const f=document.createElementNS("http://www.w3.org/2000/svg","svg");f.setAttribute("class","p-edges");const _=document.createElement("div");_.className="p-layer p-frames";let p;const R=a=>{var h,g;p!==void 0&&((h=Ie.get(p))==null||h.classList.remove("selected")),p=a,a!==void 0&&((g=Ie.get(a))==null||g.classList.add("selected"))},j=document.createElement("div");j.className="p-layer p-nodes",j.setAttribute("role","listbox"),j.setAttribute("aria-multiselectable","true"),j.setAttribute("aria-label","会话节点"),y.append(f,_,j);const K=document.createElement("div");K.className="p-marquee";const we=document.createElement("div");we.className="p-toolbar";const Me=document.createElement("span");Me.className="p-zoom mono",Me.textContent="100%";const D=(a,h,g)=>{const F=document.createElement("button");return F.type="button",F.textContent=a,F.title=h,F.addEventListener("click",g,S),F},U=()=>{const a=document.createElement("span");return a.className="p-sep",a.setAttribute("role","separator"),a.setAttribute("aria-orientation","vertical"),a};we.append(D("适配","适配视图(快捷键 0)",()=>it()),D("-","缩小",()=>pe(1/1.2)),Me,D("+","放大",()=>pe(1.2)),U(),D("建队","组成团队(G):先框选至少 2 个节点",()=>O.startCreateFromSelection()),D("整理成员","每队框内仅属一队的成员自动排齐(多队成员不动)",()=>vt()),D("一键重排","全板队框+成员重排:框尺寸随内容自适应、框位行流式平铺(远端队框与多归属成员不动)",()=>St()),D("撤销","撤销上一次布局改动:拖动、缩放、整理、重排、载入时避让(Ctrl+Z;入队离队不撤销)",()=>Oe()));const ce=D("未入网","未入网会话(点击选择入网)",()=>O.toggleNetMenu());ce.className="p-netbtn",ce.setAttribute("aria-haspopup","menu"),we.append(U(),ce);const Re=Ws(we,t,lt,a=>ne(a)),Ee=D("节点","节点清单:本机与对等节点(未组队/未入网在此管理)",()=>Z.toggle());Ee.className="p-nodebtn",Ee.setAttribute("aria-haspopup","dialog"),we.appendChild(Ee);const le=document.createElement("span");le.setAttribute("aria-live","polite"),le.className="p-lamp";const He=document.createElement("i"),fe=document.createElement("span");fe.textContent="布局",le.append(He,fe),le.addEventListener("click",()=>{le.classList.contains("error")&&e.onLampClick()},S),le.addEventListener("keydown",a=>{const h=a;(h.key==="Enter"||h.key===" ")&&le.classList.contains("error")&&(h.preventDefault(),e.onLampClick())},S),we.appendChild(le);const q=document.createElement("div");q.className="p-status";const de=document.createElement("span"),ee=document.createElement("span"),te=document.createElement("span");te.className="mut";const Ce=document.createElement("span");Ce.className="mut",q.append(de,ee,te,Ce),q.tabIndex=0,q.setAttribute("role","button"),q.setAttribute("aria-label","定位在途路由与联邦对端"),q.title="定位在途与联邦(回车)",q.addEventListener("click",()=>ve(),S),q.addEventListener("keydown",a=>{const h=a;(h.key==="Enter"||h.key===" ")&&(h.preventDefault(),ve())},S);const Be=bi(),Ye=document.createElement("div");Ye.className="p-notice-stack",Ye.setAttribute("role","log"),Ye.setAttribute("aria-live","polite"),E.append(G,y,K,we,q,Be,Ye);let qe=0,ut=0;const kt=()=>e.viewSize?e.viewSize():{w:E.clientWidth,h:E.clientHeight},Je=()=>{const a=kt();qe=a.w,ut=a.h};function Qe(){y.style.transform=_s(s);const a=24*s.scale;G.style.backgroundSize=`${a}px ${a}px`,G.style.backgroundPosition=`${-s.x*s.scale}px ${-s.y*s.scale}px`,Me.textContent=`${Math.round(s.scale*100)}%`}function vt(){const a=u.capture();ri(t),qt(t,new Set(nt.keys())),u.commit(a),N(),Se()}function St(){const a=u.capture();Vs(t,new Set(nt.keys()))&&(qt(t,new Set(nt.keys())),u.commit(a),N(),Se())}function Se(){Qe(),t.revision!==r&&(r=t.revision,ft(),At(),ps(f,t)),ge()}const Ie=new Map,tt=new Map;function ft(){var h;const a=new Set;for(const[g,F]of t.allFrames()){a.add(g);let P=Ie.get(g);if(P===void 0){P=document.createElement("div"),P.className="p-frame",P.dataset.name=g;const oe=document.createElement("div");oe.className="p-frame-head",oe.dataset.frame=g,oe.tabIndex=0,oe.setAttribute("role","button"),oe.setAttribute("aria-haspopup","menu"),oe.setAttribute("aria-label",`团队框 ${g}(拖动整组,回车菜单)`);const Fe=document.createElement("span");Fe.className="ttl";const Ge=document.createElement("span");Ge.className="cnt mono";const rt=document.createElement("span");rt.className="route mono",oe.append(Fe,Ge,rt),P.appendChild(oe);for(const yt of["n","s","e","w","ne","nw","se","sw"]){const wt=document.createElement("div");wt.className=`p-frame-handle p-h-${yt}`,wt.dataset.frame=g,wt.dataset.dir=yt,P.appendChild(wt)}_.appendChild(P),Ie.set(g,P)}const ue=Ps(g);P.style.setProperty("--frame-line",ue.line),P.style.setProperty("--frame-bg",ue.bg),P.style.left=`${F.x}px`,P.style.top=`${F.y}px`,P.style.width=`${F.w}px`,P.style.height=`${F.h}px`;const W=P.querySelector(".ttl"),B=P.querySelector(".cnt"),z=P.querySelector(".route"),ie=k.has(g),Ae=ie?tn(g):g;W.textContent!==Ae&&(W.textContent=Ae),P.classList.toggle("is-roster",ie);let Le=0,Ne=0;for(const oe of t.allNodes())oe.memberships.find(Ge=>Ge.team===g)!==void 0&&(Le+=1,oe.memberships.length>1&&(Ne+=1));const Ke=`${Le} 成员`+(Ne>0?` +${Ne} 跨队`:"");B.textContent!==Ke&&(B.textContent=Ke);const v=Gs(nt.get(g),Te.has(g)),be=v!==void 0&&w.hosts.has(dt(nt.get(g))),he=(v==null?void 0:v.text)??((h=Ht.find(oe=>oe.name===g))==null?void 0:h.team)??g;z.textContent!==he&&(z.textContent=he),z.title=`${(v==null?void 0:v.title)??""}${be?` · ${Gt}`:""}`,gi(P,be),P.classList.toggle("is-mirror",v!==void 0),P.classList.toggle("is-syncing",(v==null?void 0:v.syncing)===!0);const je=`团队框 ${g}${v!==void 0?`(${v.text})`:""}${be?`(${Gt})`:""}(拖动整组,回车菜单)`,$e=P.querySelector(".p-frame-head");$e.getAttribute("aria-label")!==je&&$e.setAttribute("aria-label",je)}for(const[g,F]of[...Ie])a.has(g)||(F.remove(),Ie.delete(g))}function At(){const a=new Set;for(const h of t.allNodes()){a.add(h.id);let g=tt.get(h.id);g===void 0&&(g=pi(h.id),j.appendChild(g),tt.set(h.id,g));const F=mt(h);g.style.left=`${F.x}px`,g.style.top=`${F.y}px`,g.classList.toggle("cold",!h.live),g.classList.toggle("remote",h.remote===!0);const P=h.live&&h.remote!==!0?I.get(h.id):void 0;g.classList.toggle("is-working",(P==null?void 0:P.status)==="running");const ue=fi(P),W=g.querySelector(".work");W.textContent!==ue&&(W.textContent=ue),g.classList.toggle("selected",t.isSelected(h.id)),g.setAttribute("aria-selected",String(t.isSelected(h.id)));const B=h.id.slice(5),z=ui(h,h.remote===!0?A.get(B)??[]:[],Q.get(B)),ie=h.remote===!0&&(h.id.startsWith("member-")?w.members.has(h.id):w.hosts.has(B));g.classList.toggle("is-unreachable",ie);const Ae=g.querySelector(".nm-text");Ae.textContent!==z.title&&(Ae.textContent=z.title);const Le=g.querySelector(".sub"),Ne=ie?`未应答 · ${z.sub}`:z.sub;Le.textContent!==Ne&&(Le.textContent=Ne);const Ke=ie?`${z.tip} · ${Gt}`:z.tip;g.title!==Ke&&(g.title=Ke);const v=h.id.startsWith("member-")?me.get(h.remoteHandle??""):B;hi(g.querySelector(".prio"),h,h.remote===!0&&v!==void 0?X.get(v):void 0)}for(const[h,g]of[...tt])a.has(h)||(g.remove(),tt.delete(h));Re.refresh()}const d=$s(f,t);let A=new Map,I=new Map;const Q=new Map,X=new Map;let me=new Map;function ge(){d.render(Y())}function ve(){s=$n(Es(t.contentBounds(),d.placements()),E.clientWidth||qe,E.clientHeight||ut),Qe(),N()}const ne=Ys({model:t,viewSize:kt,setVp:a=>{s=a},applyViewport:Qe,markDirty:N,cardEl:a=>tt.get(a)});function We(a){var F;const h=a.sessions.filter(P=>P.live!==!1).length,g=(P,ue,W)=>{const B=document.createElement("b");B.className=ue,B.textContent=W,P.replaceChildren(B)};g(de,"ok",`● ${h} live`),g(ee,"warn",`● ${a.sessions.length-h} cold`),te.textContent=`${((F=a.inFlight)==null?void 0:F.length)??0} inFlight`,Ce.className="mut",Ce.textContent=`${a.teams.length} 队 · ${a.peerCount} peer`}const Te=new Map,Xe=a=>{Te.set(a,(Te.get(a)??0)+1),r=-1},Lt=a=>{r=-1;const h=(Te.get(a)??0)-1;h<=0?Te.delete(a):Te.set(a,h)};let nt=new Map,k=new Set,w=to({});const H=Zs(e.now);function $(a){const h=a.type==="create-team"&&a.roster===!0||k.has(Rt(a));if(h&&a.type==="remove-team"&&!window.confirm(`解散网络队「${tn(a.name)}」并撤回成员与白名单?`))return;if(h&&a.type==="reorder"){L("error","roster 队不支持置顶路由");return}if(h&&(a.type==="create-team"||a.type==="add-member")&&a.ids.some(W=>{var B;return((B=t.getNode(W))==null?void 0:B.remote)===!0||!se.some(z=>z.id===W&&z.joined===!0)})){L("error","roster 只接受本机已入网会话,远端或未入网成员未写入");return}function g(W){const B=z=>{var Ae;const ie=[];for(const Le of z){if(!Le.startsWith("peer-")&&!Le.startsWith("member-")){ie.push(Le);continue}const Ne=(Ae=t.getNode(Le))==null?void 0:Ae.remoteHandle;Ne!==void 0&&Ne!==""&&ie.push(Ne)}return ie};if(W.type==="add-member"||W.type==="remove-member"||W.type==="create-team"){const z=B(W.ids),ie=W.type!=="create-team"?nt.get(W.team):void 0;return z.length>0||ie!==void 0?{...W,ids:z,...ie!==void 0?{fleetPeer:ie}:{}}:W}return W.type==="remove-team"&&nt.has(W.name)?H.fork(W,nt.get(W.name)):W}if(a.type==="add-member"||a.type==="remove-member"||a.type==="reorder"||a.type==="create-team"){const W=a.type==="reorder"?a.ops.map(B=>B.id):[...a.ids];for(const B of W){if(B===""||B.startsWith("peer-")||B.startsWith("member-")||t.getNode(B)!==void 0)continue;const z=se.find(Le=>Le.id===B);if(z===void 0)continue;const ie=o==null?void 0:o.nodes[B],Ae=ie!==void 0?{x:ie.x,y:ie.y}:Sn(B);t.upsertNode({id:B,x:Ae.x,y:Ae.y,label:z.label,team:z.team,name:z.name,description:z.description,live:z.live!==!1,memberships:[],...z.teams!==void 0&&z.teams.length>0?{teams:z.teams}:{}})}}h&&a.type==="create-team"&&k.add(a.name);const F=Os(t,a),P=Rt(a);Xe(P),Se();const ue=g(h?{...a,roster:!0}:a);e.onCanvasAction(ue).then(W=>{Lt(P),!W&&a.type==="create-team"&&h&&k.delete(P),o=Jn(t,a,W,F,o),N(),H.settled(ue,W),Se()},()=>{Lt(P),a.type==="create-team"&&h&&k.delete(P),o=Jn(t,a,!1,F,o),N(),H.settled(ue,!1),L("error","操作通道异常,已回滚"),Se()})}function L(a,h){var F;for(;Ye.childElementCount>=3;)(F=Ye.firstElementChild)==null||F.remove();const g=document.createElement("div");g.className="p-notice"+(a==="error"?" error":""),g.setAttribute("role",a==="error"?"alert":"status"),g.textContent=h,Ye.appendChild(g),V.push(setTimeout(()=>g.remove(),4e3))}const O=Rs({root:E,netBtn:ce,signal:S,model:t,teams:()=>Ht,joined:a=>se.some(h=>h.id===a&&h.joined===!0),isRoster:a=>k.has(a),anchorFor:a=>(a.kind==="node"?tt.get(a.id):Ie.get(a.name))??null,emit:$,notice:L});let se=[],ae=new Set;const Z=li({root:E,trigger:Ee,signal:S,model:t,facts:()=>({sessions:se,canvasMemberIds:ae,remoteTeams:A,teams:Ht}),menuItem:O.menuItem,emit:$,openNameDialog:O.openNameDialog,locate:xe});zo(E,{signal:S,frames:()=>Ie,frameAt:(a,h)=>{const g=_e({clientX:a,clientY:h});return Kt(new Map(t.allFrames()),ct(s,g.x,g.y))},drop:(a,h)=>{var g;return((g=t.getNode(h))==null?void 0:g.memberships.some(F=>F.team===a))===!0?L("info","该会话已在这个队里"):$({type:"add-member",team:a,ids:[h]})}});function xe(a){var F;const h=t.getNode(a);if(h===void 0)return;Z.close();const g=((F=e.viewSize)==null?void 0:F.call(e))??{w:E.clientWidth>0?E.clientWidth:800,h:E.clientHeight>0?E.clientHeight:600};s=Nt({scale:s.scale,x:h.x-g.w/(2*s.scale),y:h.y-g.h/(2*s.scale)}),Qe(),r=-1,Se()}function _e(a){const h=E.getBoundingClientRect();return{x:a.clientX-h.left,y:a.clientY-h.top}}function J(a,h){var W;const g=_e(h),F=ct(s,g.x,g.y),P=Kt(new Map(t.allFrames()),F),ue=a.ids.filter(B=>{const z=t.getNode(B);return z===void 0?!1:z.remote!==!0?!0:z.remoteHandle!==void 0&&z.remoteHandle!==""});if(P!==void 0){const B=ue.filter(z=>{var ie;return!((ie=t.getNode(z))!=null&&ie.memberships.some(Ae=>Ae.team===P))});if(B.length>0){$({type:"add-member",team:P,ids:B});return}if(a.ids.length===1&&((W=t.getNode(a.clicked))==null?void 0:W.remote)!==!0){const z=t.teamMemberIds(P),ie=Fs(t,P);ie.join("\0")!==z.join("\0")&&$({type:"reorder",team:P,ops:vn(z,ie)})}}if(a.rosterOrigin!==void 0&&P!==a.rosterOrigin){const B=a.ids.filter(z=>t.teamMemberIds(a.rosterOrigin).includes(z));B.length>0&&$({type:"remove-member",team:a.rosterOrigin,ids:B})}}function Pe(a){if(qe===0&&Je(),O.isDialogOpen()){a.preventDefault();return}const h=a.target;if(O.isMenuOpen()){if(h!==null&&h.closest(".p-menu")!==null)return;O.closeMenu(),a.preventDefault();return}if(h!==null&&h.closest("button, input, textarea, select, .p-toolbar, .p-search, .p-lamp, .p-status, .p-legend")!==null)return;b=u.capture();const g=_e(a);if(a.button===2){M={x:g.x,y:g.y,target:a.target,moved:!1},a.preventDefault();try{E.setPointerCapture(a.pointerId??0)}catch{}return}const F=h!==null?h.closest(".p-node"):null,P=h!==null?h.closest(".p-frame-head"):null;if((F!==null||P!==null)&&a.button===1){n={kind:"pan",last:g,moved:!1},a.preventDefault();try{E.setPointerCapture(a.pointerId??0)}catch{}return}const ue=h!==null?h.closest(".p-frame-handle"):null;if(p!==void 0){const W=Ie.get(p),B=h!==null&&W!==void 0&&(W.contains(h)||W===h),z=P!==null&&P.dataset.frame===p;!B&&!z&&R(void 0)}if(ue!==null&&a.button===0){const W=ue.dataset.frame??"";R(W);const B=t.getFrame(W);if(B===void 0)return;n={kind:"frame-resize",name:W,dir:ue.dataset.dir??"se",startRect:{...B},origin:ct(s,g.x,g.y),moved:!1},a.preventDefault();try{E.setPointerCapture(a.pointerId??0)}catch{}return}if(F!==null){if(a.button!==0)return;const W=F.dataset.id??"",B=t.isSelected(W);!B&&!a.shiftKey&&t.setSelection([W]);const z=a.shiftKey||B?t.isSelected(W)?t.selectedIds():[...t.selectedIds(),W]:[W],ie=Kt(new Map(t.allFrames()),ct(s,g.x,g.y));n={kind:"node",clicked:W,ids:z,...ie&&k.has(ie)&&t.teamMemberIds(ie).includes(W)?{rosterOrigin:ie}:{},last:ct(s,g.x,g.y),moved:!1,el:F},F.classList.add("dragging")}else if(P!==null){if(a.button!==0)return;const W=P.dataset.frame??"";R(W);const B=t.beginFrameDrag(W);if(B===void 0)return;n={kind:"frame",name:W,snap:B,origin:ct(s,g.x,g.y),moved:!1}}else if(a.button===1||a.button===0&&i)n={kind:"pan",last:g,moved:!1};else if(a.button===0)n={kind:"marquee",origin:g,last:g,additive:a.shiftKey},K.style.display="block",K.style.left=`${g.x}px`,K.style.top=`${g.y}px`,K.style.width="0px",K.style.height="0px";else return;a.preventDefault();try{E.setPointerCapture(a.pointerId??0)}catch{}}function Ze(a){const h=_e(a);if(M!==null){const g=h.x-M.x,F=h.y-M.y;Math.hypot(g,F)>4&&(M.moved=!0,s=Nt(un(s,-g,-F)),M.x=h.x,M.y=h.y,Qe());return}if(n.kind==="node"){const g=ct(s,h.x,h.y),F=g.x-n.last.x,P=g.y-n.last.y;if(F===0&&P===0)return;n.moved=!0,n.last=g,t.dragNodes(n.ids,F,P);const ue=Kt(new Map(t.allFrames()),g),W=n.ids.filter(z=>{const ie=t.getNode(z);return ie===void 0?!1:ie.remote!==!0||ie.remoteHandle!==void 0&&ie.remoteHandle!==""}),B=ue!==void 0&&W.length>0;for(const[z,ie]of Ie)ie.classList.toggle("drop-target",B&&z===ue);Se()}else if(n.kind==="frame"){const g=ct(s,h.x,h.y),F=g.x-n.origin.x,P=g.y-n.origin.y;if(!n.moved&&F===0&&P===0)return;n.moved=!0,t.applyFrameDrag(n.snap,F,P),Se()}else if(n.kind==="frame-resize"){const g=ct(s,h.x,h.y),F=g.x-n.origin.x,P=g.y-n.origin.y;if(!n.moved&&F===0&&P===0)return;n.moved=!0;const ue=220,W=120,B={...n.startRect};let{x:z,y:ie,w:Ae,h:Le}=B;n.dir.includes("e")&&(Ae=Math.max(ue,B.w+F)),n.dir.includes("s")&&(Le=Math.max(W,B.h+P)),n.dir.includes("w")&&(Ae=Math.max(ue,B.w-F),z=B.x+(B.w-Ae)),n.dir.includes("n")&&(Le=Math.max(W,B.h-P),ie=B.y+(B.h-Le)),t.setFrame(n.name,{x:Math.round(z),y:Math.round(ie),w:Math.round(Ae),h:Math.round(Le)}),Se()}else if(n.kind==="pan")s=un(s,h.x-n.last.x,h.y-n.last.y),n.last=h,n.moved=!0,Qe();else if(n.kind==="marquee"){const g=Math.min(n.origin.x,h.x),F=Math.min(n.origin.y,h.y);K.style.left=`${g}px`,K.style.top=`${F}px`,K.style.width=`${Math.abs(h.x-n.origin.x)}px`,K.style.height=`${Math.abs(h.y-n.origin.y)}px`,n.last=h}}function et(a){var h,g;if(M!==null){const F=M.moved,P=M.target,ue=M.x,W=M.y;M=null,F?(C=!0,N()):P!==null&&O.contextMenuAt(ue,W,P);return}if(n.kind==="node"){const F=n.clicked;if(n.moved)J(n,a),N();else if(a.shiftKey){const P=t.selectedIds();t.setSelection(P.includes(F)?P.filter(ue=>ue!==F):[...P,F])}else t.setSelection([F]),(h=e.onNodePick)==null||h.call(e,F);for(const P of Ie.values())P.classList.remove("drop-target");(g=n.el)==null||g.classList.remove("dragging"),Se()}else if(n.kind==="frame"||n.kind==="frame-resize")n.moved&&(qt(t,new Set(nt.keys()),n.name),N(),Se());else if(n.kind==="pan")n.moved&&N();else if(n.kind==="marquee"){const F=n.last,P=ct(s,Math.min(n.origin.x,F.x),Math.min(n.origin.y,F.y)),ue=ct(s,Math.max(n.origin.x,F.x),Math.max(n.origin.y,F.y));t.marqueeSelect({x:P.x,y:P.y,w:ue.x-P.x,h:ue.y-P.y},n.additive),K.style.display="none",Se()}n={kind:"none"},b!==void 0&&(u.commit(b),b=void 0);try{E.releasePointerCapture(a.pointerId??0)}catch{}}function pt(a){var g;for(const F of Ie.values())F.classList.remove("drop-target");n.kind==="node"&&((g=n.el)==null||g.classList.remove("dragging"));const h=n.kind==="pan"&&n.moved||(M==null?void 0:M.moved)===!0;K.style.display="none",M=null,n={kind:"none"},b!==void 0&&u.revert(b)&&Se(),h&&N(),b=void 0;try{E.releasePointerCapture(a.pointerId??0)}catch{}}function Ve(a){O.isMenuOpen()&&O.closeMenu();const h=_e(a);if(a.shiftKey&&!a.ctrlKey){const g=a.deltaMode===1?16:1;s=Nt(un(s,(a.deltaX??0)*g,(a.deltaY??0)*g))}else{const g=a.deltaMode===1?16:1,F=Math.exp(-((a.deltaY??0)*g)*.0015);s=Xn(s,F,h.x,h.y)}a.preventDefault(),Qe(),N()}function pe(a){Je(),s=Xn(s,a,qe/2,ut/2),Qe(),N()}function Oe(){u.undo()?(N(),Se()):L("info","没有可撤销的布局改动")}function it(){Je(),s=qn(Un(t.contentBounds(),t.allNodes()),qe,ut,zn(we,q)),Qe(),N()}function It(a){var ue,W,B,z,ie,Ae,Le;if(O.isDialogOpen()||((W=(ue=a.target)==null?void 0:ue.closest)==null?void 0:W.call(ue,".p-search"))!==null)return;if((a.ctrlKey||a.metaKey)&&a.key.toLowerCase()==="k"){a.preventDefault(),Re.focus();return}if((a.ctrlKey||a.metaKey)&&!a.shiftKey&&a.key.toLowerCase()==="z"){a.preventDefault(),Oe();return}if(a.ctrlKey||a.metaKey)return;if(O.isMenuOpen()){a.key==="Escape"&&(O.closeMenu(),a.preventDefault());return}if(a.key===" "&&a.target===E){i=!0,a.preventDefault();return}const h=((z=(B=a.target)==null?void 0:B.closest)==null?void 0:z.call(B,".p-frame-head"))??null;if((a.key==="Enter"||a.key===" ")&&h!==null){a.preventDefault();const Ne=h.getBoundingClientRect();O.contextMenuAt(Ne.left+Ne.width/2,Ne.top+Ne.height/2,h);return}if(a.key===" "&&((Ae=(ie=a.target)==null?void 0:ie.classList)!=null&&Ae.contains("p-node"))){const Ke=a.target.dataset.id??"",v=t.selectedIds();t.setSelection(v.includes(Ke)?v.filter(be=>be!==Ke):[...v,Ke]),Se(),a.preventDefault();return}if(a.key==="F10"&&a.shiftKey||a.key==="ContextMenu"){a.preventDefault();const Ne=document.activeElement??null,Ke=((Le=Ne==null?void 0:Ne.getBoundingClientRect)==null?void 0:Le.call(Ne))??{left:0,top:0,width:0,height:0};O.contextMenuAt(Ke.left+Ke.width/2,Ke.top+Ke.height/2,Ne);return}if(a.key==="Delete"||a.key==="Backspace"){a.preventDefault(),cn();return}if(a.altKey&&(a.key==="ArrowUp"||a.key==="ArrowDown")){a.preventDefault(),ko(a.key==="ArrowUp");return}if(a.key==="g"||a.key==="G"){O.startCreateFromSelection();return}if(a.key==="0"){it();return}if(a.key==="="||a.key==="+"){pe(1.2);return}if(a.key==="-"){pe(1/1.2);return}if(a.key==="Escape"){if(O.isMenuOpen()){O.closeMenu(),Se();return}t.setSelection([]),Se();return}const g=a.shiftKey?40:8,P={ArrowLeft:[-g,0],ArrowRight:[g,0],ArrowUp:[0,-g],ArrowDown:[0,g]}[a.key];if(P!==void 0){a.preventDefault();const Ne=t.selectedIds();if(Ne.length>0){const Ke=u.capture();t.nudge(Ne,P[0],P[1]),u.commit(Ke),Se(),N()}}}function cn(){var F,P,ue;const a=document.activeElement,h=((F=a==null?void 0:a.closest)==null?void 0:F.call(a,".p-frame-head"))??null,g=((P=a==null?void 0:a.closest)==null?void 0:P.call(a,".p-node"))??null;if(h!==null){$({type:"remove-team",name:h.dataset.frame??""});return}if(g!==null){const W=g.dataset.id??"",B=((ue=t.getNode(W))==null?void 0:ue.memberships.map(z=>z.team))??[];if(B.length===0){L("info","该节点未加入任何团队");return}if(B.length===1){$({type:"remove-member",team:B[0],ids:[W]});return}O.openMenu(window.innerWidth/2,window.innerHeight/2,{kind:"node",id:W},"leave",g);return}L("info","焦点不在节点或团队框上")}function ko(a){var Ae,Le;const h=document.activeElement,g=((Ae=h==null?void 0:h.closest)==null?void 0:Ae.call(h,".p-node"))??null;if(g===null)return;const F=g.dataset.id??"",P=((Le=t.getNode(F))==null?void 0:Le.memberships)??[];if(P.length!==1)return;const ue=P[0].team,W=t.teamMemberIds(ue),B=W.indexOf(F),z=a?Math.max(0,B-1):Math.min(W.length-1,B+1);if(z===B)return;const ie=[...W];ie.splice(B,1),ie.splice(z,0,F),$({type:"reorder",team:ue,ops:vn(W,ie)})}function Mn(a){a.key===" "&&(i=!1)}E.addEventListener("pointerdown",a=>Pe(a),S),E.addEventListener("pointermove",a=>Ze(a),S),E.addEventListener("pointerup",a=>et(a),S),E.addEventListener("pointercancel",a=>pt(a),S),E.addEventListener("wheel",a=>Ve(a),{...S,passive:!1}),E.addEventListener("keydown",a=>It(a),S),E.addEventListener("keyup",a=>Mn(a),S),E.addEventListener("contextmenu",a=>{var g,F;const h=a;if(((F=(g=h.target)==null?void 0:g.closest)==null?void 0:F.call(g,"input, textarea, .p-search"))==null){if(h.preventDefault(),C){C=!1;return}O.contextMenuAt(h.clientX,h.clientY,h.target)}},S);let Ht=[];function Eo(a){var Ke;Ht=a.teams,k=new Set([...a.teams.filter(v=>v.kind==="roster").map(v=>v.name),...[...k].filter(v=>Te.has(v))]),a.peers,d.setInFlight(a.inFlight??[]),se=a.sessions,O.setUnjoined(a.sessions.filter(v=>v.joined!==!0&&!v.id.startsWith("peer-")));const h=Ss(a.teams);ae=new Set(h.keys());const g=new Set,F=v=>{const be=h.get(v)??[];if(Te.size===0)return be;const he=be.filter($e=>!Te.has($e.team)),je=[];for(const[$e]of Te){const Fe=t.teamMemberIds($e).indexOf(v);Fe>=0&&je.push({team:$e,index:Fe})}return[...he,...je]};let P;if(o===void 0&&!t.allNodes().some(v=>v.remote!==!0)){const v=a.sessions.filter(be=>{var he;return be.joined===!0&&(F(be.id).length>0||(((he=be.teams)==null?void 0:he.length)??0)>0)}).map(be=>be.id);Je(),P=ds(a.teams,v,qe>0?qe:void 0)}const ue=a.peerOrg!==void 0?As(a.peerOrg,a.sessions,a.remoteTeams):new Set;a.peerOrg!==void 0&&(ae=new Set([...ae,...ue]));for(const v of a.sessions){if(v.joined!==!0)continue;const be=F(v.id);if(!(be.length===0&&(v.teams===void 0||v.teams.length===0)&&!ue.has(v.id)))if(g.add(v.id),t.getNode(v.id)!==void 0)t.upsertNode({id:v.id,x:t.getNode(v.id).x,y:t.getNode(v.id).y,label:v.label,team:v.team,name:v.name,description:v.description,live:v.live!==!1,memberships:be,...v.teams!==void 0&&v.teams.length>0?{teams:v.teams}:{}});else{const he=o==null?void 0:o.nodes[v.id];let je,$e;if(he!==void 0)je=he.x,$e=he.y;else{const oe=(P==null?void 0:P.get(v.id))??Sn(v.id);je=oe.x,$e=oe.y}t.upsertNode({id:v.id,x:je,y:$e,label:v.label,team:v.team,name:v.name,description:v.description,live:v.live!==!1,memberships:be,...v.teams!==void 0&&v.teams.length>0?{teams:v.teams}:{}})}}for(const v of t.nodeIds())!g.has(v)&&!v.startsWith("peer-")&&!v.startsWith("member-")&&t.removeNode(v);const W=new Set;A=bs(a.remoteTeams??[]),me=new Map([...A].flatMap(([v,be])=>be.map(he=>[he.team,v]))),I=new Map(a.sessions.map(v=>[v.id,{status:v.status,queued:v.queued}])),w=to(a),Q.clear();for(const v of a.peers??[])Q.set(dt(v.url),v.score),X.set(dt(v.url),{link:v.link,verified:v.verified});if(a.peers!==void 0){const v=t.contentBounds(),be=xs(a.peers,v);a.peers.forEach((he,je)=>{var wt,An,Ln,In;const $e=hs(he.url);W.add($e);const oe=o==null?void 0:o.nodes[$e],Fe=t.getNode($e),Ge=Fe!==void 0?{x:Fe.x,y:Fe.y}:oe!==void 0?{x:oe.x,y:oe.y}:{x:((wt=be[je])==null?void 0:wt.x)??200,y:((An=be[je])==null?void 0:An.y)??0},rt=dt(he.url),yt=(In=(Ln=A.get(rt))==null?void 0:Ln.find(Io=>Io.team.includes("/")))==null?void 0:In.team;t.upsertNode({id:$e,x:Ge.x,y:Ge.y,label:he.url,team:"",name:he.url,peerUrl:he.url,remoteHandle:yt,live:!0,remote:!0,memberships:[]}),t.upsertScore($e,he.score)})}for(const v of t.nodeIds())v.startsWith("peer-")&&!W.has(v)&&t.removeNode(v);const B=new Set;for(const[v,be]of A){const he=t.allNodes().find(oe=>oe.remote===!0&&dt(oe.peerUrl??"")===v&&!oe.id.startsWith("member-")),je=((he==null?void 0:he.x)??400)+190;let $e=(he==null?void 0:he.y)??0;for(const oe of be){if(!oe.team.includes("/"))continue;const Fe=`member-${oe.team.replace(/[^a-z0-9-]/gi,"-")}`;if(B.has(Fe))continue;B.add(Fe);const Ge=o==null?void 0:o.nodes[Fe],rt=t.getNode(Fe),yt=rt!==void 0?{x:rt.x,y:rt.y}:Ge!==void 0?{x:Ge.x,y:Ge.y}:{x:je,y:$e};$e+=92,t.upsertNode({id:Fe,x:yt.x,y:yt.y,label:oe.team,team:oe.team,name:oe.name!==void 0&&oe.name!==""?oe.name:oe.team,remoteHandle:oe.team,live:!0,remote:!0,memberships:[]})}}for(const v of t.nodeIds())v.startsWith("member-")&&!B.has(v)&&t.removeNode(v);const z=new Map;for(const v of t.allNodes())v.remote!==!0||v.remoteHandle===void 0||v.remoteHandle===""||(!z.has(v.remoteHandle)||v.id.startsWith("member-"))&&z.set(v.remoteHandle,v.id);for(const v of a.teams){if(Te.has(v.name))continue;const be=[];for(const $e of v.members){const oe=z.get($e.id)??$e.id;t.getNode(oe)!==void 0&&be.push(oe)}const he=[...t.teamMemberIds(v.name)].sort().join("|"),je=[...be].sort().join("|");he!==je&&t.setTeamMembers(v.name,be)}const ie=new Map,Ae=nt;if(nt=ie,a.peerOrg!==void 0){let v=0;const be=new Set(a.teams.map(he=>he.name));H.sweep(a.peerOrg);for(const he of a.peerOrg){const je=new Set((a.remoteTeams??[]).map(oe=>oe.team)),$e=wo(a.sessions,je);for(const oe of he.org){if(oe.name===""||be.has(oe.name)||H.hides(oe.name,he.url))continue;const Fe=oe.members.map(rt=>Ms(rt,$e,a.remoteTeams,he.url)).filter(rt=>t.getNode(rt)!==void 0),Ge=(Ke=o==null?void 0:o.frames)==null?void 0:Ke[oe.name];t.getFrame(oe.name)===void 0&&t.setFrame(oe.name,Ge!==void 0?{x:Ge.x,y:Ge.y,w:Ge.w,h:Ge.h}:{x:200+v%4*280,y:940+Math.floor(v/4)*160,w:250,h:130}),t.setTeamMembers(oe.name,Fe),ie.set(oe.name,he.url),v+=1}}}for(const[v,be]of Ae)ie.has(v)||t.removeFrame(v);const Le=new Map;for(const v of t.allNodes())v.remote===!0&&v.remoteHandle!==void 0&&v.remoteHandle!==""&&Le.set(v.remoteHandle,v.id);const Ne=go(a.teams);for(const v of a.teams){if(t.getFrame(v.name)!==void 0||Te.has(v.name))continue;const be=o==null?void 0:o.frames[v.name];if(be!==void 0){t.setFrame(v.name,{...be});continue}const he=[],je=[];for(const oe of v.members){const Fe=t.getNode(Le.get(oe.id)??oe.id);Fe!==void 0&&(je.push(mt(Fe)),Ne.get(Fe.id)===v.name&&he.push(mt(Fe)))}const $e=he.length>0?he:je;$e.length>0&&t.setFrame(v.name,En($e))}for(const[v]of t.allFrames())Te.has(v)||!a.teams.some(be=>be.name===v)&&!ie.has(v)&&t.removeFrame(v);if(Z.refresh(),We(a),!l&&n.kind==="none"&&t.nodeIds().length>0){l=!0;const v=u.capture();qt(t,new Set(nt.keys())),u.commit(v)}c&&n.kind==="none"&&t.nodeIds().length>0&&(Je(),qe>0&&ut>0&&(c=!1,s=qn(Un(t.contentBounds(),t.allNodes()),qe,ut,zn(we,q)))),Se()}function Sn(a){return vo(a,t.allNodes().filter(h=>h.remote!==!0))}function No(a){const h=ho(a);if(h===void 0)return;o=h;const g=e.viewportStore;if(g===void 0)c=!1,n.kind==="none"&&(s=Nt({...h.viewport}));else if(!m&&n.kind==="none"){m=!0;const F=g.get(x());F!=null&&Number.isFinite(F.x)&&Number.isFinite(F.y)&&Number.isFinite(F.scale)?(s=Nt({x:F.x,y:F.y,scale:F.scale}),c=!1):x()==="wide"&&(s=Nt({...h.viewport}),c=!1)}r=-1,Se()}function $o(){return rs(s,t.positions(),t.frameRects())}function Mo(a,h){le.classList.remove("pending","saved","error"),a==="pending"&&le.classList.add("pending"),a==="saved"&&le.classList.add("saved"),a==="error"&&le.classList.add("error"),a==="error"?(le.tabIndex=0,le.setAttribute("role","button"),le.setAttribute("aria-label","布局保存失败,按回车重试")):(le.removeAttribute("tabindex"),le.removeAttribute("role"),le.removeAttribute("aria-label"));const g=a==="pending"?"布局待保存…":a==="saved"?`布局已保存 ${h??""}`.trimEnd():a==="error"?"保存失败 · 回车重试":"布局";fe.textContent=g}function So(){E.style.display="block",Je(),Qe(),E.focus()}function Ao(){E.style.display="none"}function Lo(){re.abort();for(const a of V)clearTimeout(a)}return{root:E,reconcile:Eo,activate:So,deactivate:Ao,adoptExternalLayout:No,snapshotDoc:$o,setLamp:Mo,notice:L,destroy:Lo,seam:{pointerDown:Pe,pointerMove:Ze,pointerUp:et,pointerCancel:pt,wheel:Ve,key:It,keyUp:Mn,contextMenu(a){a.preventDefault(),O.contextMenuAt(a.clientX,a.clientY,a.target)}}}}const wi=800;function xi(e){let t,o=!1,s=!1,n=!1,i="idle";function r(b){b!==i&&(i=b,e.onLamp(b))}function c(){t!==void 0&&(t(),t=void 0)}function l(){c(),t=e.schedule(()=>{t=void 0,u(!1)},wi)}async function u(b){if(o){s=!0;return}o=!0,c();const m=e.snapshot();let x;try{x=JSON.stringify(m)}catch{o=!1,r("error"),e.onHttpError("layout document is not JSON-serializable");return}try{const N=await e.send(m,{keepalive:b});if(N===null||typeof N!="object"||N.ok!==!0){r("error");const Y=N!==null&&typeof N=="object"&&typeof N.error=="string"?N.error:"layout save refused";e.onHttpError(`layout save: ${Y}`)}else JSON.stringify(e.snapshot())===x&&(e.onAdopt(N.layout),r("saved"))}catch(N){r("error"),e.onHttpError(`layout save unreachable: ${String((N==null?void 0:N.message)??N).slice(0,80)}`)}if(o=!1,i==="error"){n=!1;return}if(n){n=!1,u(!0);return}s&&(s=!1,r("pending"),l())}return{markDirty(){if(s=!1,r("pending"),o){s=!0;return}l()},retry(){i!=="error"||o||(r("pending"),u(!1))},flush(){if(o){n=!0,s=!0;return}c(),u(!0)},isBusy(){return o},dispose(){c()}}}function no(e){return e!=null&&typeof e.error=="string"?e.error:void 0}function Ci(e){const t=new Map;let o=0;function s(r,c){o+=1;const l=t.get(r)??Promise.resolve(),u=async()=>{try{return await c()}finally{o-=1}},b=l.then(u,u);return t.set(r,b.then(()=>{},()=>{})),b}async function n(r){var re,V,M,C;let c;try{c=await e.send(r)}catch(S){const E=String((S==null?void 0:S.message)??S).slice(0,80);return e.onNotice("error",`画布不可达:${E}`),!1}if(c.status>=400)return e.onNotice("error",no(c.body)??`HTTP ${c.status}`),!1;if(((re=c.body)==null?void 0:re.ok)===!0)return!0;const l=c.body!=null&&typeof c.body=="object"?no(c.body):void 0;if(l!==void 0)return e.onNotice("error",l),!1;const u=String(r.name??""),b=String(r.id??""),m=(V=c.body)==null?void 0:V.members,x=(M=c.body)==null?void 0:M.teams,N=Array.isArray(m)&&m.every(S=>typeof S=="string"),Y=Array.isArray(x)&&x.every(S=>typeof S=="string");return((C=c.body)==null?void 0:C.ok)===!1&&(r.action==="add-member"&&N&&m.includes(b)||r.action==="remove-member"&&N&&!m.includes(b)||r.action==="remove"&&Y&&!x.includes(u))?!0:(e.onNotice("error","画布操作未确认:"+String(r.action)+"(可能队伍/成员已达上限,请重试)"),!1)}async function i(r,c){for(const l of c)if(!await n({...r,id:l}))return!1;return!0}return{createTeam(r,c){return s(r,async()=>{if(!await n({action:"create",name:r}))return!1;for(let l=0;l<c.length;l++)if(!await n({action:"add-member",name:r,id:c[l]}))return!1;return!0})},addMembers(r,c){return s(r,()=>i({action:"add-member",name:r},c))},removeMembers(r,c){return s(r,()=>i({action:"remove-member",name:r},c))},runRosterOps(r,c){return s(r,async()=>{for(const l of c){const u=l.op==="remove"?{action:"remove-member",name:r,id:l.id}:{action:"add-member",name:r,id:l.id};if(!await n(u))return!1}return!0})},removeTeam(r){return s(r,()=>n({action:"remove",name:r}))},hasPending(){return o>0}}}const Co=document.getElementById("app"),ki=(()=>{try{return window.sessionStorage.getItem("dsh_a2a_key")??""}catch{return""}})(),yn=window.__DSH_A2A_KEY__??ki,ze=(e,t={})=>fetch(e,{...t,headers:{...t.headers??{},...yn!==""?{"X-API-Key":yn}:{}}});yn===""&&ze("/__dsh_a2a/owner-settings").then(e=>{if(e.status!==401)return;const t=document.createElement("div");t.className="nexus-keygate",t.style.cssText="position:fixed;inset:0;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:10px;background:#fff;z-index:9999;font:14px/1.5 system-ui,sans-serif;color:#000";const o=document.createElement("div");o.textContent="此面板经远程面打开(密钥不随页面下发)——输入控制密钥";const s=document.createElement("input");s.type="password",s.placeholder="X-API-Key",s.setAttribute("aria-label","控制密钥");const n=document.createElement("button");n.type="button",n.textContent="进入面板";const i=document.createElement("div");i.style.color="#b00";const r=()=>{const c=s.value.trim();c!==""&&fetch("/__dsh_a2a/owner-settings",{headers:{"X-API-Key":c}}).then(l=>{if(l.status===401){i.textContent="密钥不对,再试一次";return}try{window.sessionStorage.setItem("dsh_a2a_key",c)}catch{}window.location.reload()})};n.addEventListener("click",r),s.addEventListener("keydown",c=>{c.key==="Enter"&&r()}),t.append(o,s,n,i),document.body.appendChild(t)});const Pt=document.createElement("div");Pt.className="nexus-fault";Co.appendChild(Pt);const{fault:wn,clear:Ei}=Oo({show(e){Pt.textContent=e,Pt.style.display="block"},hide(){Pt.style.display="none"}},e=>console.error(e));let Qt;const oo="dsh-a2a.viewport.",Ni={get(e){try{const t=window.localStorage.getItem(oo+e);return t===null?void 0:JSON.parse(t)}catch{return}},set(e,t){try{window.localStorage.setItem(oo+e,JSON.stringify({x:t.x,y:t.y,scale:t.scale}))}catch{}}},st=yi({viewportStore:Ni,onDirty:()=>on.markDirty(),onLampClick:()=>on.retry(),onNodePick:e=>{Qt==null||Qt(e)},onCanvasAction:async e=>{const t=await Mi(e);return an(),t}}),on=xi({snapshot:()=>st.snapshotDoc(),send:(e,t)=>ze("/__dsh_a2a/canvas-layout",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"save",layout:e}),cache:"no-store",keepalive:t.keepalive}).then(async o=>await o.json()),schedule:(e,t)=>{const o=setTimeout(e,t);return()=>{clearTimeout(o)}},now:Date.now,onLamp:e=>{xn=e;const t=new Date,o=String(t.getHours()).padStart(2,"0")+":"+String(t.getMinutes()).padStart(2,"0");st.setLamp(e,o)},onAdopt:e=>{st.adoptExternalLayout(e)},onHttpError:e=>wn(e)});window.addEventListener("pagehide",()=>on.flush());const Ot=Ci({send:async e=>{const t=await ze("/__dsh_a2a/canvas",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),cache:"no-store"});return{status:t.status,body:await t.json()}},onNotice:(e,t)=>st.notice(e,t)});async function so(e,t,o,s){const n=await ze("/__dsh_a2a/fleet-canvas-op",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({peer:e,op:t,name:o,...s!==void 0?{id:s}:{}}),cache:"no-store"}).catch(()=>{}),i=n!==void 0?await n.json().catch(()=>{}):void 0;return(i==null?void 0:i.ok)===!0&&t==="remove"&&i.removed===!1&&st.notice("info",`属主那边已没有「${o}」,无需解散`),(i==null?void 0:i.ok)===!0?!0:(st.notice("error",`跨主机团队操作失败:${String((i==null?void 0:i.error)??"对端无响应")}`),!1)}async function $i(e,t){const o=async s=>{const n=await ze("/__dsh_a2a/roster-op",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:t,...s})}).catch(()=>{}),i=n!==void 0?await n.json().catch(()=>{}):void 0;return n!=null&&n.ok&&(i==null?void 0:i.ok)===!0?!0:(st.notice("error",`roster 操作失败:${String((i==null?void 0:i.error)??(n?`HTTP ${n.status}`:"无响应"))}`),!1)};if(e.type==="create-team")return o({op:"create",ids:e.ids});if(e.type==="remove-team")return o({op:"dissolve"});if(e.type==="add-member"||e.type==="remove-member"){for(const s of e.ids)if(!await o({op:e.type,id:s}))return!1;return!0}return st.notice("error","roster 不支持该操作"),!1}function Mi(e){if((e.type==="add-member"||e.type==="remove-member")&&e.fleetPeer!==void 0){const t=e.fleetPeer;return(async()=>{for(const o of e.ids)if(!await so(t,e.type,e.team,o))return!1;return!0})()}if(e.type==="remove-team"&&e.fleetPeer!==void 0)return so(e.fleetPeer,"remove",e.name);if(e.roster===!0){const t=xo(Rt(e));return t!==void 0?$i(e,t):(st.notice("error","无效的 roster 框名"),Promise.resolve(!1))}switch(e.type){case"create-team":return Ot.createTeam(e.name,e.ids,e.created);case"add-member":return Ot.addMembers(e.team,e.ids);case"remove-member":return Ot.removeMembers(e.team,e.ids);case"remove-team":return Ot.removeTeam(e.name);case"reorder":return Ot.runRosterOps(e.team,e.ops);case"join-network":case"leave-network":return Si(e.type==="join-network"?"join":"leave",e.id)}}async function Si(e,t){const o=await ze(`/__dsh_a2a/${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:t}),cache:"no-store"}).catch(()=>{});return o!==void 0&&o.ok}let xn="idle",fn=new Set,io=0,sn=!1,ro,pn=!1;async function Ai(){const e=await ze("/__dsh_a2a/canvas-layout",{cache:"no-store"});if(!e.ok)throw new Error(`/__dsh_a2a/canvas-layout ${e.status}`);return(await e.json()).layout??null}const rn=ss({now:()=>Date.now(),async ownerSettingsRead(){try{return await(await ze("/__dsh_a2a/owner-settings")).json()}catch{return{ok:!1,error:"unreachable"}}},async ownerSettingsWrite(e){try{return await(await ze("/__dsh_a2a/owner-settings",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})).json()}catch{return{ok:!1,error:"unreachable"}}},async abandon(e,t){try{return(await ze("/__dsh_a2a/tasks/abandon",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({task_id:e,reason:t})})).ok}catch{return!1}},copy(e){var t;(t=navigator.clipboard)==null||t.writeText(e).catch(()=>{})},async cliHomeOptions(e,t){try{const o=await ze("/__dsh_a2a/canvas",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({action:"cli-home-options",name:e,id:t})}),s=await o.json();return{...s,ok:o.ok&&s.ok===!0}}catch(o){return{ok:!1,error:String(o)}}},async canvasOp(e,t,o,s){try{const n=await ze("/__dsh_a2a/canvas",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({action:e,name:t,id:o,...s===void 0?{}:{home:s}})}),i=await n.json().catch(()=>({}));return n.ok&&i.ok!==!1?!0:(console.warn(`canvas ${e} ${t}: ${i.error??`HTTP ${n.status}`}`),!1)}catch{return!1}},async dispatchQuick(e,t){try{const o=await ze("/__dsh_a2a/dispatch",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({team:e,message:t})}),s=await o.json().catch(()=>({}));return{ok:o.ok&&s.ok===!0,task_id:s.task_id,reply:s.reply,error:s.error??`HTTP ${o.status}`}}catch(o){return{ok:!1,error:o instanceof Error?o.message:String(o)}}},async sessionLog(e){try{const t=await ze(`/__dsh_a2a/session-log?id=${encodeURIComponent(e)}`),o=await t.json().catch(()=>({}));return{ok:t.ok&&o.ok===!0,messages:o.messages,error:o.error??(t.ok?void 0:`HTTP ${t.status}`)}}catch(t){return{ok:!1,error:t instanceof Error?t.message:String(t)}}},async sessionLogList(){try{const e=await ze("/__dsh_a2a/session-log"),t=await e.json().catch(()=>({}));return{ok:e.ok&&t.ok===!0,sessions:t.sessions,count:typeof t.count=="number"?t.count:void 0,error:t.error??(e.ok?void 0:`HTTP ${e.status}`)}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}},async remoteSessionLog(e){try{const t=new URLSearchParams;e.team!==void 0&&t.set("team",e.team),e.peer!==void 0&&t.set("peer",e.peer),e.id!==void 0&&t.set("id",e.id),e.limit!==void 0&&t.set("limit",String(e.limit));const o=await ze(`/__dsh_a2a/remote-session-log?${t.toString()}`),s=await o.json().catch(()=>({}));return{ok:o.ok&&s.ok===!0,messages:s.messages,sessions:s.sessions,error:s.error??(o.ok?void 0:`HTTP ${o.status}`),via:s.via}}catch(t){return{ok:!1,error:t instanceof Error?t.message:String(t)}}},board:{root:st.root,activate:()=>st.activate(),deactivate:()=>st.deactivate(),available:()=>sn}});Co.appendChild(rn.root);Qt=e=>{rn.openNodeChat(e)};if(new URLSearchParams(window.location.search).get("mode")==="plan"){const e=window.setInterval(()=>{sn&&(rn.selectTab("board"),window.clearInterval(e))},300);window.setTimeout(()=>window.clearInterval(e),3e4)}async function an(){var e,t;try{const o=await ze("/__dsh_a2a/state",{cache:"no-store"});if(!o.ok)throw new Error(`/__dsh_a2a/state ${o.status}`);const s=await o.json();if(Date.now()-io>=15e3){io=Date.now();try{const m=await ze("/__dsh_a2a/nodes",{cache:"no-store"});if(!m.ok)throw new Error(`nodes ${m.status}`);const x=await m.json();fn=new Set((x.bindings??[]).filter(N=>N.mounted!==null&&N.effective!==null&&(N.effective.core===!1||N.effective.mutable===!1)).map(N=>N.session))}catch{fn.clear()}}const n={...s,sessions:(s.sessions??[]).map(m=>({...m,...fn.has(m.id)?{nodePromptMissing:!0}:{}}))};if(Ei(),sn=s.canvas!==void 0,rn.update(n),sn)try{const m=await Ai(),x=JSON.stringify(m??null);x!==ro&&(ro=x,(xn==="idle"||xn==="saved")&&!on.isBusy()&&st.adoptExternalLayout(m)),pn=!0}catch(m){if(!pn){wn(`canvas layout 获取失败:${String(m)}`);return}}else pn=!0;const i=(s.sessions??[]).map(m=>({...m,joined:m.joined===!0})),r=[...((e=s.canvas)==null?void 0:e.teams)??[],...Ds(((t=s.registry)==null?void 0:t.teams)??[],s.zone??"")],c=(s.peers??[]).filter(m=>m!==null&&typeof m=="object"&&typeof m.url=="string"),l=(s.inFlight??[]).filter(m=>m!==null&&typeof m=="object"&&typeof m.team=="string"&&typeof m.peer=="string"&&Number.isFinite(m.startedAt)),u=(s.remote??[]).filter(m=>m!==null&&typeof m=="object"&&typeof m.team=="string"&&typeof m.via=="string").map(m=>({team:m.team,name:m.name,via:m.via,workspace:m.workspace,...m.unreachable===!0?{unreachable:!0}:{},...typeof m.origin=="string"&&m.origin!==""?{origin:m.origin}:{},...Array.isArray(m.teams)&&m.teams.length>0?{teams:m.teams.filter(x=>typeof x=="string"&&x!=="")}:{}})),b=(s.peerOrg??[]).filter(m=>m!==null&&typeof m=="object").filter(m=>typeof m.url=="string"&&Array.isArray(m.org)).map(m=>({url:m.url,...m.unreachable===!0?{unreachable:!0}:{},org:m.org.filter(x=>x!==null&&typeof x=="object").filter(x=>typeof x.team=="string"&&x.team!=="").map(x=>({name:typeof x.name=="string"?x.name:"",team:x.team,members:Array.isArray(x.members)?x.members.filter(N=>typeof N=="string"):[]}))}));st.reconcile({sessions:i,teams:r,peerCount:c.length,peers:c,inFlight:l,remoteTeams:u,peerOrg:b})}catch(o){wn(`state 轮询失败:${String(o)}`)}}an();window.setInterval(()=>{document.hidden||an()},3e3);document.addEventListener("visibilitychange",()=>{document.hidden||an()});