dsh-plugin-t-expert 0.1.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -33
- package/THIRD-PARTY-NOTICES +24 -13
- package/cordis.patch.yml +1 -1
- package/data/source.json +1 -1
- package/data/team-profiles.py +1 -1
- package/data/teams.json +1 -1
- package/data/zh/manual.json +1 -1
- package/lib/catalog.js +1 -1
- package/lib/client.js +111 -65
- package/lib/i18n.js +4 -4
- package/lib/index.js +124 -50
- package/lib/plan-check.js +3 -1
- package/lib/teams/capabilities.js +1 -1
- package/lib/teams/index.js +1 -1
- package/lib/teams/quality-gates.js +4 -5
- package/lib/teams/tools.js +6 -3
- package/package.json +10 -12
- package/vendor/dsh-agent-teams/LICENSE +21 -0
- package/vendor/dsh-agent-teams/VENDOR.md +53 -0
- package/vendor/third-party-licenses/README.md +22 -0
- package/vendor/third-party-licenses/agency-agents-zh.LICENSE +22 -0
- package/vendor/third-party-licenses/agency-agents.LICENSE +21 -0
package/lib/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// T专家 client bundle — 由
|
|
1
|
+
// T专家 client bundle — 由 build-client.mjs(运维目录)生成,勿手改。
|
|
2
2
|
window.__ModuleLoader__.load({
|
|
3
3
|
id: "dsh-plugin-t-expert",
|
|
4
4
|
factory: (require) => {
|
|
@@ -19716,7 +19716,7 @@ function date4(params) {
|
|
|
19716
19716
|
return _coercedDate(ZodDate, params);
|
|
19717
19717
|
}
|
|
19718
19718
|
|
|
19719
|
-
//
|
|
19719
|
+
// inlined team-engine client bundle
|
|
19720
19720
|
var client_bundle_default = 'window.__ModuleLoader__.load({\n id: "dsh-plugin-t-expert",\n factory: (require) => {\n var module = { exports: {} };\n var exports = module.exports;\n Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });\n let react_jsx_runtime = require("react/jsx-runtime");\n let react = require("react");\n let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");\n /** Compact `provider/model` route, or just the model when the provider is absent. */\n function memberRouteLabel(member) {\n if (member === void 0) return "";\n const provider = member.provider?.trim() ?? "";\n const model = member.model?.trim() ?? "";\n if (provider !== "" && model !== "") return `${provider}/${model}`;\n return model;\n }\n /**\n * Compact route shown on a running task. Prefer the task\'s own snapshot\n * field; fall back to the assignee member when older hosts omit it.\n */\n function taskModelLabel(task, members) {\n const direct = task.model?.trim() ?? "";\n if (direct !== "") return direct;\n return memberRouteLabel(members.find((candidate) => candidate.name === task.assignee));\n }\n /** Short model id for tight DAG/chip surfaces (`openai/gpt-5.6-sol` \u2192 `gpt-5.6-sol`). */\n function compactModelLabel(route) {\n const trimmed = route.trim();\n if (trimmed === "") return "";\n const slash = trimmed.lastIndexOf("/");\n return slash === -1 ? trimmed : trimmed.slice(slash + 1);\n }\n /** Whether the captain chat should keep showing the in-progress banner. */\n function teamIsActive(team) {\n if (team.halted === true || team.phase === "staged") return false;\n if (team.members.some((member) => member.activity === "working" || member.status === "working")) return true;\n if (team.tasks.some((task) => task.status === "pending" || task.status === "claimed" || task.status === "in_progress")) return true;\n return team.members.length > 0 && team.tasks.length === 0;\n }\n /** Use a fill-width grid when the task graph has no real dependency edges. */\n function usesParallelTaskGrid(tasks) {\n if (tasks.length === 0) return false;\n const taskIds = new Set(tasks.map((task) => task.id));\n return tasks.every((task) => task.dependencies.every((dependency) => !taskIds.has(dependency)));\n }\n /**\n * Whether an expanded activity panel still belongs to the current session.\n *\n * The panel is mounted in the root-scoped shell overlay, so React does not\n * remount it when the conversation route changes. Ownership keeps an expanded\n * panel from leaking onto the new-session screen (or another conversation)\n * while its local open state is being reset.\n */\n function activityPanelExpandedForSession(open, owner, current) {\n return open && owner !== void 0 && owner === current;\n }\n /**\n * Auto-expand only for live teams that appear after the current session\'s\n * initial restore pass. Replayed cards, archived teams, and live teams restored\n * while reopening a conversation must remain behind the collapsed badge.\n */\n function activityPanelShouldAutoExpand({ alreadyAutoOpened, pageSettled, restoreComplete, previousLiveTeamIds, currentLiveTeamIds }) {\n return !alreadyAutoOpened && pageSettled && restoreComplete && currentLiveTeamIds.some((teamId) => !previousLiveTeamIds.has(teamId));\n }\n /**\n * Resolve the task whose dependency chain should be highlighted.\n *\n * A pinned task is an explicit user choice. Keyboard focus takes precedence\n * over delayed pointer intent so an older hover timer cannot steal the active\n * chain from someone navigating the task map with the keyboard.\n */\n function dependencyFocusTaskId(pinnedTaskId, keyboardTaskId, hoverTaskId) {\n return pinnedTaskId ?? keyboardTaskId ?? hoverTaskId;\n }\n /** Group tasks by their precomputed dependency depth. */\n function taskStages(tasks) {\n const byDepth = /* @__PURE__ */ new Map();\n for (const task of tasks) {\n const depth = Number.isFinite(task.depth) ? Math.max(0, Math.floor(task.depth)) : 0;\n const stage = byDepth.get(depth) ?? [];\n stage.push(task);\n byDepth.set(depth, stage);\n }\n return [...byDepth.entries()].sort(([left], [right]) => left - right).map(([depth, stageTasks]) => ({\n depth,\n tasks: stageTasks.slice().sort((left, right) => left.id.localeCompare(right.id, "en", { numeric: true }))\n }));\n }\n /**\n * Lay tasks out as the reference panel\'s compact left-to-right DAG.\n *\n * Columns are dependency-depth stages. Rows are stable task-id order within\n * each stage. Edges use cubic curves so fan-in remains readable without\n * turning every task into a large card.\n */\n function compactDagLayout(tasks) {\n const stages = taskStages(tasks);\n const positions = /* @__PURE__ */ new Map();\n const nodes = [];\n for (const [column, stage] of stages.entries()) for (const [row, task] of stage.tasks.entries()) {\n const x = column * 118;\n const y = row * 38;\n positions.set(task.id, {\n x,\n y\n });\n nodes.push({\n task,\n x,\n y\n });\n }\n const edges = [];\n for (const task of tasks) {\n const target = positions.get(task.id);\n if (target === void 0) continue;\n for (const dependency of task.dependencies) {\n const source = positions.get(dependency);\n if (source === void 0) continue;\n const x1 = source.x + 92;\n const y1 = source.y + 30 / 2;\n const x2 = target.x;\n const y2 = target.y + 30 / 2;\n edges.push({\n from: dependency,\n to: task.id,\n path: `M${x1} ${y1}C${x1 + 14} ${y1},${x2 - 14} ${y2},${x2} ${y2}`\n });\n }\n }\n const rows = Math.max(1, ...stages.map((stage) => stage.tasks.length));\n return {\n width: stages.length === 0 ? 0 : stages.length * 92 + (stages.length - 1) * 26,\n height: stages.length === 0 ? 0 : rows * 30 + (rows - 1) * 8,\n nodes,\n edges\n };\n }\n /**\n * Return the complete upstream/downstream chain around one task.\n *\n * Traversal uses both dependency directions and remains cycle-safe, so the UI\n * can highlight every handoff related to the focused task even if malformed\n * durable data contains a cycle.\n */\n function relatedTaskIds(taskId, tasks) {\n const byId = new Map(tasks.map((task) => [task.id, task]));\n if (!byId.has(taskId)) return /* @__PURE__ */ new Set();\n const dependents = /* @__PURE__ */ new Map();\n for (const task of tasks) for (const dependency of task.dependencies) {\n const targets = dependents.get(dependency) ?? [];\n targets.push(task.id);\n dependents.set(dependency, targets);\n }\n const related = /* @__PURE__ */ new Set();\n const upstreamSeen = /* @__PURE__ */ new Set();\n const downstreamSeen = /* @__PURE__ */ new Set();\n const visitUpstream = (id) => {\n if (upstreamSeen.has(id)) return;\n upstreamSeen.add(id);\n related.add(id);\n for (const dependency of byId.get(id)?.dependencies ?? []) visitUpstream(dependency);\n };\n const visitDownstream = (id) => {\n if (downstreamSeen.has(id)) return;\n downstreamSeen.add(id);\n related.add(id);\n for (const dependent of dependents.get(id) ?? []) visitDownstream(dependent);\n };\n visitUpstream(taskId);\n visitDownstream(taskId);\n return related;\n }\n //#endregion\n //#region lib/client/activity-monitor.js\n /** Shared, demand-driven state for the T Team browser monitor. */\n const targets = /* @__PURE__ */ new Map();\n const targetListeners = /* @__PURE__ */ new Set();\n const snapshotListeners = /* @__PURE__ */ new Set();\n let targetSnapshot = [];\n let activitySnapshots = {\n teams: [],\n archivedTeams: []\n };\n function targetKey(sessionId, teamId) {\n return `${sessionId}\\u0000${teamId}`;\n }\n function publishTargets() {\n targetSnapshot = [...targets.values()].filter((target) => target.active).map(({ key, sessionId, teamId }) => ({\n key,\n sessionId,\n teamId\n }));\n for (const listener of targetListeners) listener();\n }\n /** Subscribe to the active monitor-target list (React external-store shape). */\n function subscribeActivityMonitorTargets(listener) {\n targetListeners.add(listener);\n return () => {\n targetListeners.delete(listener);\n };\n }\n /** Read the stable active-target snapshot. */\n function getActivityMonitorTargetsSnapshot() {\n return targetSnapshot;\n }\n /**\n * Register one successful T Team card as a monitoring demand.\n *\n * The returned cleanup is reference-counted so multiple cards and React\n * StrictMode remounts cannot stop another card\'s monitor.\n */\n function monitorAgentTeam(sessionId, teamId) {\n const owner = sessionId.trim();\n const id = teamId.trim();\n if (owner === "" || id === "") return () => {};\n const key = targetKey(owner, id);\n const existing = targets.get(key);\n if (existing === void 0) {\n targets.set(key, {\n key,\n sessionId: owner,\n teamId: id,\n refs: 1,\n active: true\n });\n publishTargets();\n } else {\n existing.refs += 1;\n if (!existing.active) {\n existing.active = true;\n publishTargets();\n }\n }\n let released = false;\n return () => {\n if (released) return;\n released = true;\n const current = targets.get(key);\n if (current === void 0) return;\n current.refs -= 1;\n if (current.refs <= 0) {\n targets.delete(key);\n if (current.active) publishTargets();\n }\n };\n }\n /** Stop polling targets whose final archived snapshot has been captured. */\n function settleActivityMonitorTargets(keys) {\n let changed = false;\n for (const key of keys) {\n const target = targets.get(key);\n if (target?.active !== true) continue;\n target.active = false;\n changed = true;\n }\n if (changed) publishTargets();\n }\n /** Subscribe to the shared live/archive snapshot. */\n function subscribeActivitySnapshots(listener) {\n snapshotListeners.add(listener);\n return () => {\n snapshotListeners.delete(listener);\n };\n }\n /** Read the stable shared live/archive snapshot. */\n function getActivitySnapshotsSnapshot() {\n return activitySnapshots;\n }\n /** Publish one or both successful state-route responses. */\n function updateActivitySnapshots(update) {\n const next = {\n teams: update.teams ?? activitySnapshots.teams,\n archivedTeams: update.archivedTeams ?? activitySnapshots.archivedTeams\n };\n if (next.teams === activitySnapshots.teams && next.archivedTeams === activitySnapshots.archivedTeams) return;\n activitySnapshots = next;\n for (const listener of snapshotListeners) listener();\n }\n /** Poll cadence for the live host snapshot route. */\n const ACTIVITY_POLL_MS = 1e3;\n /**\n * Low-frequency probe cadence while a cardless discovery session still owns\n * no team. The probe keeps the panel able to pick up a team created later in\n * that session (e.g. a run_code-wrapped t_team_create) without turning\n * every ordinary session into a one-second filesystem scan.\n */\n const ACTIVITY_PROBE_MS = 5e3;\n /** Host route serving live and archived team snapshots. */\n const ACTIVITY_STATE_URL = "/plugins/t-team/state";\n const ACTIVITY_HALT_URL = "/plugins/t-team/halt";\n /**\n * Start the single polling loop for the current session\'s requested targets.\n *\n * With neither targets nor a discovery session this is deliberately inert.\n * Explicit card targets poll at the live cadence from the start. A discovery\n * session performs an immediate live+archive restore pass, then \u2014 while it\n * still owns no team \u2014 probes on a low-frequency cadence, so a team created\n * later in that session (e.g. a run_code-wrapped t_team_create) is\n * discovered without a manual reload, without turning every ordinary session\n * into a one-second filesystem scan. The moment a team for the discovery\n * session appears, the controller upgrades to the live one-second cadence for\n * the rest of its lifetime. The caller \u2014 the session view, which stops the\n * controller when the session is no longer current \u2014 bounds the lifetime, and\n * archive state is refreshed when a target or a previously discovered live\n * team disappears.\n */\n function startActivityPolling(monitorTargets, runtime = {}) {\n const discoverySessionId = runtime.discoverySessionId?.trim();\n if (monitorTargets.length === 0 && (discoverySessionId === void 0 || discoverySessionId === "")) return {\n firstTick: Promise.resolve(),\n stop: () => {}\n };\n const fetchState = runtime.fetchState ?? ((url, init) => fetch(url, init));\n const schedule = runtime.schedule ?? ((callback, intervalMs) => setInterval(callback, intervalMs));\n const cancel = runtime.cancel ?? ((timer) => {\n clearInterval(timer);\n });\n const publishSnapshots = runtime.publishSnapshots ?? updateActivitySnapshots;\n const settleTargets = runtime.settleTargets ?? settleActivityMonitorTargets;\n let cancelled = false;\n let inFlight = false;\n let hot = monitorTargets.length > 0;\n let discoveryComplete = false;\n let discoveredLiveKeys = /* @__PURE__ */ new Set();\n let controller;\n let timer;\n const intervalMs = () => hot ? ACTIVITY_POLL_MS : ACTIVITY_PROBE_MS;\n const reschedule = () => {\n cancel(timer);\n timer = schedule(() => {\n tick();\n }, intervalMs());\n };\n const tick = async () => {\n if (inFlight || cancelled) return;\n inFlight = true;\n controller = new AbortController();\n try {\n const liveResponse = await fetchState(ACTIVITY_STATE_URL, {\n cache: "no-store",\n signal: controller.signal\n });\n if (!liveResponse.ok) return;\n const body = await liveResponse.json();\n if (cancelled || !Array.isArray(body.teams)) return;\n const liveTeams = body.teams;\n publishSnapshots({ teams: liveTeams });\n const previousDiscoveredKeys = discoveredLiveKeys;\n discoveredLiveKeys = new Set(discoverySessionId === void 0 || discoverySessionId === "" ? [] : liveTeams.filter((team) => team.captainSessionId === discoverySessionId).map((team) => team.teamId));\n if (!hot && discoveredLiveKeys.size > 0) {\n hot = true;\n reschedule();\n }\n const discoveredTeamArchived = [...previousDiscoveredKeys].some((teamId) => !discoveredLiveKeys.has(teamId));\n const missing = monitorTargets.filter((target) => !liveTeams.some((team) => team.captainSessionId === target.sessionId && team.teamId === target.teamId));\n const needsDiscoveryArchive = discoverySessionId !== void 0 && discoverySessionId !== "" && !discoveryComplete;\n if (missing.length === 0 && !needsDiscoveryArchive && !discoveredTeamArchived) return;\n const archivedResponse = await fetchState(`${ACTIVITY_STATE_URL}?archived=1`, {\n cache: "no-store",\n signal: controller.signal\n });\n if (!archivedResponse.ok) return;\n const archivedBody = await archivedResponse.json();\n if (cancelled || !Array.isArray(archivedBody.teams)) return;\n publishSnapshots({ archivedTeams: archivedBody.teams });\n discoveryComplete = true;\n settleTargets(new Set(missing.map((target) => target.key)));\n } catch (error) {\n if (error?.name === "AbortError") return;\n } finally {\n inFlight = false;\n }\n };\n const firstTick = tick();\n if (timer === void 0) timer = schedule(() => {\n tick();\n }, intervalMs());\n return {\n firstTick,\n stop: () => {\n if (cancelled) return;\n cancelled = true;\n controller?.abort();\n cancel(timer);\n }\n };\n }\n //#endregion\n //#region lib/client/artwork.js\n /**\n * Shared whale artwork lookup for the activity panel and the conversation\n * card: role keywords map to the packaged role images; the captain always\n * uses the lead whale.\n * @module t-team/client/artwork\n */\n /** Artwork route prefix served by the plugin host half. */\n const ART_BASE = "/plugins/t-team/assets/";\n /** V2 whale role artwork per role keyword. */\n const ROLE_ART = [\n [/data|analys|metric|performance|\u6570\u636E|\u5206\u6790|\u6307\u6807|\u6027\u80FD/, "member-data-v2.png"],\n [/resear|investig|explor|study|\u7814\u7A76|\u8C03\u67E5|\u63A2\u7D22|\u8C03\u7814/, "member-researcher-v2.png"],\n [/\\bqa\\b|test|verif|quality|\u6D4B\u8BD5|\u8D28\u91CF|\u9A8C\u8BC1/, "member-qa-v2.png"],\n [/engineer|dev\\b|server|backend|\\bapi\\b|runtime|watcher|contract|\u5DE5\u7A0B|\u540E\u7AEF|\u670D\u52A1|\u63A5\u53E3|\u5F00\u53D1|\u4EE3\u7801|\u7F16\u7A0B/, "member-engineer-v2.png"],\n [/design|\\bui\\b|\\bux\\b|front|theme|accessib|\u8BBE\u8BA1|\u524D\u7AEF|\u4E3B\u9898|\u65E0\u969C\u788D/, "member-designer-v2.png"],\n [/secur|audit|risk|threat|review|\u5B89\u5168|\u5BA1\u8BA1|\u5BA1\u67E5|\u98CE\u9669/, "member-security-v2.png"],\n [/docs|writer|product|spec|\u64B0\u5199|\u6587\u6848|\u5199\u4F5C|\u6587\u6863|\u89C4\u8303/, "member-docs-v2.png"],\n [/release|\\bbuild\\b|deploy|\\bops\\b|\\bci\\b|ship|coordin|\u53D1\u5E03|\u6784\u5EFA|\u90E8\u7F72|\u8FD0\u7EF4|\u534F\u8C03/, "member-operator-v2.png"]\n ];\n /** Captain artwork (always the lead whale). */\n const LEAD_ART = `${ART_BASE}team-lead-v2.png`;\n /** Status action artwork per member activity. */\n const ACTION_ART = {\n working: `${ART_BASE}action-working-v2.png`,\n idle: `${ART_BASE}action-sleeping-v2.png`,\n unknown: `${ART_BASE}action-thinking-v2.png`\n };\n /**\n * Member artwork URL, or null when no role matches (initial-letter fallback).\n * @param name - the member\'s display name.\n * @param role - the member\'s role text.\n * @returns the artwork URL, or null when unmatched.\n */\n function memberArtUrl(name, role) {\n const identity = `${name} ${role}`.toLowerCase();\n for (const [pattern, art] of ROLE_ART) if (pattern.test(identity)) return `${ART_BASE}${art}`;\n return null;\n }\n //#endregion\n //#region \\0dsh-css:/home/runner/work/t-team/t-team/src/client/TTeamCard.module.css.mjs\n const css$1 = ".kPAopq_root{box-sizing:border-box;border:1px solid var(--dsw-alias-line-normal);background:var(--dsw-alias-bg-module-platform);border-radius:10px;flex-direction:column;gap:8px;width:100%;min-width:0;padding:10px 12px;display:flex}.kPAopq_head{align-items:center;gap:8px;min-width:0;display:flex}.kPAopq_leadAvatar{object-fit:contain;filter:drop-shadow(0 1px 1px #122d4833);background:0 0;border:0;border-radius:0;flex:none;width:30px;height:30px}.kPAopq_teamName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;flex:0 auto;font-size:13px;font-weight:600;line-height:20px;overflow:hidden}.kPAopq_memberCount{color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:none;margin-left:auto;font-size:11px;line-height:16px}.kPAopq_panelButton{border:1px solid var(--dsw-alias-line-strong);background:var(--dsw-alias-bg-module);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;border-radius:999px;flex:none;padding:2px 8px;font-size:10.5px;font-weight:600;line-height:16px;transition:border-color .12s,color .12s}.kPAopq_panelButton:hover{border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.kPAopq_panelButton:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}.kPAopq_members{flex-wrap:wrap;gap:6px;min-width:0;display:flex}.kPAopq_member{border:1px solid var(--dsw-alias-line-normal);background:var(--dsw-alias-bg-module);max-width:160px;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;border-radius:999px;align-items:center;gap:5px;padding:3px 8px 3px 3px;font-size:11px;font-weight:500;line-height:16px;transition:border-color .12s,background-color .12s;display:inline-flex}.kPAopq_member:hover{border-color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-bg-fill-neutral)}.kPAopq_member:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}.kPAopq_memberArt{object-fit:contain;filter:drop-shadow(0 1px 1px #122d482e);background:0 0;border:0;border-radius:0;width:24px;height:24px}.kPAopq_memberInitial{background:var(--dsw-alias-bg-fill-business);width:20px;height:20px;color:var(--dsw-alias-label-on-fill);border-radius:50%;justify-content:center;align-items:center;font-size:10px;font-weight:600;line-height:20px;display:inline-flex}.kPAopq_memberName{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}";\n const tagId$1 = "dsh-plugin-t-expert/TTeamCard.module.css";\n if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {\n const tag = document.createElement("style");\n tag.dataset.plugin = "dsh-plugin-t-expert";\n tag.dataset.pluginCss = tagId$1;\n tag.textContent = css$1;\n document.head.appendChild(tag);\n }\n var TTeamCard_module_css_default = {\n "head": "kPAopq_head",\n "leadAvatar": "kPAopq_leadAvatar",\n "member": "kPAopq_member",\n "memberArt": "kPAopq_memberArt",\n "memberCount": "kPAopq_memberCount",\n "memberInitial": "kPAopq_memberInitial",\n "memberName": "kPAopq_memberName",\n "members": "kPAopq_members",\n "panelButton": "kPAopq_panelButton",\n "root": "kPAopq_root",\n "teamName": "kPAopq_teamName"\n };\n //#endregion\n //#region lib/client/TTeamCard.js\n /**\n * T Team conversation card: the lightweight in-conversation summary for\n * one team \u2014 the captain\'s whale avatar and name, the member roster as\n * clickable whale avatars (opening the member\'s subagent transcript), and\n * an "activity panel" button that re-activates the top-right floater.\n *\n * The floater and this card share the `t-team:open-panel` window event\n * so the card can summon the panel even after it was closed (or when an old\n * session is re-opened for review).\n * @module t-team/client/card\n */\n /** Window event name the floater listens for to open itself. */\n const OPEN_PANEL_EVENT = "t-team:open-panel";\n /** Re-activate the top-right activity panel, carrying this team\'s summary\n * so the panel can show it even when the team no longer exists on disk\n * (historical session review). */\n function openActivityPanel(data) {\n window.dispatchEvent(new CustomEvent(OPEN_PANEL_EVENT, { detail: {\n teamId: data.teamId,\n captainSessionId: data.captainSessionId,\n teamName: data.teamName,\n members: data.members\n } }));\n }\n /** Render one durable team as a compact conversation card. */\n function TTeamCard({ node, openMember, sessionId, t }) {\n const data = node.data;\n const owner = data.captainSessionId || sessionId;\n const { teams, archivedTeams } = (0, react.useSyncExternalStore)(subscribeActivitySnapshots, getActivitySnapshotsSnapshot);\n (0, react.useEffect)(() => {\n return monitorAgentTeam(owner, data.teamId);\n }, [data.teamId, owner]);\n const snapshot = teams.find((team) => team.teamId === data.teamId && (owner === "" || team.captainSessionId === owner)) ?? archivedTeams.find((team) => team.teamId === data.teamId && (owner === "" || team.captainSessionId === owner));\n const resolved = (0, react.useMemo)(() => ({\n ...data,\n captainSessionId: snapshot?.captainSessionId ?? owner,\n teamName: snapshot?.name ?? data.teamName,\n members: snapshot?.members.map((member) => ({\n id: member.id,\n name: member.name,\n role: member.role\n })) ?? data.members\n }), [\n data,\n owner,\n snapshot\n ]);\n return (0, react_jsx_runtime.jsxs)("section", {\n className: TTeamCard_module_css_default.root,\n "data-t-team-card": true,\n "data-team-id": resolved.teamId,\n children: [(0, react_jsx_runtime.jsxs)("header", {\n className: TTeamCard_module_css_default.head,\n children: [\n (0, react_jsx_runtime.jsx)("img", {\n className: TTeamCard_module_css_default.leadAvatar,\n src: LEAD_ART,\n alt: "",\n "aria-hidden": true\n }),\n (0, react_jsx_runtime.jsx)("span", {\n className: TTeamCard_module_css_default.teamName,\n title: resolved.teamName,\n children: resolved.teamName\n }),\n (0, react_jsx_runtime.jsx)("span", {\n className: TTeamCard_module_css_default.memberCount,\n children: t("card.memberCount", { count: resolved.members.length })\n }),\n (0, react_jsx_runtime.jsx)("button", {\n type: "button",\n className: TTeamCard_module_css_default.panelButton,\n onClick: () => {\n openActivityPanel(resolved);\n },\n "aria-label": t("action.openActivityPanel"),\n title: t("action.openActivityPanel"),\n children: t("activity.panelButton")\n })\n ]\n }), resolved.members.length > 0 && (0, react_jsx_runtime.jsx)("div", {\n className: TTeamCard_module_css_default.members,\n children: resolved.members.map((member) => (0, react_jsx_runtime.jsxs)("button", {\n type: "button",\n className: TTeamCard_module_css_default.member,\n onClick: () => {\n if (member.id !== "") openMember(owner, member.id);\n },\n title: member.role === "" ? member.name : `${member.name} \xB7 ${member.role}`,\n children: [memberArtUrl(member.name, member.role) !== null ? (0, react_jsx_runtime.jsx)("img", {\n className: TTeamCard_module_css_default.memberArt,\n src: memberArtUrl(member.name, member.role) ?? "",\n alt: "",\n "aria-hidden": true\n }) : (0, react_jsx_runtime.jsx)("span", {\n className: TTeamCard_module_css_default.memberInitial,\n children: member.name.trim().slice(0, 1).toUpperCase() || "?"\n }), (0, react_jsx_runtime.jsx)("span", {\n className: TTeamCard_module_css_default.memberName,\n children: member.name\n })]\n }, member.id))\n })]\n });\n }\n //#endregion\n //#region \\0dsh-css:/home/runner/work/t-team/t-team/src/client/ActivityPanel.module.css.mjs\n const css = "html{--t-team-panel-shift:420px}html[data-t-team-panel-open] [data-phase=active]{box-sizing:border-box;padding-right:var(--t-team-panel-shift)}.aYQbCq_badge,.aYQbCq_panel{--dsw-alias-line-normal:var(--dsw-static-neutral-bluish-150,#e7e9ee);--dsw-alias-line-strong:color-mix(in srgb, var(--dsw-static-neutral-bluish-200,#e1e5ee) 50%, var(--dsw-static-neutral-bluish-300,#cfd3d6));--dsw-alias-bg-module:var(--dsw-alias-bg-layer-1,#fff);--dsw-alias-bg-fill-neutral:var(--dsw-static-neutral-bluish-100,#eef0f4);--dsw-alias-bg-fill-business:var(--dsw-alias-state-business-primary,#4d6bfe);--dsw-alias-bg-fill-success:var(--dsw-alias-state-success-primary,#12a150);--dsw-alias-bg-fill-warning:var(--dsw-alias-state-warn-primary,#e08700);--dsw-alias-bg-fill-danger:var(--dsw-alias-state-error-primary,#e5484d);--dsw-alias-state-success:var(--dsw-alias-state-success-primary,#12a150);--dsw-alias-state-warning:var(--dsw-alias-state-warn-primary,#e08700);--dsw-alias-state-danger:var(--dsw-alias-state-error-primary,#e5484d);--dsw-alias-label-on-fill:var(--dsw-alias-label-primary-inverted,#fff)}.aYQbCq_badge{box-sizing:border-box;border:1px solid var(--dsw-alias-line-normal);background:color-mix(in srgb, var(--dsw-alias-bg-module-platform) 92%, transparent);backdrop-filter:blur(16px);height:34px;box-shadow:0 8px 28px color-mix(in srgb, var(--dsw-alias-label-primary) 14%, transparent);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;border-radius:999px;align-items:center;gap:7px;padding:0 12px;font-size:12px;font-weight:600;line-height:20px;transition:border-color .15s,transform .12s;display:inline-flex;position:absolute;top:64px;right:18px}.aYQbCq_badge:hover{border-color:var(--dsw-alias-line-strong);transform:translateY(-1px)}.aYQbCq_badge:active{transform:translateY(0)scale(.98)}.aYQbCq_badge:focus-visible,.aYQbCq_iconButton:focus-visible,.aYQbCq_memberRow:focus-visible,.aYQbCq_membersToggle:focus-visible,.aYQbCq_sectionToggleTitle:focus-visible,.aYQbCq_dagNode:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.aYQbCq_badgeDot,.aYQbCq_panelDot{background:var(--dsw-alias-label-tertiary);border-radius:50%;width:7px;height:7px}.aYQbCq_badgeDot[data-busy=true],.aYQbCq_panelDot[data-busy=true]{background:var(--dsw-alias-state-business-primary);animation:1.25s ease-in-out infinite aYQbCq_tTeamPulse}.aYQbCq_badgeCount,.aYQbCq_memberCount,.aYQbCq_teamStats,.aYQbCq_stageLabel,.aYQbCq_taskId{font-variant-numeric:tabular-nums}.aYQbCq_panel{box-sizing:border-box;border:1px solid color-mix(in srgb, var(--dsw-alias-line-strong) 58%, transparent);background:color-mix(in srgb, var(--dsw-alias-bg-module) 95%, transparent);backdrop-filter:blur(20px)saturate(1.08);box-shadow:0 12px 32px color-mix(in srgb, var(--dsw-alias-label-primary) 12%, transparent), 0 32px 72px color-mix(in srgb, var(--dsw-alias-label-primary) 16%, transparent);will-change:transform;border-radius:16px;flex-direction:column;animation:.16s ease-out aYQbCq_tTeamPanelIn;display:flex;position:absolute;top:0;left:0;overflow:hidden}.aYQbCq_panel[data-dragging],.aYQbCq_panel[data-resizing]{user-select:none;box-shadow:0 16px 38px color-mix(in srgb, var(--dsw-alias-label-primary) 14%, transparent), 0 36px 78px color-mix(in srgb, var(--dsw-alias-label-primary) 18%, transparent)}@keyframes aYQbCq_tTeamPanelIn{0%{opacity:0}to{opacity:1}}@keyframes aYQbCq_tTeamPulse{0%,to{opacity:.42}50%{opacity:1}}.aYQbCq_panelHead{border-bottom:1px solid var(--dsw-alias-line-normal);cursor:grab;touch-action:none;flex:none;justify-content:space-between;align-items:center;min-height:44px;padding:0 14px 0 16px;display:flex}.aYQbCq_panelHead:active,.aYQbCq_panel[data-dragging] .aYQbCq_panelHead{cursor:grabbing}.aYQbCq_panel[data-compact] .aYQbCq_panelHead{cursor:default;touch-action:auto}.aYQbCq_panelTitle{color:var(--dsw-alias-label-primary);align-items:center;gap:8px;font-size:14px;font-weight:600;line-height:20px;display:inline-flex}.aYQbCq_panelControls{flex:none;align-items:center;gap:2px;display:inline-flex}.aYQbCq_iconButton{width:28px;height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:7px;justify-content:center;align-items:center;padding:0;transition:background-color .12s,color .12s,transform .12s;display:inline-flex}.aYQbCq_iconButton:hover{background:var(--dsw-alias-bg-fill-neutral);color:var(--dsw-alias-label-primary)}.aYQbCq_iconButton:active{transform:scale(.94)}.aYQbCq_iconButton[data-control=dock][data-mode=docked] svg{transform:scaleX(-1)}.aYQbCq_resizeHandle{z-index:5;touch-action:none;pointer-events:auto;position:absolute}.aYQbCq_resizeHandle[data-resize-edge=left]{cursor:ew-resize;width:14px;top:44px;bottom:14px;left:0}.aYQbCq_resizeHandle[data-resize-edge=left]:after{background:color-mix(in srgb, var(--dsw-alias-label-tertiary) 42%, transparent);content:\\"\\";opacity:.45;border-radius:999px;width:3px;height:48px;transition:background-color .12s,opacity .12s;position:absolute;top:50%;left:4px;transform:translateY(-50%)}.aYQbCq_resizeHandle[data-resize-edge=bottom]{cursor:ns-resize;height:14px;bottom:0;left:20px;right:20px}.aYQbCq_resizeHandle[data-resize-edge=bottom]:after{background:color-mix(in srgb, var(--dsw-alias-label-tertiary) 42%, transparent);content:\\"\\";opacity:.45;border-radius:999px;width:48px;height:3px;transition:background-color .12s,opacity .12s;position:absolute;bottom:4px;left:50%;transform:translate(-50%)}.aYQbCq_resizeHandle[data-resize-edge=corner]{cursor:nwse-resize;width:28px;height:28px;bottom:0;right:0}.aYQbCq_resizeHandle[data-resize-edge=corner]:after{border-right:2px solid var(--dsw-alias-label-tertiary);border-bottom:2px solid var(--dsw-alias-label-tertiary);content:\\"\\";opacity:.58;width:10px;height:10px;transition:border-color .12s,opacity .12s;position:absolute;bottom:6px;right:6px}.aYQbCq_resizeHandle:hover:after,.aYQbCq_panel[data-resizing] .aYQbCq_resizeHandle:after{background-color:var(--dsw-alias-bg-fill-business);border-color:var(--dsw-alias-bg-fill-business);opacity:.95}.aYQbCq_teams{overscroll-behavior:contain;scrollbar-color:color-mix(in srgb, var(--dsw-alias-label-tertiary) 28%, transparent) transparent;scrollbar-width:thin;flex-direction:column;min-height:0;display:flex;overflow-y:auto}.aYQbCq_teams::-webkit-scrollbar{width:6px}.aYQbCq_teams::-webkit-scrollbar-track{background:0 0}.aYQbCq_teams::-webkit-scrollbar-thumb{background:color-mix(in srgb, var(--dsw-alias-label-tertiary) 28%, transparent);background-clip:padding-box;border:2px solid #0000;border-radius:999px}.aYQbCq_teams:hover::-webkit-scrollbar-thumb{background:color-mix(in srgb, var(--dsw-alias-label-tertiary) 44%, transparent);background-clip:padding-box}.aYQbCq_team{border-bottom:1px solid var(--dsw-alias-line-normal);flex-direction:column;gap:12px;padding:12px 14px 16px;display:flex;container:aYQbCq_agent-team/inline-size}.aYQbCq_team:last-child{border-bottom:0}.aYQbCq_teamHead{align-items:center;gap:10px;min-width:0;display:flex}.aYQbCq_teamName{min-width:0;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:13px;font-weight:600;line-height:18px;overflow:hidden}.aYQbCq_teamStats{color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:none;gap:8px;font-size:10.5px;line-height:16px;display:inline-flex}.aYQbCq_teamStopButton{border:1px solid var(--dsw-alias-line-normal);width:26px;height:26px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border-radius:7px;flex:none;place-items:center;padding:0;transition:border-color .15s,background .15s,color .15s;display:grid}.aYQbCq_teamStopButton:hover{border-color:color-mix(in srgb, var(--dsw-alias-state-danger) 42%, var(--dsw-alias-line-normal));background:color-mix(in srgb, var(--dsw-alias-state-danger) 7%, transparent);color:var(--dsw-alias-state-danger)}.aYQbCq_teamStopButton:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.aYQbCq_stopModalActions{justify-content:flex-end;gap:8px;display:flex}.aYQbCq_stopModalActions button{border:1px solid var(--dsw-alias-line-normal,#e7e9ee);background:var(--dsw-alias-bg-fill-neutral,#eef0f4);min-height:34px;color:var(--dsw-alias-label-primary,#1c1c1e);cursor:pointer;font:inherit;border-radius:8px;justify-content:center;align-items:center;gap:6px;padding:6px 13px;font-size:12px;font-weight:600;display:inline-flex}.aYQbCq_stopModalActions button[data-danger]{border-color:var(--dsw-alias-state-danger,#e5484d);background:var(--dsw-alias-state-danger,#e5484d);color:var(--dsw-alias-label-on-fill,#fff)}.aYQbCq_stopModalActions button:disabled{cursor:wait;opacity:.58}.aYQbCq_stopModalError{background:color-mix(in srgb, var(--dsw-alias-state-danger,#e5484d) 8%, transparent);color:var(--dsw-alias-state-danger,#e5484d);border-radius:8px;align-items:flex-start;gap:7px;margin:0;padding:9px 10px;font-size:12px;line-height:18px;display:flex}.aYQbCq_stopModalError svg{flex:none;margin-top:1px}.aYQbCq_sectionHead{justify-content:space-between;align-items:center;gap:8px;min-width:0;display:flex}.aYQbCq_sectionTitle{color:var(--dsw-alias-label-secondary);align-items:center;gap:6px;font-size:11px;font-weight:600;line-height:16px;display:inline-flex}.aYQbCq_sectionHint{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:10px;line-height:14px;overflow:hidden}.aYQbCq_delegationSection{min-width:0}.aYQbCq_captainNode{box-sizing:border-box;border:1px solid color-mix(in srgb, var(--dsw-alias-state-business-primary) 32%, var(--dsw-alias-line-normal));background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 7%, var(--dsw-alias-bg-module));border-radius:10px;grid-template-columns:48px minmax(0,1fr) auto;align-items:center;gap:9px;min-height:56px;padding:6px 10px;display:grid}.aYQbCq_captainAvatar,.aYQbCq_memberAvatar{flex:none;justify-content:center;align-items:center;display:inline-flex;position:relative}.aYQbCq_captainAvatar{width:46px;height:46px}.aYQbCq_leadAvatar,.aYQbCq_memberArt{object-fit:contain;filter:drop-shadow(0 1px 1px #122d4833);background:0 0;border:0;border-radius:0}.aYQbCq_leadAvatar{width:44px;height:44px}.aYQbCq_memberArt{width:40px;height:40px}.aYQbCq_captainInfo,.aYQbCq_memberInfo{flex-direction:column;min-width:0;display:flex}.aYQbCq_captainInfo{gap:2px}.aYQbCq_captainLine,.aYQbCq_memberLine{align-items:center;gap:6px;min-width:0;display:flex}.aYQbCq_captainName,.aYQbCq_memberName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:12.5px;font-weight:600;line-height:18px;overflow:hidden}.aYQbCq_captainRole,.aYQbCq_memberRole{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:10px;line-height:14px;overflow:hidden}.aYQbCq_captainSummary,.aYQbCq_memberStatusLine{color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;white-space:nowrap;font-size:10.5px;line-height:15px;overflow:hidden}.aYQbCq_taskDetailModel{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:9.5px;line-height:14px;overflow:hidden}.aYQbCq_memberModel{box-sizing:border-box;border:1px solid var(--dsw-alias-line-normal);background:var(--dsw-alias-bg-fill-neutral);min-width:0;max-width:132px;color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;border-radius:999px;flex:0 auto;align-items:center;padding:0 6px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:9px;font-weight:600;line-height:15px;display:inline-flex;overflow:hidden}.aYQbCq_captainState,.aYQbCq_memberState{color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:none;align-items:center;gap:5px;font-size:10px;font-weight:500;line-height:15px;display:inline-flex}.aYQbCq_captainState[data-busy=true],.aYQbCq_memberState[data-activity=working]{color:var(--dsw-alias-bg-fill-business)}.aYQbCq_workGlyph rect{opacity:.5}.aYQbCq_workGlyph[data-active=true] rect{animation:1.1s ease-in-out infinite aYQbCq_tTeamDot}@keyframes aYQbCq_tTeamDot{0%,to{opacity:.25}50%{opacity:1}}.aYQbCq_progressOverview{flex-direction:column;gap:7px;display:flex}.aYQbCq_progressTitle{color:var(--dsw-alias-label-secondary);font-size:11px;font-weight:600;line-height:16px}.aYQbCq_progressSegments{gap:3px;display:flex}.aYQbCq_progressSegments>span,.aYQbCq_progressEmpty{background:var(--dsw-alias-line-strong);border-radius:2px;flex:1;height:5px}.aYQbCq_progressEmpty{width:100%;display:block}.aYQbCq_progressSegments>span[data-state=running]{background:var(--dsw-alias-state-business-primary)}.aYQbCq_progressSegments>span[data-state=blocked]{background:var(--dsw-alias-state-warning)}.aYQbCq_progressSegments>span[data-state=completed]{background:var(--dsw-alias-state-success)}.aYQbCq_progressSegments>span[data-state=failed]{background:var(--dsw-alias-state-danger)}.aYQbCq_progressSegments>span[data-state=cancelled]{opacity:.55}.aYQbCq_progressLegend{color:var(--dsw-alias-label-tertiary);gap:10px;font-size:9.5px;line-height:14px;display:flex}.aYQbCq_progressLegend>span[data-state=running]{color:var(--dsw-alias-state-business-primary)}.aYQbCq_progressLegend>span[data-state=blocked]{color:var(--dsw-alias-state-warning)}.aYQbCq_progressLegend>span[data-state=completed]{color:var(--dsw-alias-state-success)}.aYQbCq_progressSummary{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 7%, var(--dsw-alias-bg-module));min-width:0;color:var(--dsw-alias-label-secondary);border-radius:8px;align-items:center;gap:6px;padding:5px 8px;font-size:10px;font-weight:600;line-height:15px;display:flex}.aYQbCq_progressSummary[data-state=warning]{background:color-mix(in srgb, var(--dsw-alias-state-warning) 8%, var(--dsw-alias-bg-module))}.aYQbCq_progressSummary[data-state=completed]{background:color-mix(in srgb, var(--dsw-alias-state-success) 8%, var(--dsw-alias-bg-module))}.aYQbCq_progressSummary[data-state=discarded]{background:var(--dsw-alias-bg-fill-neutral)}.aYQbCq_progressSummary>span:last-child{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.aYQbCq_progressSummaryDot{background:var(--dsw-alias-state-business-primary);border-radius:50%;flex:none;width:5px;height:5px}.aYQbCq_progressSummary[data-state=warning] .aYQbCq_progressSummaryDot{background:var(--dsw-alias-state-warning)}.aYQbCq_progressSummary[data-state=completed] .aYQbCq_progressSummaryDot{background:var(--dsw-alias-state-success)}.aYQbCq_progressSummary[data-state=discarded] .aYQbCq_progressSummaryDot{background:var(--dsw-alias-label-tertiary)}.aYQbCq_membersToggle{background:var(--dsw-alias-bg-module-platform);width:100%;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;border:0;border-radius:8px;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;font-size:10.5px;font-weight:600;line-height:15px;display:flex}.aYQbCq_membersToggle:hover{background:var(--dsw-alias-bg-fill-neutral)}.aYQbCq_membersToggle>span{align-items:center;gap:5px;display:inline-flex}.aYQbCq_membersToggle>span:last-child{color:var(--dsw-alias-state-business-primary)}.aYQbCq_chevron{flex:none;transition:transform .14s}.aYQbCq_chevron[data-open=true]{transform:rotate(90deg)}.aYQbCq_delegationTree{flex-direction:column;gap:2px;margin-left:18px;padding:9px 0 0 20px;display:flex;position:relative}.aYQbCq_delegationTree:before{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 48%, var(--dsw-alias-line-normal));content:\\"\\";width:1px;position:absolute;top:0;bottom:22px;left:0}.aYQbCq_memberBlock{flex-direction:column;min-width:0;padding:3px 0 7px;display:flex;position:relative}.aYQbCq_memberBranch{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 48%, var(--dsw-alias-line-normal));width:20px;height:1px;display:block;position:absolute;top:27px;right:100%}.aYQbCq_memberBranch:before{background:var(--dsw-alias-state-business-primary);content:\\"\\";border-radius:50%;width:5px;height:5px;position:absolute;top:-2px;right:-1px}.aYQbCq_memberRow{box-sizing:border-box;width:100%;min-width:0;min-height:48px;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:8px;grid-template-columns:46px minmax(0,1fr) auto;align-items:center;gap:8px;padding:4px 6px;transition:background-color .12s,transform .12s;display:grid}.aYQbCq_memberRow:hover,.aYQbCq_memberRow[data-activity=working]{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 6%, var(--dsw-alias-bg-module))}.aYQbCq_memberRow:active{transform:scale(.995)}.aYQbCq_memberAvatar{width:42px;height:42px}.aYQbCq_memberAvatar[data-unread=true]:after{box-sizing:border-box;border:1px solid var(--dsw-alias-bg-module);background:var(--dsw-alias-state-business-primary);content:\\"\\";border-radius:50%;width:6px;height:6px;animation:1.8s ease-in-out infinite aYQbCq_tTeamUnreadPulse;position:absolute;top:0;right:-1px}@keyframes aYQbCq_tTeamUnreadPulse{0%,to{opacity:.78;transform:scale(.92)}50%{opacity:1;transform:scale(1.16)}}.aYQbCq_memberInitial{background:var(--dsw-alias-bg-fill-business);width:34px;height:34px;color:var(--dsw-alias-label-on-fill);border-radius:50%;justify-content:center;align-items:center;font-size:14px;font-weight:600;line-height:20px;display:inline-flex}.aYQbCq_stateArt{box-sizing:border-box;object-fit:contain;width:22px;height:22px;filter:drop-shadow(0 0 1px var(--dsw-alias-bg-module)) drop-shadow(0 1px 1px #122d483d);background:0 0;border:0;border-radius:0;position:absolute;bottom:-3px;right:-5px}.aYQbCq_stateArt[data-activity=working]{animation:2.4s ease-in-out infinite aYQbCq_tTeamFloat}.aYQbCq_stateArt[data-activity=idle]{animation:4.2s ease-in-out infinite aYQbCq_tTeamBreathe}.aYQbCq_stateArt[data-activity=unknown]{animation:2.8s ease-in-out infinite aYQbCq_tTeamThink}@keyframes aYQbCq_tTeamFloat{0%,to{transform:translateY(0)rotate(-4deg)}50%{transform:translateY(-2px)rotate(4deg)}}@keyframes aYQbCq_tTeamBreathe{0%,to{opacity:.82;transform:scale(1)}50%{opacity:1;transform:scale(1.06)}}@keyframes aYQbCq_tTeamThink{0%,to{transform:rotate(-7deg)}50%{transform:rotate(7deg)}}.aYQbCq_memberState{margin-left:auto}.aYQbCq_memberCount{color:var(--dsw-alias-label-tertiary);font-size:10.5px;line-height:16px}.aYQbCq_assignmentLine{align-items:center;gap:7px;min-width:0;padding:0 6px 0 60px;display:flex}.aYQbCq_assignmentLabel{color:var(--dsw-alias-label-tertiary);flex:none;font-size:9.5px;line-height:14px}.aYQbCq_assignmentTasks{flex-wrap:wrap;flex:1;gap:4px;min-width:0;display:flex}.aYQbCq_assignmentChip{background:var(--dsw-alias-bg-fill-neutral);max-width:100%;min-height:16px;color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;white-space:nowrap;border-radius:4px;align-items:center;padding:0 5px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:9px;font-weight:600;line-height:14px;display:inline-flex;overflow:hidden}.aYQbCq_assignmentChip[data-state=running]{background:var(--dsw-alias-bg-fill-business);color:var(--dsw-alias-label-on-fill)}.aYQbCq_assignmentChip[data-state=completed]{background:var(--dsw-alias-bg-fill-success);color:var(--dsw-alias-label-on-fill)}.aYQbCq_assignmentChip[data-state=blocked]{background:var(--dsw-alias-bg-fill-warning);color:var(--dsw-alias-label-on-fill)}.aYQbCq_assignmentChip[data-state=failed]{background:var(--dsw-alias-bg-fill-danger);color:var(--dsw-alias-label-on-fill)}.aYQbCq_assignmentChip[data-state=cancelled]{color:var(--dsw-alias-label-tertiary);text-decoration:line-through}.aYQbCq_unreadPill{color:var(--dsw-alias-state-business-primary);white-space:nowrap;flex:none;font-size:9.5px;font-weight:600;line-height:14px}.aYQbCq_taskEmpty{color:var(--dsw-alias-label-tertiary);font-size:9.5px;line-height:14px}.aYQbCq_dependencySection{border-top:1px solid var(--dsw-alias-line-normal);flex-direction:column;gap:7px;min-width:0;padding-top:10px;display:flex}.aYQbCq_sectionToggleTitle{color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border:0;align-items:center;gap:6px;padding:0;font-size:11px;font-weight:600;line-height:16px;display:inline-flex}.aYQbCq_dagViewport{scrollbar-width:thin;min-width:0;padding:2px 0 4px;overflow-x:auto}.aYQbCq_dagCanvas{min-width:100%;position:relative}.aYQbCq_dagCanvas[data-layout=parallel]{flex-wrap:wrap;gap:8px;display:flex}.aYQbCq_dagCanvas[data-layout=parallel] .aYQbCq_dagNode{flex:92px;min-width:92px;position:relative}.aYQbCq_dagEdges{pointer-events:none;position:absolute;inset:0;overflow:visible}.aYQbCq_dagEdges path{fill:none;stroke:var(--dsw-alias-line-strong);stroke-width:1px;transition:opacity .14s,stroke .14s,stroke-width .14s}.aYQbCq_dagEdges path[data-active=true]{stroke:var(--dsw-alias-state-business-primary);stroke-width:1.6px}.aYQbCq_dagEdges path[data-dimmed=true]{opacity:.24}.aYQbCq_dagNode{box-sizing:border-box;border:1px solid var(--dsw-alias-line-normal);background:var(--dsw-alias-bg-module);color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;border-radius:6px;flex-direction:column;justify-content:center;gap:1px;padding:0 6px;transition:border-color .14s,background-color .14s,opacity .14s;display:flex;position:absolute}.aYQbCq_dagNode:hover,.aYQbCq_dagNode[data-focused=true]{border-color:var(--dsw-alias-state-business-primary);background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 6%, var(--dsw-alias-bg-module))}.aYQbCq_dagNode[data-dimmed=true]{opacity:.3}.aYQbCq_dagNode[data-state=running][data-dimmed=true]{opacity:.58}.aYQbCq_dagNode[data-state=completed]{border-color:color-mix(in srgb, var(--dsw-alias-state-success) 48%, var(--dsw-alias-line-normal))}.aYQbCq_dagNode[data-state=blocked]{border-color:color-mix(in srgb, var(--dsw-alias-state-warning) 52%, var(--dsw-alias-line-normal))}.aYQbCq_dagNode[data-state=failed]{border-color:color-mix(in srgb, var(--dsw-alias-state-danger) 56%, var(--dsw-alias-line-normal))}.aYQbCq_dagNodeHead{color:var(--dsw-alias-label-primary);align-items:center;gap:4px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:9.5px;font-weight:700;display:flex}.aYQbCq_dagNodeDot{background:var(--dsw-alias-line-strong);border-radius:1.5px;flex:none;width:5px;height:5px}.aYQbCq_dagNode[data-state=running] .aYQbCq_dagNodeDot{background:var(--dsw-alias-state-business-primary)}.aYQbCq_dagNode[data-state=running] .aYQbCq_dagNodeHead{padding-right:12px}.aYQbCq_dagRunningState{width:9px;height:9px;color:var(--dsw-alias-state-business-primary);pointer-events:none;justify-content:center;align-items:center;display:inline-flex;position:absolute;top:4px;right:5px}.aYQbCq_dagRunningState .aYQbCq_workGlyph{width:9px;height:9px}.aYQbCq_dagNode[data-state=blocked] .aYQbCq_dagNodeDot{background:var(--dsw-alias-state-warning)}.aYQbCq_dagNode[data-state=completed] .aYQbCq_dagNodeDot{background:var(--dsw-alias-state-success)}.aYQbCq_dagNode[data-state=failed] .aYQbCq_dagNodeDot{background:var(--dsw-alias-state-danger)}.aYQbCq_dagNodeLabel{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:8.5px;line-height:11px;overflow:hidden}.aYQbCq_taskDetail{border:1px solid var(--dsw-alias-line-normal);background:var(--dsw-alias-bg-module-platform);border-radius:9px;flex-direction:column;gap:3px;min-width:0;padding:7px 9px;display:flex}.aYQbCq_taskDetailHead{align-items:center;gap:6px;min-width:0;display:flex}.aYQbCq_taskDetailId{color:var(--dsw-alias-state-business-primary);flex:none;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:10px;font-weight:700}.aYQbCq_taskDetailSubject{min-width:0;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:11px;font-weight:600;line-height:16px;overflow:hidden}.aYQbCq_taskDetailBadge{background:var(--dsw-alias-bg-fill-neutral);color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:0 5px;font-size:8.5px;font-weight:600;line-height:14px}.aYQbCq_taskDetailBadge[data-state=running]{background:var(--dsw-alias-bg-fill-business);color:var(--dsw-alias-label-on-fill)}.aYQbCq_taskDetailBadge[data-state=blocked]{background:var(--dsw-alias-bg-fill-warning);color:var(--dsw-alias-label-on-fill)}.aYQbCq_taskDetailBadge[data-state=completed]{background:var(--dsw-alias-bg-fill-success);color:var(--dsw-alias-label-on-fill)}.aYQbCq_taskDetailBadge[data-state=failed]{background:var(--dsw-alias-bg-fill-danger);color:var(--dsw-alias-label-on-fill)}.aYQbCq_taskDetailLine,.aYQbCq_taskDetailMeta{color:var(--dsw-alias-label-secondary);font-size:9.5px;line-height:14px}.aYQbCq_taskDetailMeta{color:var(--dsw-alias-label-tertiary)}.aYQbCq_emptyHint{color:var(--dsw-alias-label-tertiary);padding:10px 12px;font-size:11px;line-height:16px}.aYQbCq_planEditor{border:1px solid color-mix(in srgb, var(--dsw-alias-state-business-primary) 30%, var(--dsw-alias-line-normal));background:color-mix(in srgb, var(--dsw-alias-bg-module-platform) 94%, var(--dsw-alias-state-business-primary));box-shadow:inset 0 1px 0 color-mix(in srgb, var(--dsw-alias-label-primary) 5%, transparent);border-radius:10px;flex-direction:column;gap:12px;margin:0 10px 12px;padding:12px;display:flex}.aYQbCq_planHeader>span{justify-content:space-between;align-items:center;gap:8px;display:flex}.aYQbCq_planHeader>span>span{flex-direction:column;gap:2px;min-width:0;display:flex}.aYQbCq_planHeader strong{color:var(--dsw-alias-label-primary);font-size:12px}.aYQbCq_planHeader small{color:var(--dsw-alias-label-secondary);font-size:9px;font-weight:500;line-height:13px}.aYQbCq_planHeader em{background:var(--dsw-alias-bg-fill-business);color:var(--dsw-alias-label-on-fill);border-radius:999px;flex:none;padding:1px 7px;font-size:9px;font-style:normal;line-height:16px}.aYQbCq_planHeader p{color:var(--dsw-alias-label-secondary);margin:5px 0 0;font-size:10px;line-height:15px}.aYQbCq_planFlow{grid-template-columns:repeat(3,minmax(0,1fr));margin:0;padding:0;list-style:none;display:grid}.aYQbCq_planFlow li{min-width:0;color:var(--dsw-alias-label-tertiary);align-items:center;gap:5px;font-size:9px;font-weight:600;line-height:14px;display:flex;position:relative}.aYQbCq_planFlow li:not(:last-child):after{background:var(--dsw-alias-line-normal);content:\\"\\";flex:1;min-width:8px;height:1px;margin-right:5px}.aYQbCq_planFlow li>span{border:1px solid var(--dsw-alias-line-normal);border-radius:50%;flex:none;place-items:center;width:18px;height:18px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:9px;display:grid}.aYQbCq_planFlow li[data-active]{color:var(--dsw-alias-state-business-primary)}.aYQbCq_planFlow li[data-active]>span{border-color:var(--dsw-alias-state-business-primary);background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 12%, transparent)}.aYQbCq_planSection{border:1px solid var(--dsw-alias-line-normal);background:var(--dsw-alias-bg-module-platform);border-radius:8px;overflow:hidden}.aYQbCq_planSectionToggle,.aYQbCq_planCardHeader{box-sizing:border-box;width:100%;color:var(--dsw-alias-label-primary);cursor:pointer;text-align:left;background:0 0;border:0}.aYQbCq_planSectionToggle{justify-content:space-between;align-items:center;gap:8px;min-height:42px;padding:7px 9px;display:flex}.aYQbCq_planSectionToggle:hover,.aYQbCq_planCardHeader:hover{background:color-mix(in srgb, var(--dsw-alias-bg-fill-neutral) 46%, transparent)}.aYQbCq_planSectionToggle>span{align-items:baseline;gap:7px;min-width:0;display:flex}.aYQbCq_planSectionToggle strong{font-size:10.5px}.aYQbCq_planSectionToggle small{color:var(--dsw-alias-label-tertiary);font-size:9px}.aYQbCq_planList{border-top:1px solid var(--dsw-alias-line-normal);flex-direction:column;gap:0;display:flex}.aYQbCq_planEmpty{color:var(--dsw-alias-label-tertiary);text-align:center;margin:0;padding:12px;font-size:10px}.aYQbCq_planCard{background:0 0;border:0;border-radius:0;min-width:0;margin:0;padding:0;display:block;position:relative}.aYQbCq_planCard+.aYQbCq_planCard{border-top:1px solid var(--dsw-alias-line-normal)}.aYQbCq_planCard[data-open=true]{background:color-mix(in srgb, var(--dsw-alias-bg-base) 62%, transparent)}.aYQbCq_planCardHeader{grid-template-columns:minmax(80px,.9fr) minmax(72px,1.15fr) auto 12px;align-items:center;gap:7px;min-height:40px;padding:6px 9px;display:grid}.aYQbCq_planCardIdentity{flex-direction:column;gap:1px;min-width:0;display:flex}.aYQbCq_planCardIdentity strong,.aYQbCq_planTaskSummary{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:10px;font-weight:650;line-height:14px;overflow:hidden}.aYQbCq_planCardIdentity>span,.aYQbCq_planCardMeta{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:8.5px;line-height:12px;overflow:hidden}.aYQbCq_planTaskId{background:var(--dsw-alias-bg-fill-neutral);width:max-content;color:var(--dsw-alias-label-secondary);border-radius:4px;padding:1px 5px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:8.5px;font-weight:700;line-height:14px}.aYQbCq_planDirty{background:color-mix(in srgb, var(--dsw-alias-state-warning) 13%, transparent);color:var(--dsw-alias-state-warning);border-radius:999px;justify-self:end;padding:1px 5px;font-size:8px;font-style:normal;font-weight:650;line-height:14px}.aYQbCq_planChevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .18s cubic-bezier(.2,.7,.2,1)}.aYQbCq_planChevron[data-open=true]{transform:rotate(90deg)}.aYQbCq_planCardBody{flex-direction:column;gap:8px;padding:0 9px 9px;display:flex}.aYQbCq_planCardBody fieldset{border:0;flex-direction:column;gap:7px;min-width:0;margin:0;padding:0;display:flex}.aYQbCq_planCardBody label,.aYQbCq_planNewTask label{min-width:0;color:var(--dsw-alias-label-tertiary);flex-direction:column;flex:1;gap:4px;font-size:9px;display:flex}.aYQbCq_planCardBody label small{color:var(--dsw-alias-label-tertiary);font-size:8px;line-height:11px}.aYQbCq_planCard input,.aYQbCq_planCard textarea,.aYQbCq_planCard select,.aYQbCq_planNewTask input{box-sizing:border-box;border:1px solid var(--dsw-alias-line-normal);background:var(--dsw-alias-bg-base);width:100%;min-width:0;color:var(--dsw-alias-label-primary);font:inherit;border-radius:6px;outline:none;font-size:10.5px;line-height:16px;transition:border-color .16s,box-shadow .16s}.aYQbCq_planCard input,.aYQbCq_planCard select,.aYQbCq_planNewTask input{min-height:32px;padding:6px 8px}.aYQbCq_planCard textarea{resize:vertical;min-height:58px;padding:7px 8px}.aYQbCq_planCard input:focus-visible,.aYQbCq_planCard textarea:focus-visible,.aYQbCq_planCard select:focus-visible,.aYQbCq_planNewTask input:focus-visible{border-color:var(--dsw-alias-state-business-primary);box-shadow:0 0 0 2px color-mix(in srgb, var(--dsw-alias-state-business-primary) 16%, transparent)}.aYQbCq_planGrid{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:6px;display:grid}.aYQbCq_planModelPicker{grid-template-columns:minmax(0,1fr);gap:5px;display:grid}.aYQbCq_planModelMenu{width:100%;display:flex}.aYQbCq_planModelTrigger{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);width:100%;min-height:38px;color:var(--dsw-alias-label-primary);cursor:pointer;text-align:left;border-radius:7px;justify-content:space-between;align-items:center;gap:8px;padding:7px 9px;transition:border-color .16s,background-color .16s,transform .12s;display:flex}.aYQbCq_planModelTrigger:hover:not(:disabled){border-color:var(--dsw-alias-border-l3);background:var(--dsw-alias-interactive-bg-hover)}.aYQbCq_planModelTrigger:active:not(:disabled){transform:translateY(1px)}.aYQbCq_planModelTrigger:focus-visible{border-color:var(--dsw-alias-state-business-primary);outline:2px solid color-mix(in srgb, var(--dsw-alias-state-business-primary) 16%, transparent);outline-offset:1px}.aYQbCq_planModelTrigger:disabled{cursor:wait;opacity:.64}.aYQbCq_planModelTriggerCopy{align-items:baseline;gap:6px;min-width:0;display:flex}.aYQbCq_planModelTriggerCopy strong,.aYQbCq_planModelTriggerCopy span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.aYQbCq_planModelTriggerCopy strong{color:var(--dsw-alias-label-primary);font-size:10px;font-weight:650;line-height:15px}.aYQbCq_planModelTriggerCopy span{color:var(--dsw-alias-label-tertiary);font-size:9px;line-height:14px}.aYQbCq_planModelMenuRow{grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:8px;width:100%;min-width:0;display:grid}.aYQbCq_planModelMenuRow>span:first-child{color:var(--dsw-alias-label-primary)}.aYQbCq_planModelMenuRow strong{color:var(--dsw-alias-label-tertiary);text-align:right;text-overflow:ellipsis;white-space:nowrap;font-weight:450;overflow:hidden}.aYQbCq_planModelMenuBack{align-items:center;gap:7px;display:inline-flex}.aYQbCq_planModelMenuBack svg{transform:rotate(180deg)}.aYQbCq_planModelEffortRow{flex-direction:column;align-items:flex-start;min-width:0;display:flex}.aYQbCq_planModelEffortRow small{width:100%;color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:10px;line-height:14px;overflow:hidden}.aYQbCq_planModelHint{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:8.5px;line-height:12px;overflow:hidden}.aYQbCq_planModelNotice{background:color-mix(in srgb, var(--dsw-alias-state-warning) 9%, transparent);color:var(--dsw-alias-label-secondary);border-radius:6px;grid-column:1/-1;justify-content:space-between;align-items:center;gap:8px;padding:6px 7px;font-size:8.5px;line-height:12px;display:flex}.aYQbCq_planModelNotice button{color:var(--dsw-alias-state-business-primary);cursor:pointer;font:inherit;background:0 0;border:0;flex:none;padding:2px 6px;font-weight:650}.aYQbCq_planActions,.aYQbCq_planApproveRow,.aYQbCq_planNewTask,.aYQbCq_planConfirm,.aYQbCq_planApproveActions,.aYQbCq_planSecondaryActions{align-items:center;gap:7px;display:flex}.aYQbCq_planReviewActions{grid-template-columns:minmax(0,1fr);gap:6px;width:100%;display:grid}.aYQbCq_planSecondaryActions{grid-template-columns:minmax(0,1fr) auto;display:grid}.aYQbCq_planActions{justify-content:flex-end}.aYQbCq_planActions button,.aYQbCq_planNewTask button,.aYQbCq_planApproveRow button,.aYQbCq_planConfirm button{border:1px solid var(--dsw-alias-line-normal);background:var(--dsw-alias-bg-fill-neutral);min-height:30px;color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;flex:none;padding:5px 10px;font-size:9.5px;font-weight:600;transition:background .16s,border-color .16s,transform .16s}.aYQbCq_planActions button:hover:not(:disabled),.aYQbCq_planNewTask button:hover:not(:disabled),.aYQbCq_planApproveRow button:hover:not(:disabled),.aYQbCq_planConfirm button:hover:not(:disabled){border-color:var(--dsw-alias-label-tertiary)}.aYQbCq_planActions button:active:not(:disabled),.aYQbCq_planNewTask button:active:not(:disabled),.aYQbCq_planApproveRow button:active:not(:disabled),.aYQbCq_planConfirm button:active:not(:disabled){transform:scale(.98)}.aYQbCq_planActions button[data-danger],.aYQbCq_planConfirm button[data-danger]{color:var(--dsw-alias-state-danger)}.aYQbCq_planFeedback{min-width:0;color:var(--dsw-alias-label-secondary);flex:1;align-items:center;gap:5px;font-size:9px;line-height:13px;animation:.18s ease-out aYQbCq_plan-feedback-in;display:inline-flex}.aYQbCq_planFeedback[data-tone=success]{color:var(--dsw-alias-state-success)}.aYQbCq_planFeedback[data-tone=error]{color:var(--dsw-alias-state-danger)}.aYQbCq_planFeedback>span{border:1px solid;border-radius:50%;flex:none;place-items:center;width:15px;height:15px;display:grid}.aYQbCq_planFeedback svg{width:11px;height:11px}@keyframes aYQbCq_plan-feedback-in{0%{opacity:0;transform:translateY(-2px)}to{opacity:1;transform:translateY(0)}}.aYQbCq_planConfirm{border:1px solid color-mix(in srgb, var(--dsw-alias-state-danger) 30%, var(--dsw-alias-line-normal));background:color-mix(in srgb, var(--dsw-alias-state-danger) 7%, transparent);border-radius:7px;flex-wrap:wrap;justify-content:flex-end;padding:7px}.aYQbCq_planConfirm>span{min-width:140px;color:var(--dsw-alias-label-secondary);flex:1;font-size:9px;line-height:13px}.aYQbCq_planNewTask{align-items:flex-end}.aYQbCq_planNewTask label{gap:4px}.aYQbCq_planNewTask label>span{line-height:13px}.aYQbCq_planApproveRow{z-index:1;border:1px solid var(--dsw-alias-line-normal);background:color-mix(in srgb, var(--dsw-alias-bg-module-platform) 94%, transparent);min-height:50px;box-shadow:0 -5px 16px color-mix(in srgb, var(--dsw-alias-bg-base) 35%, transparent);backdrop-filter:blur(8px);border-radius:8px;flex-direction:column;justify-content:flex-end;align-items:stretch;margin:0 -4px -4px;padding:8px;position:sticky;bottom:0}.aYQbCq_planApproveRow[data-armed=true]{border-color:color-mix(in srgb, var(--dsw-alias-state-business-primary) 45%, var(--dsw-alias-line-normal))}.aYQbCq_planApproveRow[data-discard=true]{border-color:color-mix(in srgb, var(--dsw-alias-state-danger) 45%, var(--dsw-alias-line-normal))}.aYQbCq_planApproveCopy{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.aYQbCq_planApproveCopy strong{color:var(--dsw-alias-label-primary);font-size:9.5px;line-height:13px}.aYQbCq_planApproveCopy small{color:var(--dsw-alias-label-tertiary);font-size:8.5px;line-height:12px}.aYQbCq_planApproveRow button{background:var(--dsw-alias-state-business-primary);min-height:32px;color:var(--dsw-alias-label-on-fill);padding-inline:13px}.aYQbCq_planReviewActions>button[data-plan-approve]{width:100%}.aYQbCq_planApproveActions>button:first-child{background:var(--dsw-alias-bg-fill-neutral);color:var(--dsw-alias-label-primary)}.aYQbCq_planSecondaryActions>button,.aYQbCq_planApproveActions>button[data-danger]{border-color:var(--dsw-alias-line-normal);background:var(--dsw-alias-bg-fill-neutral);color:var(--dsw-alias-label-primary)}.aYQbCq_planSecondaryActions>button[data-danger],.aYQbCq_planApproveActions>button[data-danger]{color:var(--dsw-alias-state-danger)}.aYQbCq_planSectionToggle:focus-visible,.aYQbCq_planCardHeader:focus-visible,.aYQbCq_planActions button:focus-visible,.aYQbCq_planNewTask button:focus-visible,.aYQbCq_planApproveRow button:focus-visible,.aYQbCq_planConfirm button:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px}.aYQbCq_planActions button:disabled,.aYQbCq_planNewTask button:disabled,.aYQbCq_planApproveRow button:disabled{cursor:default;opacity:.55}.aYQbCq_historicPill{background:var(--dsw-alias-bg-fill-neutral);color:var(--dsw-alias-label-tertiary);border-radius:4px;flex:none;margin-left:auto;padding:1px 7px;font-size:9.5px;font-weight:600;line-height:15px}.aYQbCq_members{flex-direction:column;gap:3px;display:flex}.aYQbCq_archiveLabel{color:var(--dsw-alias-label-tertiary);padding:5px 14px 0;font-size:9.5px;font-weight:600;line-height:14px;display:block}@media (prefers-reduced-motion:reduce){.aYQbCq_panel,.aYQbCq_badge,.aYQbCq_badgeDot,.aYQbCq_panelDot,.aYQbCq_workGlyph rect,.aYQbCq_stateArt,.aYQbCq_memberAvatar[data-unread=true]:after,.aYQbCq_planChevron,.aYQbCq_planFeedback,.aYQbCq_planActions button,.aYQbCq_planNewTask button,.aYQbCq_planApproveRow button,.aYQbCq_planConfirm button,.aYQbCq_planCard input,.aYQbCq_planCard textarea,.aYQbCq_planCard select,.aYQbCq_planNewTask input{transition:none;animation:none}}@media (width<=960px){html[data-t-team-panel-open] [data-phase=active]{padding-right:0}}@media (width<=640px){.aYQbCq_badge{top:56px;right:10px}.aYQbCq_teamStats span[data-stat=messages]{display:none}.aYQbCq_captainNode{grid-template-columns:48px minmax(0,1fr)}.aYQbCq_captainState{display:none}.aYQbCq_delegationTree{margin-left:12px;padding-left:15px}.aYQbCq_memberBranch{width:15px}.aYQbCq_assignmentLine{padding-left:53px}.aYQbCq_planFlow li{gap:4px;font-size:8px}.aYQbCq_planFlow li:not(:last-child):after{margin-right:3px}.aYQbCq_planCardHeader{grid-template-columns:auto minmax(0,1fr) auto}.aYQbCq_planCardHeader .aYQbCq_planCardMeta{display:none}.aYQbCq_planGrid,.aYQbCq_planModelPicker{grid-template-columns:minmax(0,1fr)}.aYQbCq_planNewTask,.aYQbCq_planApproveRow{flex-direction:column;align-items:stretch}.aYQbCq_planNewTask button,.aYQbCq_planApproveRow>button,.aYQbCq_planApproveActions,.aYQbCq_planReviewActions{width:100%}.aYQbCq_planApproveActions button,.aYQbCq_planReviewActions button,.aYQbCq_planSecondaryActions button{flex:1}}@container aYQbCq_agent-team (width<=360px){.aYQbCq_planEditor{margin-inline:0;padding-inline:10px}.aYQbCq_planHeader>span{align-items:flex-start}.aYQbCq_planFlow li{gap:3px;font-size:7.5px}.aYQbCq_planFlow li:not(:last-child):after{min-width:4px;margin-right:2px}.aYQbCq_planSecondaryActions,.aYQbCq_planApproveActions{grid-template-columns:minmax(0,1fr);width:100%;display:grid}.aYQbCq_planSecondaryActions button,.aYQbCq_planApproveActions button{width:100%}}";\n const tagId = "dsh-plugin-t-expert/ActivityPanel.module.css";\n if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {\n const tag = document.createElement("style");\n tag.dataset.plugin = "dsh-plugin-t-expert";\n tag.dataset.pluginCss = tagId;\n tag.textContent = css;\n document.head.appendChild(tag);\n }\n var ActivityPanel_module_css_default = {\n "agent-team": "aYQbCq_agent-team",\n "tTeamBreathe": "aYQbCq_tTeamBreathe",\n "tTeamDot": "aYQbCq_tTeamDot",\n "tTeamFloat": "aYQbCq_tTeamFloat",\n "tTeamPanelIn": "aYQbCq_tTeamPanelIn",\n "tTeamPulse": "aYQbCq_tTeamPulse",\n "tTeamThink": "aYQbCq_tTeamThink",\n "tTeamUnreadPulse": "aYQbCq_tTeamUnreadPulse",\n "archiveLabel": "aYQbCq_archiveLabel",\n "assignmentChip": "aYQbCq_assignmentChip",\n "assignmentLabel": "aYQbCq_assignmentLabel",\n "assignmentLine": "aYQbCq_assignmentLine",\n "assignmentTasks": "aYQbCq_assignmentTasks",\n "badge": "aYQbCq_badge",\n "badgeCount": "aYQbCq_badgeCount",\n "badgeDot": "aYQbCq_badgeDot",\n "captainAvatar": "aYQbCq_captainAvatar",\n "captainInfo": "aYQbCq_captainInfo",\n "captainLine": "aYQbCq_captainLine",\n "captainName": "aYQbCq_captainName",\n "captainNode": "aYQbCq_captainNode",\n "captainRole": "aYQbCq_captainRole",\n "captainState": "aYQbCq_captainState",\n "captainSummary": "aYQbCq_captainSummary",\n "chevron": "aYQbCq_chevron",\n "dagCanvas": "aYQbCq_dagCanvas",\n "dagEdges": "aYQbCq_dagEdges",\n "dagNode": "aYQbCq_dagNode",\n "dagNodeDot": "aYQbCq_dagNodeDot",\n "dagNodeHead": "aYQbCq_dagNodeHead",\n "dagNodeLabel": "aYQbCq_dagNodeLabel",\n "dagRunningState": "aYQbCq_dagRunningState",\n "dagViewport": "aYQbCq_dagViewport",\n "delegationSection": "aYQbCq_delegationSection",\n "delegationTree": "aYQbCq_delegationTree",\n "dependencySection": "aYQbCq_dependencySection",\n "emptyHint": "aYQbCq_emptyHint",\n "historicPill": "aYQbCq_historicPill",\n "iconButton": "aYQbCq_iconButton",\n "leadAvatar": "aYQbCq_leadAvatar",\n "memberArt": "aYQbCq_memberArt",\n "memberAvatar": "aYQbCq_memberAvatar",\n "memberBlock": "aYQbCq_memberBlock",\n "memberBranch": "aYQbCq_memberBranch",\n "memberCount": "aYQbCq_memberCount",\n "memberInfo": "aYQbCq_memberInfo",\n "memberInitial": "aYQbCq_memberInitial",\n "memberLine": "aYQbCq_memberLine",\n "memberModel": "aYQbCq_memberModel",\n "memberName": "aYQbCq_memberName",\n "memberRole": "aYQbCq_memberRole",\n "memberRow": "aYQbCq_memberRow",\n "memberState": "aYQbCq_memberState",\n "memberStatusLine": "aYQbCq_memberStatusLine",\n "members": "aYQbCq_members",\n "membersToggle": "aYQbCq_membersToggle",\n "panel": "aYQbCq_panel",\n "panelControls": "aYQbCq_panelControls",\n "panelDot": "aYQbCq_panelDot",\n "panelHead": "aYQbCq_panelHead",\n "panelTitle": "aYQbCq_panelTitle",\n "plan-feedback-in": "aYQbCq_plan-feedback-in",\n "planActions": "aYQbCq_planActions",\n "planApproveActions": "aYQbCq_planApproveActions",\n "planApproveCopy": "aYQbCq_planApproveCopy",\n "planApproveRow": "aYQbCq_planApproveRow",\n "planCard": "aYQbCq_planCard",\n "planCardBody": "aYQbCq_planCardBody",\n "planCardHeader": "aYQbCq_planCardHeader",\n "planCardIdentity": "aYQbCq_planCardIdentity",\n "planCardMeta": "aYQbCq_planCardMeta",\n "planChevron": "aYQbCq_planChevron",\n "planConfirm": "aYQbCq_planConfirm",\n "planDirty": "aYQbCq_planDirty",\n "planEditor": "aYQbCq_planEditor",\n "planEmpty": "aYQbCq_planEmpty",\n "planFeedback": "aYQbCq_planFeedback",\n "planFlow": "aYQbCq_planFlow",\n "planGrid": "aYQbCq_planGrid",\n "planHeader": "aYQbCq_planHeader",\n "planList": "aYQbCq_planList",\n "planModelEffortRow": "aYQbCq_planModelEffortRow",\n "planModelHint": "aYQbCq_planModelHint",\n "planModelMenu": "aYQbCq_planModelMenu",\n "planModelMenuBack": "aYQbCq_planModelMenuBack",\n "planModelMenuRow": "aYQbCq_planModelMenuRow",\n "planModelNotice": "aYQbCq_planModelNotice",\n "planModelPicker": "aYQbCq_planModelPicker",\n "planModelTrigger": "aYQbCq_planModelTrigger",\n "planModelTriggerCopy": "aYQbCq_planModelTriggerCopy",\n "planNewTask": "aYQbCq_planNewTask",\n "planReviewActions": "aYQbCq_planReviewActions",\n "planSecondaryActions": "aYQbCq_planSecondaryActions",\n "planSection": "aYQbCq_planSection",\n "planSectionToggle": "aYQbCq_planSectionToggle",\n "planTaskId": "aYQbCq_planTaskId",\n "planTaskSummary": "aYQbCq_planTaskSummary",\n "progressEmpty": "aYQbCq_progressEmpty",\n "progressLegend": "aYQbCq_progressLegend",\n "progressOverview": "aYQbCq_progressOverview",\n "progressSegments": "aYQbCq_progressSegments",\n "progressSummary": "aYQbCq_progressSummary",\n "progressSummaryDot": "aYQbCq_progressSummaryDot",\n "progressTitle": "aYQbCq_progressTitle",\n "resizeHandle": "aYQbCq_resizeHandle",\n "sectionHead": "aYQbCq_sectionHead",\n "sectionHint": "aYQbCq_sectionHint",\n "sectionTitle": "aYQbCq_sectionTitle",\n "sectionToggleTitle": "aYQbCq_sectionToggleTitle",\n "stageLabel": "aYQbCq_stageLabel",\n "stateArt": "aYQbCq_stateArt",\n "stopModalActions": "aYQbCq_stopModalActions",\n "stopModalError": "aYQbCq_stopModalError",\n "taskDetail": "aYQbCq_taskDetail",\n "taskDetailBadge": "aYQbCq_taskDetailBadge",\n "taskDetailHead": "aYQbCq_taskDetailHead",\n "taskDetailId": "aYQbCq_taskDetailId",\n "taskDetailLine": "aYQbCq_taskDetailLine",\n "taskDetailMeta": "aYQbCq_taskDetailMeta",\n "taskDetailModel": "aYQbCq_taskDetailModel",\n "taskDetailSubject": "aYQbCq_taskDetailSubject",\n "taskEmpty": "aYQbCq_taskEmpty",\n "taskId": "aYQbCq_taskId",\n "team": "aYQbCq_team",\n "teamHead": "aYQbCq_teamHead",\n "teamName": "aYQbCq_teamName",\n "teamStats": "aYQbCq_teamStats",\n "teamStopButton": "aYQbCq_teamStopButton",\n "teams": "aYQbCq_teams",\n "unreadPill": "aYQbCq_unreadPill",\n "workGlyph": "aYQbCq_workGlyph"\n };\n //#endregion\n //#region lib/client/StagingPlanEditor.js\n /**\n * Editable pre-run roster and DAG review for staged T Team plans.\n *\n * This leaf owns only transient form/disclosure state. Durable truth remains\n * on the host and returns through the ordinary activity polling snapshot.\n * @module t-team/client/staging-plan\n */\n const PLAN_URL = "/plugins/t-team/plan";\n function useDismissSuccess(feedback, setFeedback) {\n (0, react.useEffect)(() => {\n if (feedback?.tone !== "success") return;\n const timeout = window.setTimeout(() => {\n setFeedback(void 0);\n }, 3500);\n return () => {\n window.clearTimeout(timeout);\n };\n }, [feedback, setFeedback]);\n }\n async function mutatePlan(payload) {\n const response = await fetch(PLAN_URL, {\n method: "POST",\n cache: "no-store",\n headers: { "content-type": "application/json" },\n body: JSON.stringify(payload)\n });\n if (response.ok) return;\n let message = `HTTP ${response.status}`;\n try {\n const body = await response.json();\n if (typeof body.error === "string" && body.error.trim() !== "") message = body.error;\n } catch {}\n throw new Error(message);\n }\n function errorMessage(error) {\n return error instanceof Error ? error.message : String(error);\n }\n function DisclosureChevron({ open }) {\n return (0, react_jsx_runtime.jsx)("svg", {\n className: ActivityPanel_module_css_default.planChevron,\n "data-open": open,\n width: "12",\n height: "12",\n viewBox: "0 0 12 12",\n fill: "none",\n stroke: "currentColor",\n strokeWidth: "1.5",\n strokeLinecap: "round",\n "aria-hidden": true,\n children: (0, react_jsx_runtime.jsx)("path", { d: "M4 2.5 7.5 6 4 9.5" })\n });\n }\n function Feedback({ value }) {\n if (value === void 0) return null;\n return (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planFeedback,\n "data-tone": value.tone,\n role: value.tone === "error" ? "alert" : "status",\n "aria-live": value.tone === "error" ? "assertive" : "polite",\n children: [(0, react_jsx_runtime.jsx)("span", {\n "aria-hidden": true,\n children: value.tone === "success" ? (0, react_jsx_runtime.jsx)("svg", {\n viewBox: "0 0 12 12",\n fill: "none",\n stroke: "currentColor",\n strokeWidth: "1.8",\n children: (0, react_jsx_runtime.jsx)("path", { d: "m2.5 6.2 2.2 2.2 4.8-5" })\n }) : (0, react_jsx_runtime.jsx)("svg", {\n viewBox: "0 0 12 12",\n fill: "none",\n stroke: "currentColor",\n strokeWidth: "1.8",\n children: (0, react_jsx_runtime.jsx)("path", { d: "M6 2.3v4.1M6 8.8v.1" })\n })\n }), value.message]\n });\n }\n function routeKey(provider, model) {\n return JSON.stringify([provider, model]);\n }\n const MODEL_MENU_OPEN_MODELS = "open:models";\n const MODEL_MENU_OPEN_EFFORT = "open:effort";\n const MODEL_MENU_BACK = "navigate:back";\n const MODEL_MENU_RETRY = "action:retry";\n const MODEL_MENU_DEFAULT_EFFORT = "effort:default";\n function modelMenuId(provider, model) {\n return `model:${routeKey(provider, model)}`;\n }\n function effortMenuId(effort) {\n return `effort:${effort}`;\n }\n /**\n * Thin staged-plan adapter over the official model directory. It deliberately\n * reads only catalog metadata: choosing a member route must not change the\n * captain session\'s composer model.\n */\n function StagedModelPicker({ directory, provider, model, reasoningEffort, busy, onChange, t }) {\n const state = (0, react.useSyncExternalStore)(directory.store.subscribe, directory.store.getSnapshot);\n const [open, setOpen] = (0, react.useState)(false);\n const [pane, setPane] = (0, react.useState)("root");\n const catalogRoutes = state.groups.flatMap((group) => group.models.map((candidate) => ({\n key: routeKey(group.id, candidate.id),\n provider: group.id,\n providerName: group.name,\n model: candidate\n })));\n const selectedKey = routeKey(provider, model);\n const selected = catalogRoutes.find((candidate) => candidate.key === selectedKey);\n const efforts = selected?.model.reasoning?.efforts ?? [];\n const currentMissing = provider !== "" && model !== "" && selected === void 0;\n const defaultEffort = selected?.model.reasoning?.defaultEffort;\n const effectiveEffort = reasoningEffort === "" || reasoningEffort === "default" ? defaultEffort : reasoningEffort;\n const selectedEffort = efforts.find((effort) => effort.id === effectiveEffort);\n const modelLabel = selected?.model.name ?? (model === "" ? t("plan.model.choose") : model);\n const effortLabel = selectedEffort?.name ?? (effectiveEffort === void 0 ? t("plan.model.providerDefault") : effectiveEffort);\n const unavailable = state.status === "error" || state.failures.length > 0;\n const close = () => {\n setOpen(false);\n setPane("root");\n };\n const rootItems = [{\n id: MODEL_MENU_OPEN_MODELS,\n label: (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planModelMenuRow,\n children: [\n (0, react_jsx_runtime.jsx)("span", { children: t("plan.member.model") }),\n (0, react_jsx_runtime.jsx)("strong", { children: modelLabel }),\n (0, react_jsx_runtime.jsx)(DisclosureChevron, { open: false })\n ]\n }),\n disabled: state.status === "loading" && catalogRoutes.length === 0\n }, {\n id: MODEL_MENU_OPEN_EFFORT,\n label: (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planModelMenuRow,\n children: [\n (0, react_jsx_runtime.jsx)("span", { children: t("plan.member.reasoning") }),\n (0, react_jsx_runtime.jsx)("strong", { children: effortLabel }),\n (0, react_jsx_runtime.jsx)(DisclosureChevron, { open: false })\n ]\n }),\n disabled: selected?.model.reasoning === void 0\n }];\n const modelItems = [{\n id: MODEL_MENU_BACK,\n label: (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planModelMenuBack,\n children: [(0, react_jsx_runtime.jsx)(DisclosureChevron, { open: false }), t("plan.model.back")]\n })\n }, {\n type: "separator",\n id: "models:separator"\n }];\n if (catalogRoutes.length === 0) modelItems.push({\n id: "models:empty",\n label: state.status === "loading" ? t("plan.model.loading") : t("plan.model.empty"),\n disabled: true\n });\n else for (const group of state.groups) {\n modelItems.push({\n type: "label",\n id: `provider:${group.id}`,\n text: group.name\n });\n for (const candidate of group.models) modelItems.push({\n id: modelMenuId(group.id, candidate.id),\n label: candidate.name\n });\n }\n const effortItems = [\n {\n id: MODEL_MENU_BACK,\n label: (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planModelMenuBack,\n children: [(0, react_jsx_runtime.jsx)(DisclosureChevron, { open: false }), t("plan.model.back")]\n })\n },\n {\n type: "separator",\n id: "effort:separator"\n },\n {\n id: MODEL_MENU_DEFAULT_EFFORT,\n label: defaultEffort === void 0 ? t("plan.model.providerDefault") : t("plan.model.modelDefault", { effort: efforts.find((effort) => effort.id === defaultEffort)?.name ?? defaultEffort })\n },\n ...efforts.map((effort) => ({\n id: effortMenuId(effort.id),\n label: (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planModelEffortRow,\n children: [(0, react_jsx_runtime.jsx)("span", { children: effort.name }), effort.description !== void 0 && (0, react_jsx_runtime.jsx)("small", { children: effort.description })]\n })\n }))\n ];\n const items = pane === "models" ? modelItems : pane === "effort" ? effortItems : rootItems;\n const selectedId = pane === "models" ? modelMenuId(provider, model) : pane === "effort" ? reasoningEffort === "" || reasoningEffort === "default" ? MODEL_MENU_DEFAULT_EFFORT : effortMenuId(reasoningEffort) : void 0;\n const choose = (id) => {\n if (id === MODEL_MENU_OPEN_MODELS) {\n setPane("models");\n return;\n }\n if (id === MODEL_MENU_OPEN_EFFORT) {\n setPane("effort");\n return;\n }\n if (id === MODEL_MENU_BACK) {\n setPane("root");\n return;\n }\n if (id === MODEL_MENU_RETRY) {\n directory.load().catch(() => void 0);\n return;\n }\n const nextModel = catalogRoutes.find((candidate) => modelMenuId(candidate.provider, candidate.model.id) === id);\n if (nextModel !== void 0) {\n close();\n if (nextModel.provider === provider && nextModel.model.id === model) return;\n onChange({\n provider: nextModel.provider,\n model: nextModel.model.id,\n reasoningEffort: "default"\n });\n return;\n }\n if (id === MODEL_MENU_DEFAULT_EFFORT) {\n close();\n if (effectiveEffort === defaultEffort) return;\n onChange({\n provider,\n model,\n reasoningEffort: "default"\n });\n return;\n }\n const nextEffort = efforts.find((effort) => effortMenuId(effort.id) === id);\n if (nextEffort === void 0) return;\n close();\n if (nextEffort.id === reasoningEffort) return;\n onChange({\n provider,\n model,\n reasoningEffort: nextEffort.id\n });\n };\n return (0, react_jsx_runtime.jsxs)("div", {\n className: ActivityPanel_module_css_default.planModelPicker,\n "data-model-directory-status": state.status,\n children: [\n (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {\n open,\n portal: true,\n align: "end",\n compact: true,\n className: ActivityPanel_module_css_default.planModelMenu,\n items,\n footer: unavailable ? [{\n id: MODEL_MENU_RETRY,\n label: t("plan.model.retry")\n }] : void 0,\n selectedId,\n onSelect: choose,\n onClose: close,\n anchor: (0, react_jsx_runtime.jsxs)("button", {\n type: "button",\n className: ActivityPanel_module_css_default.planModelTrigger,\n "data-plan-model-trigger": true,\n "aria-label": t("plan.model.triggerAria", {\n model: modelLabel,\n effort: effortLabel\n }),\n "aria-haspopup": "menu",\n "aria-expanded": open,\n disabled: busy,\n onClick: () => {\n if (open) close();\n else {\n setPane("root");\n setOpen(true);\n directory.load().catch(() => void 0);\n }\n },\n children: [(0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planModelTriggerCopy,\n children: [(0, react_jsx_runtime.jsx)("strong", { children: state.status === "loading" && catalogRoutes.length === 0 ? t("plan.model.loading") : modelLabel }), (0, react_jsx_runtime.jsx)("span", { children: effortLabel })]\n }), (0, react_jsx_runtime.jsx)(DisclosureChevron, { open })]\n })\n }),\n (0, react_jsx_runtime.jsx)("small", {\n className: ActivityPanel_module_css_default.planModelHint,\n children: currentMissing ? t("plan.model.currentUnavailable", {\n provider,\n model\n }) : selected?.model.description ?? t("plan.model.route", {\n provider,\n model\n })\n }),\n unavailable && (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planModelNotice,\n role: state.status === "error" ? "alert" : "status",\n children: [(0, react_jsx_runtime.jsx)("span", { children: state.error ?? t("plan.model.partialFailure", { count: state.failures.length }) }), (0, react_jsx_runtime.jsx)("button", {\n type: "button",\n disabled: busy || state.status === "loading",\n onClick: () => {\n directory.load().catch(() => void 0);\n },\n children: t("plan.model.retry")\n })]\n })\n ]\n });\n }\n function StagedMemberEditor({ team, member, modelDirectory, onPendingChange, t }) {\n const bodyId = (0, react.useId)();\n const [open, setOpen] = (0, react.useState)(false);\n const [role, setRole] = (0, react.useState)(member.role);\n const [provider, setProvider] = (0, react.useState)(member.provider ?? "");\n const [model, setModel] = (0, react.useState)(member.model ?? "");\n const [reasoningEffort, setReasoningEffort] = (0, react.useState)(member.reasoningEffort ?? "");\n const [executionPrompt, setExecutionPrompt] = (0, react.useState)(member.executionPrompt ?? "");\n const remoteSignature = JSON.stringify([\n member.role,\n member.provider ?? "",\n member.model ?? "",\n member.reasoningEffort ?? "",\n member.executionPrompt ?? ""\n ]);\n const [savedSignature, setSavedSignature] = (0, react.useState)(remoteSignature);\n const [busy, setBusy] = (0, react.useState)(false);\n const [feedback, setFeedback] = (0, react.useState)();\n useDismissSuccess(feedback, setFeedback);\n const dirty = JSON.stringify([\n role,\n provider,\n model,\n reasoningEffort,\n executionPrompt\n ]) !== savedSignature;\n (0, react.useEffect)(() => {\n onPendingChange(`member:${member.name}`, dirty || busy);\n return () => {\n onPendingChange(`member:${member.name}`, false);\n };\n }, [\n busy,\n dirty,\n member.name,\n onPendingChange\n ]);\n (0, react.useEffect)(() => {\n setRole(member.role);\n setProvider(member.provider ?? "");\n setModel(member.model ?? "");\n setReasoningEffort(member.reasoningEffort ?? "");\n setExecutionPrompt(member.executionPrompt ?? "");\n setSavedSignature(remoteSignature);\n }, [\n member.role,\n member.provider,\n member.model,\n member.reasoningEffort,\n member.executionPrompt,\n remoteSignature\n ]);\n const markEdited = () => {\n setFeedback(void 0);\n };\n const persist = async (selection = {\n provider,\n model,\n reasoningEffort\n }) => {\n const nextSignature = JSON.stringify([\n role,\n selection.provider,\n selection.model,\n selection.reasoningEffort,\n executionPrompt\n ]);\n setProvider(selection.provider);\n setModel(selection.model);\n setReasoningEffort(selection.reasoningEffort);\n setBusy(true);\n setFeedback(void 0);\n try {\n await mutatePlan({\n sessionId: team.captainSessionId,\n teamId: team.teamId,\n action: "update_member",\n memberName: member.name,\n role,\n provider: selection.provider,\n model: selection.model,\n reasoningEffort: selection.reasoningEffort,\n executionPrompt\n });\n setSavedSignature(nextSignature);\n setFeedback({\n tone: "success",\n message: t("plan.saved")\n });\n } catch (error) {\n setFeedback({\n tone: "error",\n message: t("plan.failed", { message: errorMessage(error) })\n });\n } finally {\n setBusy(false);\n }\n };\n const save = async (event) => {\n event.preventDefault();\n await persist();\n };\n const route = `${provider}/${model}`.replace(/^\\//u, "");\n return (0, react_jsx_runtime.jsxs)("article", {\n className: ActivityPanel_module_css_default.planCard,\n "data-plan-member": member.name,\n "data-open": open,\n children: [(0, react_jsx_runtime.jsxs)("button", {\n type: "button",\n className: ActivityPanel_module_css_default.planCardHeader,\n "aria-expanded": open,\n "aria-controls": bodyId,\n onClick: () => {\n setOpen((current) => !current);\n },\n children: [\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planCardIdentity,\n children: [(0, react_jsx_runtime.jsx)("strong", { children: member.name }), (0, react_jsx_runtime.jsx)("span", { children: role || t("plan.member.roleFallback") })]\n }),\n (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.planCardMeta,\n title: route,\n children: route\n }),\n dirty && (0, react_jsx_runtime.jsx)("em", {\n className: ActivityPanel_module_css_default.planDirty,\n children: t("plan.unsaved")\n }),\n (0, react_jsx_runtime.jsx)(DisclosureChevron, { open })\n ]\n }), open && (0, react_jsx_runtime.jsxs)("form", {\n id: bodyId,\n className: ActivityPanel_module_css_default.planCardBody,\n onSubmit: (event) => {\n save(event);\n },\n children: [(0, react_jsx_runtime.jsxs)("fieldset", {\n disabled: busy,\n children: [\n (0, react_jsx_runtime.jsxs)("label", { children: [t("plan.member.role"), (0, react_jsx_runtime.jsx)("input", {\n name: "role",\n value: role,\n onChange: (event) => {\n setRole(event.currentTarget.value);\n markEdited();\n }\n })] }),\n (0, react_jsx_runtime.jsx)(StagedModelPicker, {\n directory: modelDirectory,\n provider,\n model,\n reasoningEffort,\n busy,\n onChange: (selection) => {\n persist(selection);\n },\n t\n }),\n (0, react_jsx_runtime.jsxs)("label", { children: [t("plan.member.prompt"), (0, react_jsx_runtime.jsx)("textarea", {\n name: "executionPrompt",\n value: executionPrompt,\n onChange: (event) => {\n setExecutionPrompt(event.currentTarget.value);\n markEdited();\n },\n rows: 3\n })] })\n ]\n }), (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planActions,\n children: [(0, react_jsx_runtime.jsx)(Feedback, { value: feedback }), (0, react_jsx_runtime.jsx)("button", {\n type: "submit",\n disabled: busy || !dirty || provider.trim() === "" || model.trim() === "",\n children: busy ? t("plan.saving") : t("plan.save")\n })]\n })]\n })]\n });\n }\n function StagedTaskEditor({ team, task, onPendingChange, t }) {\n const bodyId = (0, react.useId)();\n const taskDependencies = task.dependencies.join(", ");\n const [open, setOpen] = (0, react.useState)(false);\n const [subject, setSubject] = (0, react.useState)(task.subject);\n const [description, setDescription] = (0, react.useState)(task.description ?? "");\n const [assignee, setAssignee] = (0, react.useState)(task.assignee);\n const [dependencies, setDependencies] = (0, react.useState)(taskDependencies);\n const remoteSignature = JSON.stringify([\n task.subject,\n task.description ?? "",\n task.assignee,\n taskDependencies\n ]);\n const [savedSignature, setSavedSignature] = (0, react.useState)(remoteSignature);\n const [busy, setBusy] = (0, react.useState)(false);\n const [confirmingRemove, setConfirmingRemove] = (0, react.useState)(false);\n const [feedback, setFeedback] = (0, react.useState)();\n useDismissSuccess(feedback, setFeedback);\n const signature = JSON.stringify([\n subject,\n description,\n assignee,\n dependencies\n ]);\n const dirty = signature !== savedSignature;\n (0, react.useEffect)(() => {\n onPendingChange(`task:${task.id}`, dirty || busy);\n return () => {\n onPendingChange(`task:${task.id}`, false);\n };\n }, [\n busy,\n dirty,\n onPendingChange,\n task.id\n ]);\n (0, react.useEffect)(() => {\n setSubject(task.subject);\n setDescription(task.description ?? "");\n setAssignee(task.assignee);\n setDependencies(taskDependencies);\n setSavedSignature(remoteSignature);\n }, [\n task.subject,\n task.description,\n task.assignee,\n taskDependencies,\n remoteSignature\n ]);\n const markEdited = () => {\n setFeedback(void 0);\n setConfirmingRemove(false);\n };\n const save = async (event) => {\n event.preventDefault();\n setBusy(true);\n setFeedback(void 0);\n try {\n await mutatePlan({\n sessionId: team.captainSessionId,\n teamId: team.teamId,\n action: "update_task",\n taskId: task.id,\n subject,\n description,\n assignee,\n dependencies: dependencies.split(",").map((item) => item.trim()).filter(Boolean)\n });\n setSavedSignature(signature);\n setFeedback({\n tone: "success",\n message: t("plan.saved")\n });\n } catch (error) {\n setFeedback({\n tone: "error",\n message: t("plan.failed", { message: errorMessage(error) })\n });\n } finally {\n setBusy(false);\n }\n };\n const remove = async () => {\n setBusy(true);\n setFeedback(void 0);\n try {\n await mutatePlan({\n sessionId: team.captainSessionId,\n teamId: team.teamId,\n action: "remove_task",\n taskId: task.id\n });\n setFeedback({\n tone: "success",\n message: t("plan.removed")\n });\n } catch (error) {\n setFeedback({\n tone: "error",\n message: t("plan.failed", { message: errorMessage(error) })\n });\n setBusy(false);\n }\n };\n const dependencySummary = task.dependencies.length === 0 ? t("plan.dependencies.none") : t("plan.dependencies.count", { count: task.dependencies.length });\n return (0, react_jsx_runtime.jsxs)("article", {\n className: ActivityPanel_module_css_default.planCard,\n "data-plan-task": task.id,\n "data-open": open,\n children: [(0, react_jsx_runtime.jsxs)("button", {\n type: "button",\n className: ActivityPanel_module_css_default.planCardHeader,\n "aria-expanded": open,\n "aria-controls": bodyId,\n onClick: () => {\n setOpen((current) => !current);\n },\n children: [\n (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.planTaskId,\n children: task.id\n }),\n (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.planTaskSummary,\n title: subject,\n children: subject\n }),\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planCardMeta,\n children: [\n assignee || t("plan.task.unassigned"),\n " \xB7 ",\n dependencySummary\n ]\n }),\n dirty && (0, react_jsx_runtime.jsx)("em", {\n className: ActivityPanel_module_css_default.planDirty,\n children: t("plan.unsaved")\n }),\n (0, react_jsx_runtime.jsx)(DisclosureChevron, { open })\n ]\n }), open && (0, react_jsx_runtime.jsxs)("form", {\n id: bodyId,\n className: ActivityPanel_module_css_default.planCardBody,\n onSubmit: (event) => {\n save(event);\n },\n children: [\n (0, react_jsx_runtime.jsxs)("fieldset", {\n disabled: busy,\n children: [\n (0, react_jsx_runtime.jsxs)("label", { children: [t("plan.task.subject"), (0, react_jsx_runtime.jsx)("input", {\n name: "subject",\n required: true,\n value: subject,\n onChange: (event) => {\n setSubject(event.currentTarget.value);\n markEdited();\n }\n })] }),\n (0, react_jsx_runtime.jsxs)("label", { children: [t("plan.task.description"), (0, react_jsx_runtime.jsx)("textarea", {\n name: "description",\n value: description,\n onChange: (event) => {\n setDescription(event.currentTarget.value);\n markEdited();\n },\n rows: 3\n })] }),\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planGrid,\n children: [(0, react_jsx_runtime.jsxs)("label", { children: [t("plan.task.assignee"), (0, react_jsx_runtime.jsxs)("select", {\n name: "assignee",\n value: assignee,\n onChange: (event) => {\n setAssignee(event.currentTarget.value);\n markEdited();\n },\n children: [(0, react_jsx_runtime.jsx)("option", {\n value: "",\n children: t("plan.task.unassigned")\n }), team.members.map((member) => (0, react_jsx_runtime.jsx)("option", {\n value: member.name,\n children: member.name\n }, member.name))]\n })] }), (0, react_jsx_runtime.jsxs)("label", { children: [\n t("plan.task.dependencies"),\n (0, react_jsx_runtime.jsx)("input", {\n name: "dependencies",\n value: dependencies,\n onChange: (event) => {\n setDependencies(event.currentTarget.value);\n markEdited();\n }\n }),\n (0, react_jsx_runtime.jsx)("small", { children: t("plan.task.dependenciesHint") })\n ] })]\n })\n ]\n }),\n confirmingRemove && (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planConfirm,\n role: "alert",\n children: [\n (0, react_jsx_runtime.jsx)("span", { children: t("plan.removeWarning", { task: task.id }) }),\n (0, react_jsx_runtime.jsx)("button", {\n type: "button",\n onClick: () => {\n setConfirmingRemove(false);\n },\n children: t("plan.cancel")\n }),\n (0, react_jsx_runtime.jsx)("button", {\n type: "button",\n "data-danger": true,\n "data-confirming": true,\n onClick: () => {\n remove();\n },\n children: t("plan.removeConfirm")\n })\n ]\n }),\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planActions,\n children: [\n (0, react_jsx_runtime.jsx)(Feedback, { value: feedback }),\n (0, react_jsx_runtime.jsx)("button", {\n type: "button",\n "data-danger": true,\n onClick: () => {\n setConfirmingRemove(true);\n setFeedback(void 0);\n },\n disabled: busy || confirmingRemove,\n children: t("plan.remove")\n }),\n (0, react_jsx_runtime.jsx)("button", {\n type: "submit",\n disabled: busy || !dirty || subject.trim() === "",\n children: busy ? t("plan.saving") : t("plan.save")\n })\n ]\n })\n ]\n })]\n });\n }\n function StagingPlanEditor({ team, modelDirectory, onContinuePlanning, onDiscarded, t }) {\n const membersId = (0, react.useId)();\n const tasksId = (0, react.useId)();\n const [membersOpen, setMembersOpen] = (0, react.useState)(true);\n const [tasksOpen, setTasksOpen] = (0, react.useState)(true);\n const [newTask, setNewTask] = (0, react.useState)("");\n const [busy, setBusy] = (0, react.useState)(false);\n const [discardArmed, setDiscardArmed] = (0, react.useState)(false);\n const [pendingEditors, setPendingEditors] = (0, react.useState)(/* @__PURE__ */ new Set());\n const [feedback, setFeedback] = (0, react.useState)();\n useDismissSuccess(feedback, setFeedback);\n const dependencyLinks = team.tasks.reduce((total, task) => total + task.dependencies.length, 0);\n const runnable = team.members.length > 0 && team.tasks.length > 0;\n const hasPendingEdits = pendingEditors.size > 0 || newTask.trim() !== "";\n const waitingForFeedback = team.planReviewState === "awaiting_feedback";\n (0, react.useEffect)(() => {\n modelDirectory.load().catch(() => void 0);\n }, [modelDirectory]);\n const onPendingChange = (0, react.useCallback)((key, pending) => {\n setPendingEditors((current) => {\n if (pending === current.has(key)) return current;\n const next = new Set(current);\n if (pending) next.add(key);\n else next.delete(key);\n return next;\n });\n }, []);\n const addTask = async (event) => {\n event.preventDefault();\n setBusy(true);\n setFeedback(void 0);\n try {\n await mutatePlan({\n sessionId: team.captainSessionId,\n teamId: team.teamId,\n action: "add_task",\n subject: newTask,\n dependencies: []\n });\n setNewTask("");\n setFeedback({\n tone: "success",\n message: t("plan.taskAdded")\n });\n setTasksOpen(true);\n } catch (error) {\n setFeedback({\n tone: "error",\n message: t("plan.failed", { message: errorMessage(error) })\n });\n } finally {\n setBusy(false);\n }\n };\n const approve = async () => {\n setBusy(true);\n setFeedback(void 0);\n try {\n await mutatePlan({\n sessionId: team.captainSessionId,\n teamId: team.teamId,\n action: "approve"\n });\n } catch (error) {\n setFeedback({\n tone: "error",\n message: t("plan.failed", { message: errorMessage(error) })\n });\n setBusy(false);\n }\n };\n const continueInChat = async () => {\n if (waitingForFeedback) {\n onContinuePlanning();\n return;\n }\n setBusy(true);\n setFeedback(void 0);\n try {\n await mutatePlan({\n sessionId: team.captainSessionId,\n teamId: team.teamId,\n action: "continue"\n });\n onContinuePlanning();\n } catch (error) {\n setFeedback({\n tone: "error",\n message: t("plan.failed", { message: errorMessage(error) })\n });\n setBusy(false);\n }\n };\n const discard = async () => {\n setBusy(true);\n setFeedback(void 0);\n try {\n await mutatePlan({\n sessionId: team.captainSessionId,\n teamId: team.teamId,\n action: "discard"\n });\n onDiscarded();\n } catch (error) {\n setFeedback({\n tone: "error",\n message: t("plan.failed", { message: errorMessage(error) })\n });\n setBusy(false);\n setDiscardArmed(false);\n }\n };\n return (0, react_jsx_runtime.jsxs)("section", {\n className: ActivityPanel_module_css_default.planEditor,\n "data-staging-editor": true,\n children: [\n (0, react_jsx_runtime.jsxs)("header", {\n className: ActivityPanel_module_css_default.planHeader,\n children: [(0, react_jsx_runtime.jsxs)("span", { children: [(0, react_jsx_runtime.jsxs)("span", { children: [(0, react_jsx_runtime.jsx)("strong", { children: t("plan.title") }), (0, react_jsx_runtime.jsx)("small", { children: t("plan.readySummary", {\n members: team.members.length,\n tasks: team.tasks.length,\n links: dependencyLinks\n }) })] }), (0, react_jsx_runtime.jsx)("em", { children: t("plan.badge") })] }), (0, react_jsx_runtime.jsx)("p", { children: t("plan.description") })]\n }),\n (0, react_jsx_runtime.jsxs)("ol", {\n className: ActivityPanel_module_css_default.planFlow,\n "aria-label": t("plan.flow.aria"),\n children: [\n (0, react_jsx_runtime.jsxs)("li", {\n "data-active": true,\n children: [(0, react_jsx_runtime.jsx)("span", { children: "1" }), t("plan.flow.review")]\n }),\n (0, react_jsx_runtime.jsxs)("li", { children: [(0, react_jsx_runtime.jsx)("span", { children: "2" }), t("plan.flow.spawn")] }),\n (0, react_jsx_runtime.jsxs)("li", { children: [(0, react_jsx_runtime.jsx)("span", { children: "3" }), t("plan.flow.run")] })\n ]\n }),\n (0, react_jsx_runtime.jsxs)("section", {\n className: ActivityPanel_module_css_default.planSection,\n children: [(0, react_jsx_runtime.jsxs)("button", {\n type: "button",\n className: ActivityPanel_module_css_default.planSectionToggle,\n "aria-expanded": membersOpen,\n "aria-controls": membersId,\n onClick: () => {\n setMembersOpen((current) => !current);\n },\n children: [(0, react_jsx_runtime.jsxs)("span", { children: [(0, react_jsx_runtime.jsx)("strong", { children: t("plan.members.title") }), (0, react_jsx_runtime.jsx)("small", { children: t("plan.members.count", { count: team.members.length }) })] }), (0, react_jsx_runtime.jsx)(DisclosureChevron, { open: membersOpen })]\n }), membersOpen && (0, react_jsx_runtime.jsx)("div", {\n id: membersId,\n className: ActivityPanel_module_css_default.planList,\n children: team.members.length === 0 ? (0, react_jsx_runtime.jsx)("p", {\n className: ActivityPanel_module_css_default.planEmpty,\n children: t("plan.members.empty")\n }) : team.members.map((member) => (0, react_jsx_runtime.jsx)(StagedMemberEditor, {\n team,\n member,\n modelDirectory,\n onPendingChange,\n t\n }, member.name))\n })]\n }),\n (0, react_jsx_runtime.jsxs)("section", {\n className: ActivityPanel_module_css_default.planSection,\n children: [(0, react_jsx_runtime.jsxs)("button", {\n type: "button",\n className: ActivityPanel_module_css_default.planSectionToggle,\n "aria-expanded": tasksOpen,\n "aria-controls": tasksId,\n onClick: () => {\n setTasksOpen((current) => !current);\n },\n children: [(0, react_jsx_runtime.jsxs)("span", { children: [(0, react_jsx_runtime.jsx)("strong", { children: t("plan.tasks.title") }), (0, react_jsx_runtime.jsx)("small", { children: t("plan.tasks.count", {\n count: team.tasks.length,\n links: dependencyLinks\n }) })] }), (0, react_jsx_runtime.jsx)(DisclosureChevron, { open: tasksOpen })]\n }), tasksOpen && (0, react_jsx_runtime.jsx)("div", {\n id: tasksId,\n className: ActivityPanel_module_css_default.planList,\n children: team.tasks.length === 0 ? (0, react_jsx_runtime.jsx)("p", {\n className: ActivityPanel_module_css_default.planEmpty,\n children: t("plan.tasks.empty")\n }) : team.tasks.map((task) => (0, react_jsx_runtime.jsx)(StagedTaskEditor, {\n team,\n task,\n onPendingChange,\n t\n }, task.id))\n })]\n }),\n (0, react_jsx_runtime.jsxs)("form", {\n className: ActivityPanel_module_css_default.planNewTask,\n onSubmit: (event) => {\n addTask(event);\n },\n children: [(0, react_jsx_runtime.jsxs)("label", { children: [(0, react_jsx_runtime.jsx)("span", { children: t("plan.newTaskLabel") }), (0, react_jsx_runtime.jsx)("input", {\n name: "newTask",\n value: newTask,\n onChange: (event) => {\n setNewTask(event.currentTarget.value);\n setFeedback(void 0);\n },\n placeholder: t("plan.newTask"),\n disabled: busy\n })] }), (0, react_jsx_runtime.jsx)("button", {\n type: "submit",\n disabled: busy || newTask.trim() === "",\n children: busy ? t("plan.adding") : t("plan.addTask")\n })]\n }),\n (0, react_jsx_runtime.jsxs)("div", {\n className: ActivityPanel_module_css_default.planApproveRow,\n "data-armed": discardArmed || void 0,\n "data-discard": discardArmed || void 0,\n "data-review-state": waitingForFeedback ? "awaiting-feedback" : "awaiting-review",\n children: [\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planApproveCopy,\n children: [(0, react_jsx_runtime.jsx)("strong", { children: discardArmed ? t("plan.discardConfirmTitle") : waitingForFeedback ? t("plan.feedbackTitle") : t("plan.approveTitle") }), (0, react_jsx_runtime.jsx)("small", { children: discardArmed ? t("plan.discardWarning") : waitingForFeedback ? t("plan.feedbackHint") : hasPendingEdits ? t("plan.pendingEdits") : t("plan.approveHint", {\n members: team.members.length,\n tasks: team.tasks.length\n }) })]\n }),\n (0, react_jsx_runtime.jsx)(Feedback, { value: feedback }),\n discardArmed ? (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planApproveActions,\n children: [(0, react_jsx_runtime.jsx)("button", {\n type: "button",\n disabled: busy,\n onClick: () => {\n setDiscardArmed(false);\n },\n children: t("plan.cancel")\n }), (0, react_jsx_runtime.jsx)("button", {\n type: "button",\n "data-plan-discard": true,\n "data-danger": true,\n "data-confirming": true,\n disabled: busy,\n onClick: () => {\n discard();\n },\n children: busy ? t("plan.discarding") : t("plan.discardConfirm")\n })]\n }) : (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planReviewActions,\n children: [(0, react_jsx_runtime.jsx)("button", {\n type: "button",\n "data-plan-approve": true,\n disabled: busy || !runnable || hasPendingEdits,\n onClick: () => {\n approve();\n },\n children: t("plan.approve")\n }), (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.planSecondaryActions,\n children: [(0, react_jsx_runtime.jsx)("button", {\n type: "button",\n "data-plan-continue": true,\n disabled: busy,\n onClick: () => {\n continueInChat();\n },\n children: t(waitingForFeedback ? "plan.returnToChat" : "plan.continue")\n }), (0, react_jsx_runtime.jsx)("button", {\n type: "button",\n "data-plan-discard": true,\n "data-danger": true,\n disabled: busy,\n onClick: () => {\n setDiscardArmed(true);\n setFeedback(void 0);\n },\n children: t("plan.discard")\n })]\n })]\n })\n ]\n })\n ]\n });\n }\n //#endregion\n //#region lib/client/panel-geometry.js\n /** Pure persisted geometry rules for the T Team shell-overlay panel. */\n const PANEL_LAYOUT_STORAGE_KEY = "t-team:activity-panel:v1";\n const DEFAULT_PANEL_LAYOUT = Object.freeze({\n mode: "docked",\n x: 0,\n y: 64,\n width: 388,\n height: 640,\n heightMode: "auto"\n });\n function clamp(value, minimum, maximum) {\n return Math.min(Math.max(value, minimum), maximum);\n }\n function finite(value) {\n return typeof value === "number" && Number.isFinite(value);\n }\n /** Decode one versioned localStorage value, rejecting partial/corrupt state. */\n function parsePanelLayout(value) {\n if (value === null) return DEFAULT_PANEL_LAYOUT;\n try {\n const parsed = JSON.parse(value);\n if (typeof parsed !== "object" || parsed === null) return DEFAULT_PANEL_LAYOUT;\n const record = parsed;\n if (record.mode !== "docked" && record.mode !== "floating" || !finite(record.x) || !finite(record.y) || !finite(record.width) || !finite(record.height)) return DEFAULT_PANEL_LAYOUT;\n return {\n mode: record.mode,\n x: record.x,\n y: record.y,\n width: record.width,\n height: record.height,\n heightMode: record.mode === "floating" && record.heightMode === "manual" ? "manual" : "auto"\n };\n } catch {\n return DEFAULT_PANEL_LAYOUT;\n }\n }\n /** Whether the panel should become a simple inset overlay with no gestures. */\n function compactPanelForBounds(bounds) {\n return bounds.width <= 960;\n }\n /** Docked and compact panels always fit content; floating panels may be user-sized. */\n function panelUsesAutoHeight(layout, bounds) {\n return compactPanelForBounds(bounds) || layout.mode === "docked" || layout.heightMode === "auto";\n }\n /** CSS max-height ceiling that keeps an auto-height panel inside its shell. */\n function panelMaximumHeight(layout, bounds) {\n const bottomInset = compactPanelForBounds(bounds) || layout.mode === "floating" ? 12 : 48;\n return Math.max(1, bounds.height - layout.y - bottomInset);\n }\n /** Resolve persisted state into a visible rectangle inside the current shell. */\n function resolvePanelGeometry(layout, bounds) {\n const boundsWidth = Math.max(1, bounds.width);\n const boundsHeight = Math.max(1, bounds.height);\n if (compactPanelForBounds(bounds)) return {\n ...layout,\n x: 12,\n y: 12,\n width: Math.max(1, boundsWidth - 24),\n height: Math.max(1, boundsHeight - 24)\n };\n const maximumWidth = Math.max(1, Math.min(640, boundsWidth - 24));\n const minimumWidth = Math.min(320, maximumWidth);\n const width = clamp(layout.width, minimumWidth, maximumWidth);\n const maximumHeight = Math.max(1, boundsHeight - 24);\n const minimumHeight = Math.min(360, maximumHeight);\n if (layout.mode === "docked") {\n const y = clamp(64, 12, Math.max(12, boundsHeight - minimumHeight - 12));\n const availableHeight = Math.max(1, boundsHeight - y - 48);\n const height = clamp(availableHeight, Math.min(minimumHeight, availableHeight), maximumHeight);\n const anchorRight = clamp(bounds.anchorRight, 0, boundsWidth);\n const maximumX = Math.max(12, boundsWidth - width - 12);\n return {\n mode: "docked",\n x: clamp(anchorRight - 18 - width, 12, maximumX),\n y,\n width,\n height,\n heightMode: layout.heightMode\n };\n }\n const height = clamp(layout.height, minimumHeight, maximumHeight);\n return {\n mode: "floating",\n x: clamp(layout.x, 12, Math.max(12, boundsWidth - width - 12)),\n y: clamp(layout.y, 12, Math.max(12, boundsHeight - height - 12)),\n width,\n height,\n heightMode: layout.heightMode\n };\n }\n /** Undock without a visual jump by adopting the panel\'s resolved rectangle. */\n function floatPanelLayout(geometry, bounds) {\n return resolvePanelGeometry({\n ...geometry,\n mode: "floating"\n }, bounds);\n }\n /** Return to the right dock, preserving width and restoring content-fit height. */\n function dockPanelLayout(layout, bounds) {\n return resolvePanelGeometry({\n ...layout,\n mode: "docked",\n heightMode: "auto"\n }, bounds);\n }\n /** Translate a floating panel and clamp it back into the visible shell. */\n function movePanelLayout(start, dx, dy, bounds) {\n return resolvePanelGeometry({\n ...start,\n mode: "floating",\n x: start.x + dx,\n y: start.y + dy\n }, bounds);\n }\n /** Resize while keeping the edge opposite the active handle stationary. */\n function resizePanelLayout(start, edge, dx, dy, bounds) {\n if (start.mode === "docked") {\n if (edge !== "left") return resolvePanelGeometry(start, bounds);\n return resolvePanelGeometry({\n ...start,\n width: start.width - dx\n }, bounds);\n }\n const resolved = resolvePanelGeometry(start, bounds);\n const minimumWidth = Math.min(320, resolved.x + resolved.width - 12);\n const minimumHeight = Math.min(360, bounds.height - resolved.y - 12);\n if (edge === "left") {\n const right = resolved.x + resolved.width;\n const maximumWidth = Math.max(1, Math.min(640, right - 12));\n const width = clamp(resolved.width - dx, Math.min(minimumWidth, maximumWidth), maximumWidth);\n return {\n ...resolved,\n x: right - width,\n width\n };\n }\n const maximumHeight = Math.max(1, bounds.height - resolved.y - 12);\n const height = clamp(resolved.height + dy, Math.min(minimumHeight, maximumHeight), maximumHeight);\n if (edge === "bottom") return {\n ...resolved,\n height,\n heightMode: "manual"\n };\n const maximumWidth = Math.max(1, Math.min(640, bounds.width - resolved.x - 12));\n const width = clamp(resolved.width + dx, Math.min(minimumWidth, maximumWidth), maximumWidth);\n return {\n ...resolved,\n width,\n height,\n heightMode: "manual"\n };\n }\n //#endregion\n //#region lib/client/ActivityPanel.js\n /**\n * T Team activity panel: the top-right floater monitoring every team.\n *\n * Modeled on the Claude Code desktop SessionActivityPanel: a shell-overlay\n * panel that docks at the conversation\'s top-right edge by default, can be\n * dragged into a floating window, resized, and folded into an activity badge.\n * On wide viewports the docked panel makes the conversation column yield\n * space; narrow viewports keep a simple inset overlay. It\n * polls the host `/plugins/t-team/state` route for\n * server-side snapshots (durable files + live subagent activity), with a\n * collapsed badge that auto-expands once when activity appears. Archived\n * teams stay available for the owning conversation after live work ends.\n *\n * The floater mounts in ui-layout\'s additive `shell.overlay`; it is not a\n * conversation node \u2014 the in-conversation panel was removed in favor of this\n * always-available monitor.\n * @module t-team/client/activity\n */\n /** Grace before the panel collapses once no team remains. */\n const AUTOCLOSE_GRACE_MS = 2e3;\n /**\n * Page-settle window after mount: activity restored on page load only shows\n * the collapsed badge, so the panel never yanks the conversation column\n * right after load. New activity after this window auto-expands as usual.\n */\n const AUTO_OPEN_SETTLE_MS = 4e3;\n /** Root marker shared with the panel CSS while the shell overlay is expanded. */\n const PANEL_OPEN_ATTRIBUTE = "data-t-team-panel-open";\n /** Shared width concession consumed by the conversation root CSS. */\n const PANEL_SHIFT_PROPERTY = "--t-team-panel-shift";\n const PANEL_CONVERSATION_GAP = 14;\n const MOVE_THRESHOLD = 4;\n const CAPTAIN_ASSIGNEE = "captain";\n function initialPanelLayout() {\n if (typeof window === "undefined") return DEFAULT_PANEL_LAYOUT;\n return parsePanelLayout(window.localStorage.getItem(PANEL_LAYOUT_STORAGE_KEY));\n }\n function initialPanelBounds() {\n if (typeof window === "undefined") return {\n width: 1440,\n height: 900,\n anchorRight: 1440\n };\n return {\n width: window.innerWidth,\n height: window.innerHeight,\n anchorRight: window.innerWidth\n };\n }\n /** Initial-letter fallback for unmatched roles. */\n function memberInitial(name) {\n return name.trim().slice(0, 1).toUpperCase() || "?";\n }\n function stableHash(value) {\n let hash = 0;\n for (let index = 0; index < value.length; index += 1) hash = (hash << 5) - hash + value.charCodeAt(index) | 0;\n return Math.abs(hash);\n }\n const ACCENTS = [\n "var(--dsw-alias-state-business-primary)",\n "var(--dsw-alias-state-success)",\n "var(--dsw-alias-state-danger)",\n "var(--dsw-alias-state-warning)",\n "var(--dsw-alias-label-tertiary)"\n ];\n function accentOf(id) {\n return ACCENTS[stableHash(id) % ACCENTS.length] ?? ACCENTS[0];\n }\n /** Badge text follows the raw task status (finer than the 4 visual states):\n * claimed/pending/failed/cancelled keep their own labels and colors. */\n const TASK_STATUS_LABEL = {\n pending: "task.status.pending",\n claimed: "task.status.claimed",\n in_progress: "task.status.inProgress",\n completed: "task.status.completed",\n failed: "task.status.failed",\n cancelled: "task.status.cancelled"\n };\n function taskStatusLabel(status, t) {\n const key = TASK_STATUS_LABEL[status];\n return key === void 0 ? status : t(key);\n }\n function formatTaskIds(ids, t) {\n return ids.join(t("format.listSeparator"));\n }\n function taskTitle(task, model) {\n const extras = [\n task.kind,\n task.round === void 0 ? void 0 : `r${task.round}`,\n task.verdict,\n model === "" ? void 0 : model\n ].filter((item) => item !== void 0);\n return extras.length === 0 ? `${task.id} \xB7 ${task.subject}` : `${task.id} \xB7 ${task.subject} \xB7 ${extras.join(" \xB7 ")}`;\n }\n /** Badge/bar coloring key: visual state, widened for terminal statuses. */\n function taskTone(state, status) {\n if (status === "failed") return "failed";\n if (status === "cancelled") return "cancelled";\n return state;\n }\n function Chevron({ open }) {\n return (0, react_jsx_runtime.jsx)("svg", {\n className: ActivityPanel_module_css_default.chevron,\n "data-open": open,\n width: "9",\n height: "9",\n viewBox: "0 0 10 10",\n fill: "none",\n stroke: "currentColor",\n strokeWidth: "1.5",\n strokeLinecap: "round",\n "aria-hidden": true,\n children: (0, react_jsx_runtime.jsx)("path", { d: "M3.5 2l3 3-3 3" })\n });\n }\n function WorkGlyph({ active }) {\n return (0, react_jsx_runtime.jsx)("svg", {\n className: ActivityPanel_module_css_default.workGlyph,\n "data-active": active,\n width: "11",\n height: "11",\n viewBox: "0 0 11 11",\n fill: "currentColor",\n "aria-hidden": true,\n children: [\n [0, 0],\n [4.2, 0],\n [8.4, 0],\n [0, 4.2],\n [4.2, 4.2],\n [8.4, 4.2]\n ].map(([x, y], index) => (0, react_jsx_runtime.jsx)("rect", {\n x,\n y,\n width: "2.6",\n height: "2.6",\n rx: ".6",\n style: { animationDelay: `${index * .15}s` }\n }, `${x}:${y}`))\n });\n }\n /** Collapsed badge: an always-visible corner pill while any team exists. */\n function CollapsedBadge({ count, busy, onClick, t }) {\n return (0, react_jsx_runtime.jsxs)("button", {\n type: "button",\n className: ActivityPanel_module_css_default.badge,\n "data-t-team-collapsed": true,\n "data-busy": busy,\n onClick,\n "aria-label": t("activity.badgeAria", { count }),\n children: [(0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.badgeDot,\n "data-busy": busy,\n "aria-hidden": true\n }), (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.badgeCount,\n children: count\n })]\n });\n }\n function memberStateLabel(member, tasks, historic, t) {\n const owned = tasks.filter((task) => task.assignee === member.name);\n if (member.activity === "working") return t("member.state.working");\n if (owned.some((task) => task.status === "failed")) return t("member.state.failed");\n if (owned.some((task) => task.state === "blocked")) return t("member.state.waiting");\n if (owned.length > 0 && owned.every((task) => task.status === "completed")) return t("member.state.delivered");\n if (member.status === "removed") return t(historic ? "member.state.left" : "member.state.removed");\n if (owned.length > 0) return t("member.state.pending");\n return t("member.state.unassigned");\n }\n function memberStatusText(member, tasks, t) {\n const owned = tasks.filter((task) => task.assignee === member.name);\n const current = owned.find((task) => task.id === member.currentTask);\n const blocked = owned.find((task) => task.state === "blocked");\n if (member.activity === "working" && current !== void 0) {\n const model = taskModelLabel(current, [member]);\n return model === "" ? t("member.status.executing", { taskId: current.id }) : t("member.status.executingModel", {\n taskId: current.id,\n model\n });\n }\n if (member.activity === "working") return t("member.status.working");\n if (blocked !== void 0) {\n const dependency = tasks.find((task) => blocked.dependencies.includes(task.id) && task.state !== "completed");\n if (dependency !== void 0) return t("member.status.waitingOn", {\n taskId: dependency.id,\n assignee: dependency.assignee || t("task.assignee.unclaimed")\n });\n return t("member.status.waitingPrerequisite");\n }\n if (member.total === 0) return t("member.status.waitingAssignment");\n if (member.done === member.total) return t("member.status.delivered");\n return t(member.activity === "idle" ? "member.status.idle" : "member.status.unknown");\n }\n function compactTaskLabel(subject) {\n const withoutVerb = subject.replace(/^\u5F00\u53D1\\s*/u, "").replace(/^\\d+[-_.\u3001\\s]*/u, "");\n const head = withoutVerb.split(/[\uFF08(\xB7\uFF1A:]/u)[0]?.trim() ?? withoutVerb;\n return head.length > 18 ? `${head.slice(0, 17)}\u2026` : head;\n }\n function taskSummary(team, t, discarded = false) {\n const completed = team.tasks.filter((task) => task.status === "completed");\n const cancelled = team.tasks.filter((task) => task.status === "cancelled");\n const running = team.tasks.filter((task) => task.state === "running");\n const blocked = team.tasks.filter((task) => task.state === "blocked");\n const ready = team.tasks.filter((task) => task.state === "open" && task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled");\n const failed = team.tasks.filter((task) => task.status === "failed");\n if (discarded) return t("task.summary.discarded", { count: team.tasks.length });\n if (team.tasks.length === 0) return t("task.summary.waitingBreakdown");\n if (team.phase === "staged") return t("task.summary.staged", { count: team.tasks.length });\n if (completed.length === team.tasks.length) return t("task.summary.allDelivered", { count: completed.length });\n if (completed.length + cancelled.length + failed.length === team.tasks.length) return t("task.summary.ended", {\n completed: completed.length,\n cancelled: cancelled.length,\n failed: failed.length\n });\n if (failed.length > 0 && running.length === 0 && ready.length === 0 && blocked.length === 0) return t("task.summary.failedSettled", { count: failed.length });\n if (blocked.length > 0 && running.length > 0) return t("task.summary.blockedAndRunning", {\n tasks: formatTaskIds(blocked.slice(0, 3).map((task) => task.id), t),\n more: blocked.length > 3 ? t("task.summary.more", { count: blocked.length - 3 }) : ""\n });\n if (running.length > 0) return t("task.summary.running", { tasks: formatTaskIds(running.map((task) => task.id), t) });\n if (ready.length > 0) return t("task.summary.ready", { tasks: formatTaskIds(ready.map((task) => task.id), t) });\n if (blocked.length > 0) return t("task.summary.blocked", { tasks: formatTaskIds(blocked.map((task) => task.id), t) });\n return t("task.summary.waitingSchedule");\n }\n function ProgressOverview({ team, t, discarded = false }) {\n const running = discarded ? 0 : team.tasks.filter((task) => task.state === "running").length;\n const blocked = discarded ? 0 : team.tasks.filter((task) => task.state === "blocked").length;\n const completed = discarded ? 0 : team.tasks.filter((task) => task.status === "completed").length;\n const settled = !discarded && team.tasks.length > 0 && team.tasks.every((task) => task.status === "completed" || task.status === "failed" || task.status === "cancelled");\n const summaryTone = discarded ? "discarded" : blocked > 0 ? "warning" : settled ? "completed" : "running";\n return (0, react_jsx_runtime.jsxs)("section", {\n className: ActivityPanel_module_css_default.progressOverview,\n "aria-label": t("progress.aria"),\n "data-progress-summary": true,\n children: [\n (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.progressTitle,\n children: t("progress.title")\n }),\n team.tasks.length > 0 ? (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.progressSegments,\n "aria-hidden": true,\n children: team.tasks.map((task) => (0, react_jsx_runtime.jsx)("span", { "data-state": discarded ? "cancelled" : taskTone(task.state, task.status) }, task.id))\n }) : (0, react_jsx_runtime.jsx)("span", { className: ActivityPanel_module_css_default.progressEmpty }),\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.progressLegend,\n children: [\n (0, react_jsx_runtime.jsx)("span", {\n "data-state": "running",\n children: t("progress.running", { count: running })\n }),\n (0, react_jsx_runtime.jsx)("span", {\n "data-state": "blocked",\n children: t("progress.blocked", { count: blocked })\n }),\n (0, react_jsx_runtime.jsx)("span", {\n "data-state": "completed",\n children: t("progress.delivered", { count: completed })\n })\n ]\n }),\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.progressSummary,\n "data-state": summaryTone,\n children: [(0, react_jsx_runtime.jsx)("span", { className: ActivityPanel_module_css_default.progressSummaryDot }), (0, react_jsx_runtime.jsx)("span", { children: taskSummary(team, t, discarded) })]\n })\n ]\n });\n }\n function DependencyMap({ tasks, members, t, discarded = false }) {\n const [open, setOpen] = (0, react.useState)(true);\n const [hoverTaskId, setHoverTaskId] = (0, react.useState)(null);\n const [keyboardTaskId, setKeyboardTaskId] = (0, react.useState)(null);\n const [pinnedTaskId, setPinnedTaskId] = (0, react.useState)(null);\n const hoverTimer = (0, react.useRef)(null);\n const focusedTaskId = dependencyFocusTaskId(pinnedTaskId, keyboardTaskId, hoverTaskId);\n const layout = (0, react.useMemo)(() => compactDagLayout(tasks), [tasks]);\n const parallel = (0, react.useMemo)(() => usesParallelTaskGrid(tasks), [tasks]);\n const related = (0, react.useMemo)(() => focusedTaskId === null ? null : relatedTaskIds(focusedTaskId, tasks), [focusedTaskId, tasks]);\n const scheduleHover = (id) => {\n if (hoverTimer.current !== null) {\n clearTimeout(hoverTimer.current);\n hoverTimer.current = null;\n }\n if (id === null) {\n setHoverTaskId(null);\n return;\n }\n hoverTimer.current = setTimeout(() => {\n hoverTimer.current = null;\n setHoverTaskId(id);\n }, 180);\n };\n (0, react.useEffect)(() => () => {\n if (hoverTimer.current !== null) clearTimeout(hoverTimer.current);\n }, []);\n (0, react.useEffect)(() => {\n const onKeyDown = (event) => {\n if (event.key === "Escape") setPinnedTaskId(null);\n };\n window.addEventListener("keydown", onKeyDown);\n return () => {\n window.removeEventListener("keydown", onKeyDown);\n };\n }, []);\n if (tasks.length === 0) return null;\n const fallbackTask = tasks.find((task) => task.state === "blocked") ?? tasks.find((task) => task.state === "running") ?? tasks[0];\n const detailTask = tasks.find((task) => task.id === focusedTaskId) ?? fallbackTask;\n const detailModel = taskModelLabel(detailTask, members);\n const waitingOn = detailTask.dependencies.filter((dependency) => tasks.find((task) => task.id === dependency)?.status !== "completed");\n const dependents = tasks.filter((task) => task.dependencies.includes(detailTask.id));\n return (0, react_jsx_runtime.jsxs)("section", {\n className: ActivityPanel_module_css_default.dependencySection,\n "aria-label": t("dependency.aria"),\n "data-dependency-map": true,\n children: [(0, react_jsx_runtime.jsxs)("header", {\n className: ActivityPanel_module_css_default.sectionHead,\n children: [(0, react_jsx_runtime.jsxs)("button", {\n type: "button",\n className: ActivityPanel_module_css_default.sectionToggleTitle,\n onClick: () => {\n setOpen((current) => !current);\n },\n "aria-expanded": open,\n children: [\n (0, react_jsx_runtime.jsx)(Chevron, { open }),\n (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutline16, {}),\n " ",\n t(parallel ? "dependency.parallel" : "dependency.title")\n ]\n }), (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.sectionHint,\n children: pinnedTaskId === null ? t(parallel ? "dependency.hint.parallel" : "dependency.hint.chain") : t("dependency.hint.pinned", { taskId: pinnedTaskId })\n })]\n }), open && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("div", {\n className: ActivityPanel_module_css_default.dagViewport,\n children: (0, react_jsx_runtime.jsxs)("div", {\n className: ActivityPanel_module_css_default.dagCanvas,\n "data-layout": parallel ? "parallel" : "dependency",\n style: parallel ? void 0 : {\n width: layout.width,\n height: layout.height\n },\n children: [!parallel && (0, react_jsx_runtime.jsx)("svg", {\n className: ActivityPanel_module_css_default.dagEdges,\n width: layout.width,\n height: layout.height,\n "aria-hidden": true,\n children: layout.edges.map((edge) => {\n const active = related !== null && related.has(edge.from) && related.has(edge.to);\n return (0, react_jsx_runtime.jsx)("path", {\n d: edge.path,\n "data-active": active,\n "data-dimmed": related !== null && !active\n }, `${edge.from}:${edge.to}`);\n })\n }), layout.nodes.map(({ task, x, y }) => {\n const model = taskModelLabel(task, members);\n const shortModel = compactModelLabel(model);\n return (0, react_jsx_runtime.jsxs)("button", {\n type: "button",\n className: ActivityPanel_module_css_default.dagNode,\n style: parallel ? { height: 30 } : {\n left: x,\n top: y,\n width: 92,\n height: 30\n },\n "data-task-id": task.id,\n "data-state": discarded ? "cancelled" : taskTone(task.state, task.status),\n "data-task-model": model || void 0,\n "data-focused": related?.has(task.id) ?? false,\n "data-dimmed": related !== null && !related.has(task.id),\n "aria-pressed": pinnedTaskId === task.id,\n title: taskTitle(task, model),\n onClick: () => {\n setPinnedTaskId((current) => current === task.id ? null : task.id);\n },\n onMouseEnter: () => {\n scheduleHover(task.id);\n },\n onMouseLeave: () => {\n scheduleHover(null);\n },\n onFocus: () => {\n setKeyboardTaskId(task.id);\n },\n onBlur: () => {\n setKeyboardTaskId(null);\n },\n children: [\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.dagNodeHead,\n children: [(0, react_jsx_runtime.jsx)("span", { className: ActivityPanel_module_css_default.dagNodeDot }), task.id]\n }),\n (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.dagNodeLabel,\n children: task.state === "running" && shortModel !== "" ? shortModel : compactTaskLabel(task.subject)\n }),\n task.state === "running" && (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.dagRunningState,\n "aria-label": t("task.runningAria"),\n children: (0, react_jsx_runtime.jsx)(WorkGlyph, { active: true })\n })\n ]\n }, task.id);\n })]\n })\n }), (0, react_jsx_runtime.jsxs)("section", {\n className: ActivityPanel_module_css_default.taskDetail,\n "data-task-detail": detailTask.id,\n children: [\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.taskDetailHead,\n children: [\n (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.taskDetailId,\n children: detailTask.id\n }),\n (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.taskDetailSubject,\n title: detailTask.subject,\n children: detailTask.subject.replace(/^\u5F00\u53D1\\s*/u, "")\n }),\n (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.taskDetailBadge,\n "data-state": discarded ? "cancelled" : taskTone(detailTask.state, detailTask.status),\n children: discarded ? t("task.status.notRun") : taskStatusLabel(detailTask.status, t)\n })\n ]\n }),\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.taskDetailLine,\n children: [\n detailTask.assignee || t("task.assignee.unclaimed"),\n " \xB7 ",\n discarded ? t("task.detail.notRun") : detailTask.status === "completed" ? t("task.detail.completed") : detailTask.dependencies.length === 0 ? t("task.detail.noPrerequisite") : waitingOn.length === 0 ? t("task.detail.ready") : t("task.detail.waitingOn", { tasks: formatTaskIds(waitingOn, t) })\n ]\n }),\n detailModel !== "" && (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.taskDetailModel,\n "data-task-model": detailModel,\n children: t("task.model", { model: detailModel })\n }),\n (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.taskDetailMeta,\n children: dependents.length === 0 ? t("task.detail.noDownstream") : t("task.detail.unlocks", { tasks: formatTaskIds(dependents.map((task) => task.id), t) })\n })\n ]\n })] })]\n });\n }\n function TeamSection({ team, modelDirectory, onContinuePlanning, onDiscarded, onNavigate, t, historic = false }) {\n const [membersOpen, setMembersOpen] = (0, react.useState)(true);\n const [stopOpen, setStopOpen] = (0, react.useState)(false);\n const [stopping, setStopping] = (0, react.useState)(false);\n const [stopError, setStopError] = (0, react.useState)("");\n const discarded = historic && team.phase === "staged";\n const stopped = !historic && team.halted === true;\n const busyCount = team.members.filter((member) => member.activity === "working").length;\n const assignedCount = team.tasks.filter((task) => task.assignee !== "" && task.assignee !== CAPTAIN_ASSIGNEE).length;\n const captainOwned = team.tasks.filter((task) => task.assignee === CAPTAIN_ASSIGNEE && task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled");\n const captainBusy = captainOwned.length > 0;\n const captainTaskIds = formatTaskIds(captainOwned.map((task) => task.id), t);\n const completedCount = team.tasks.filter((task) => task.status === "completed").length;\n const allCompleted = team.tasks.length > 0 && completedCount === team.tasks.length;\n const allSettled = team.tasks.length > 0 && team.tasks.every((task) => task.status === "completed" || task.status === "failed" || task.status === "cancelled");\n const unfinishedCount = team.tasks.filter((task) => task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled").length;\n const canStop = !historic && team.phase === "running" && team.halted !== true && teamIsActive(team);\n const stopTeam = async () => {\n if (stopping) return;\n setStopping(true);\n setStopError("");\n try {\n const response = await fetch(ACTIVITY_HALT_URL, {\n method: "POST",\n cache: "no-store",\n headers: { "content-type": "application/json" },\n body: JSON.stringify({\n sessionId: team.captainSessionId,\n teamId: team.teamId\n })\n });\n if (!response.ok) {\n let message = t("team.stopRequestFailed");\n try {\n const body = await response.json();\n if (typeof body.error === "string" && body.error.trim() !== "") message = body.error;\n } catch {}\n throw new Error(message);\n }\n setStopOpen(false);\n } catch (error) {\n setStopError(t("team.stopFailed", { message: error instanceof Error ? error.message : String(error) }));\n } finally {\n setStopping(false);\n }\n };\n return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("section", {\n className: ActivityPanel_module_css_default.team,\n "data-team-id": team.teamId,\n children: [\n (0, react_jsx_runtime.jsxs)("header", {\n className: ActivityPanel_module_css_default.teamHead,\n children: [\n (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.teamName,\n title: team.name,\n children: team.name\n }),\n historic && (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.historicPill,\n children: t(discarded ? "team.discarded" : "team.ended")\n }),\n stopped && (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.historicPill,\n children: t("team.stopped")\n }),\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.teamStats,\n children: [\n (0, react_jsx_runtime.jsx)("span", {\n "data-stat": "members",\n children: t("team.stats.members", { count: team.members.length })\n }),\n (0, react_jsx_runtime.jsx)("span", {\n "data-stat": "tasks",\n children: t("team.stats.completed", {\n completed: completedCount,\n total: team.tasks.length\n })\n }),\n (0, react_jsx_runtime.jsx)("span", {\n "data-stat": "messages",\n children: t("team.stats.messages", { count: team.messageCount })\n })\n ]\n }),\n canStop && (0, react_jsx_runtime.jsx)("button", {\n type: "button",\n className: ActivityPanel_module_css_default.teamStopButton,\n "aria-label": t("team.stop"),\n title: t("team.stop"),\n onClick: () => {\n setStopError("");\n setStopOpen(true);\n },\n children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconStopFill16, {})\n })\n ]\n }),\n team.phase === "staged" && !historic && modelDirectory !== void 0 && onContinuePlanning !== void 0 && onDiscarded !== void 0 && (0, react_jsx_runtime.jsx)(StagingPlanEditor, {\n team,\n modelDirectory,\n onContinuePlanning,\n onDiscarded,\n t\n }),\n (0, react_jsx_runtime.jsxs)("section", {\n className: ActivityPanel_module_css_default.delegationSection,\n "aria-label": t("delegation.aria"),\n "data-delegation-map": true,\n children: [\n (0, react_jsx_runtime.jsxs)("div", {\n className: ActivityPanel_module_css_default.captainNode,\n children: [\n (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.captainAvatar,\n children: (0, react_jsx_runtime.jsx)("img", {\n className: ActivityPanel_module_css_default.leadAvatar,\n src: LEAD_ART,\n alt: "",\n "aria-hidden": true\n })\n }),\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.captainInfo,\n children: [(0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.captainLine,\n children: [(0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.captainName,\n children: t("captain.name")\n }), (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.captainRole,\n children: t("captain.role")\n })]\n }), (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.captainSummary,\n children: discarded ? t("captain.summary.discarded", {\n tasks: team.tasks.length,\n members: team.members.length\n }) : captainBusy ? t("captain.summary.withTakeover", {\n tasks: assignedCount,\n captainTasks: captainTaskIds\n }) : team.phase === "staged" ? t(team.planReviewState === "awaiting_feedback" ? "captain.summary.awaitingFeedback" : "captain.summary.staged", {\n tasks: team.tasks.length,\n members: team.members.length\n }) : t("captain.summary", {\n tasks: assignedCount,\n members: team.members.length\n })\n })]\n }),\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.captainState,\n "data-busy": captainBusy || busyCount > 0,\n children: [(0, react_jsx_runtime.jsx)(WorkGlyph, { active: captainBusy || busyCount > 0 }), discarded ? t("captain.state.discarded") : captainBusy ? t("captain.state.takeover", { tasks: captainTaskIds }) : team.phase === "staged" ? t(team.planReviewState === "awaiting_feedback" ? "captain.state.awaitingFeedback" : "captain.state.staged") : busyCount > 0 ? t("captain.state.working", { count: busyCount }) : t(allCompleted ? "captain.state.collected" : allSettled ? "captain.state.settled" : "captain.state.waiting")]\n })\n ]\n }),\n (0, react_jsx_runtime.jsx)(ProgressOverview, {\n team,\n t,\n discarded\n }),\n (0, react_jsx_runtime.jsxs)("button", {\n type: "button",\n className: ActivityPanel_module_css_default.membersToggle,\n onClick: () => {\n setMembersOpen((current) => !current);\n },\n "aria-expanded": membersOpen,\n "data-members-toggle": true,\n children: [(0, react_jsx_runtime.jsxs)("span", { children: [(0, react_jsx_runtime.jsx)(Chevron, { open: membersOpen }), t("members.toggle", { count: team.members.length })] }), (0, react_jsx_runtime.jsx)("span", { children: t(membersOpen ? "members.collapse" : "members.expand") })]\n }),\n membersOpen && (0, react_jsx_runtime.jsxs)("div", {\n className: ActivityPanel_module_css_default.delegationTree,\n children: [team.members.length === 0 && (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.emptyHint,\n children: t("members.empty")\n }), team.members.map((member) => {\n const owned = team.tasks.filter((task) => task.assignee === member.name);\n const memberModel = memberRouteLabel(member);\n return (0, react_jsx_runtime.jsxs)("div", {\n className: ActivityPanel_module_css_default.memberBlock,\n "data-activity": member.activity,\n children: [\n (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.memberBranch,\n "aria-hidden": true,\n children: (0, react_jsx_runtime.jsx)("span", {})\n }),\n (0, react_jsx_runtime.jsxs)("button", {\n type: "button",\n className: ActivityPanel_module_css_default.memberRow,\n "data-activity": member.activity,\n onClick: () => {\n if (member.id !== "") onNavigate(team.captainSessionId, member.id);\n },\n children: [\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.memberAvatar,\n "data-unread": member.unread > 0,\n children: [memberArtUrl(member.name, member.role) !== null ? (0, react_jsx_runtime.jsx)("img", {\n className: ActivityPanel_module_css_default.memberArt,\n src: memberArtUrl(member.name, member.role) ?? "",\n alt: "",\n "aria-hidden": true\n }) : (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.memberInitial,\n style: { background: accentOf(member.id) },\n children: memberInitial(member.name)\n }), (0, react_jsx_runtime.jsx)("img", {\n className: ActivityPanel_module_css_default.stateArt,\n "data-activity": member.activity,\n src: ACTION_ART[member.activity],\n alt: "",\n "aria-hidden": true\n })]\n }),\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.memberInfo,\n children: [(0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.memberLine,\n children: [\n (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.memberName,\n children: member.name\n }),\n member.role !== "" && (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.memberRole,\n children: member.role\n }),\n memberModel !== "" && (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.memberModel,\n role: "img",\n "data-member-model": memberModel,\n title: memberModel,\n "aria-label": memberModel,\n children: compactModelLabel(memberModel)\n }),\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.memberState,\n "data-activity": member.activity,\n children: [(0, react_jsx_runtime.jsx)(WorkGlyph, { active: member.activity === "working" }), discarded ? t("member.state.notCreated") : stopped ? t("member.state.stopped") : team.phase === "staged" ? t("member.state.staged") : memberStateLabel(member, team.tasks, historic, t)]\n })\n ]\n }), (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.memberStatusLine,\n children: discarded ? t("member.status.discarded") : stopped ? t("member.status.stopped") : team.phase === "staged" ? t("member.status.staged") : historic && owned.length > 0 && owned.every((task) => task.status === "completed" || task.status === "failed" || task.status === "cancelled") ? t("member.status.settled") : memberStatusText(member, team.tasks, t)\n })]\n }),\n (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.memberCount,\n children: [\n member.done,\n "/",\n member.total\n ]\n })\n ]\n }),\n (0, react_jsx_runtime.jsxs)("div", {\n className: ActivityPanel_module_css_default.assignmentLine,\n children: [(0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.assignmentLabel,\n children: t(discarded ? "assignment.discarded" : team.phase === "staged" ? "assignment.staged" : "assignment.label")\n }), (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.assignmentTasks,\n children: owned.length === 0 ? (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.taskEmpty,\n children: t("assignment.empty")\n }) : owned.map((task) => {\n const model = taskModelLabel(task, team.members);\n const shortModel = compactModelLabel(model);\n return (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.assignmentChip,\n "data-state": discarded ? "cancelled" : taskTone(task.state, task.status),\n "data-task-model": model || void 0,\n title: taskTitle(task, model),\n children: task.state === "running" && shortModel !== "" ? `${task.id} \xB7 ${shortModel}` : task.id\n }, task.id);\n })\n })]\n })\n ]\n }, member.id || member.name);\n })]\n })\n ]\n }),\n (0, react_jsx_runtime.jsx)(DependencyMap, {\n tasks: team.tasks,\n members: team.members,\n t,\n discarded\n })\n ]\n }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {\n open: stopOpen,\n onClose: () => {\n if (!stopping) setStopOpen(false);\n },\n title: t("team.stopTitle", { team: team.name }),\n closeLabel: t("plan.cancel"),\n description: t("team.stopDescription", {\n tasks: unfinishedCount,\n members: busyCount\n }),\n footer: (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.stopModalActions,\n children: [(0, react_jsx_runtime.jsx)("button", {\n type: "button",\n disabled: stopping,\n onClick: () => {\n setStopOpen(false);\n },\n children: t("team.stopCancel")\n }), (0, react_jsx_runtime.jsxs)("button", {\n type: "button",\n "data-danger": true,\n disabled: stopping,\n onClick: () => {\n stopTeam();\n },\n children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconStopFill16, {}), stopping ? t("team.stopping") : t("team.stopConfirm")]\n })]\n }),\n children: stopError !== "" && (0, react_jsx_runtime.jsxs)("p", {\n className: ActivityPanel_module_css_default.stopModalError,\n role: "alert",\n children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconWarningOutline16, {}), stopError]\n })\n })] });\n }\n /** Legacy conversation cards may outlive their host archive. Project their\n * durable roster through the same rebuilt panel instead of a second UI. */\n function historicCardTeam(data, owner) {\n return {\n workspace: "",\n teamId: data.teamId,\n name: data.teamName,\n captainSessionId: data.captainSessionId || owner,\n phase: "running",\n members: data.members.map((member) => ({\n ...member,\n status: "removed",\n activity: "idle",\n progress: 0,\n done: 0,\n total: 0,\n currentTask: "",\n unread: 0\n })),\n tasks: [],\n messageCount: 0,\n captainInbox: []\n };\n }\n function ActivityPanel({ sessionsList, modelDirectories, openMember, t, conversationVisible = true }) {\n const navigateToSession = (parentId, childId) => {\n setOpen(false);\n setWasActive(false);\n openMember(parentId, childId);\n };\n const [open, setOpen] = (0, react.useState)(false);\n const [openOwner, setOpenOwner] = (0, react.useState)();\n const [autoOpened, setAutoOpened] = (0, react.useState)(false);\n const [wasActive, setWasActive] = (0, react.useState)(false);\n const [historic, setHistoric] = (0, react.useState)(/* @__PURE__ */ new Map());\n const [layout, setLayout] = (0, react.useState)(initialPanelLayout);\n const [bounds, setBounds] = (0, react.useState)(initialPanelBounds);\n const [interaction, setInteraction] = (0, react.useState)(null);\n const panelRef = (0, react.useRef)(null);\n const boundsRef = (0, react.useRef)(bounds);\n const gestureRef = (0, react.useRef)(null);\n const frameRef = (0, react.useRef)(null);\n const pendingLayoutRef = (0, react.useRef)(null);\n const current = (0, react.useSyncExternalStore)(sessionsList.subscribe, sessionsList.getSnapshot).current;\n const autoOpenTrackerRef = (0, react.useRef)({\n sessionId: current,\n restoreComplete: false,\n liveTeamIds: /* @__PURE__ */ new Set()\n });\n const monitorTargets = (0, react.useSyncExternalStore)(subscribeActivityMonitorTargets, getActivityMonitorTargetsSnapshot);\n const returnToComposer = () => {\n setOpen(false);\n setOpenOwner(void 0);\n window.requestAnimationFrame(() => {\n document.querySelector("[data-composer-card] [contenteditable=\\"true\\"][role=\\"textbox\\"], [data-composer-card] textarea")?.focus();\n });\n };\n const { teams, archivedTeams } = (0, react.useSyncExternalStore)(subscribeActivitySnapshots, getActivitySnapshotsSnapshot);\n const currentTargets = (0, react.useMemo)(() => current === void 0 ? [] : monitorTargets.filter((target) => target.sessionId === current), [current, monitorTargets]);\n const currentRef = (0, react.useRef)(current);\n (0, react.useEffect)(() => {\n currentRef.current = current;\n }, [current]);\n const mountedAtRef = (0, react.useRef)(performance.now());\n const expanded = conversationVisible && activityPanelExpandedForSession(open, openOwner, current);\n const geometry = (0, react.useMemo)(() => resolvePanelGeometry(layout, bounds), [layout, bounds]);\n const compact = compactPanelForBounds(bounds);\n const commitLayout = (0, react.useCallback)((next) => {\n setLayout(next);\n }, []);\n (0, react.useEffect)(() => {\n window.localStorage.setItem(PANEL_LAYOUT_STORAGE_KEY, JSON.stringify(layout));\n }, [layout]);\n (0, react.useLayoutEffect)(() => {\n const overlay = document.querySelector("[data-shell-overlay]");\n if (overlay === null) return;\n const conversation = document.querySelector("[data-phase=\'active\']");\n let frame = null;\n const measure = () => {\n frame = null;\n const overlayRect = overlay.getBoundingClientRect();\n const conversationRect = conversation?.getBoundingClientRect();\n const next = {\n width: overlayRect.width,\n height: overlayRect.height,\n anchorRight: conversationRect === void 0 ? overlayRect.width : Math.min(Math.max(conversationRect.right - overlayRect.left, 0), overlayRect.width)\n };\n const previous = boundsRef.current;\n if (previous.width === next.width && previous.height === next.height && previous.anchorRight === next.anchorRight) return;\n boundsRef.current = next;\n setBounds(next);\n };\n const scheduleMeasure = () => {\n frame ??= requestAnimationFrame(measure);\n };\n measure();\n const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(scheduleMeasure);\n observer?.observe(overlay);\n if (conversation !== null) observer?.observe(conversation);\n window.addEventListener("resize", scheduleMeasure);\n return () => {\n if (frame !== null) cancelAnimationFrame(frame);\n observer?.disconnect();\n window.removeEventListener("resize", scheduleMeasure);\n };\n }, [current]);\n (0, react.useLayoutEffect)(() => {\n const tracker = autoOpenTrackerRef.current;\n if (tracker.sessionId !== current) {\n tracker.sessionId = current;\n tracker.restoreComplete = false;\n tracker.liveTeamIds = /* @__PURE__ */ new Set();\n setWasActive(false);\n setAutoOpened(false);\n }\n if (openOwner === void 0 || openOwner === current) return;\n setOpen(false);\n setOpenOwner(void 0);\n }, [current, openOwner]);\n (0, react.useLayoutEffect)(() => {\n const root = document.documentElement;\n if (expanded && geometry.mode === "docked" && !compact) {\n root.setAttribute(PANEL_OPEN_ATTRIBUTE, "");\n root.style.setProperty(PANEL_SHIFT_PROPERTY, `${geometry.width + PANEL_CONVERSATION_GAP + 18}px`);\n } else {\n root.removeAttribute(PANEL_OPEN_ATTRIBUTE);\n root.style.removeProperty(PANEL_SHIFT_PROPERTY);\n }\n return () => {\n root.removeAttribute(PANEL_OPEN_ATTRIBUTE);\n root.style.removeProperty(PANEL_SHIFT_PROPERTY);\n };\n }, [\n compact,\n expanded,\n geometry.mode,\n geometry.width\n ]);\n (0, react.useEffect)(() => {\n if (current === void 0) return;\n const controller = startActivityPolling(currentTargets, { discoverySessionId: current });\n let active = true;\n const tracker = autoOpenTrackerRef.current;\n if (tracker.sessionId === current && !tracker.restoreComplete) controller.firstTick.then(() => {\n const latest = autoOpenTrackerRef.current;\n if (!active || latest.sessionId !== current || latest.restoreComplete) return;\n latest.liveTeamIds = new Set(getActivitySnapshotsSnapshot().teams.filter((team) => team.captainSessionId === current).map((team) => team.teamId));\n latest.restoreComplete = true;\n });\n return () => {\n active = false;\n controller.stop();\n };\n }, [current, currentTargets]);\n (0, react.useEffect)(() => {\n const onOpenPanel = (event) => {\n const activeSession = currentRef.current;\n if (activeSession === void 0) return;\n setOpenOwner(activeSession);\n setOpen(true);\n const detail = event.detail;\n if (detail?.teamId !== void 0) {\n const owner = detail.captainSessionId !== "" ? detail.captainSessionId : currentRef.current ?? "";\n const teamKey = `${owner}:${detail.teamId}`;\n setHistoric((previous) => {\n const next = new Map(previous);\n next.set(teamKey, {\n data: detail,\n owner\n });\n return next;\n });\n }\n };\n window.addEventListener(OPEN_PANEL_EVENT, onOpenPanel);\n return () => {\n window.removeEventListener(OPEN_PANEL_EVENT, onOpenPanel);\n };\n }, []);\n const visibleTeams = (0, react.useMemo)(() => current === void 0 ? [] : teams.filter((team) => team.captainSessionId === current), [teams, current]);\n const visibleHistoric = (0, react.useMemo)(() => current === void 0 ? [] : [...historic.values()].filter(({ data, owner }) => owner === current && !teams.some((live) => live.captainSessionId === current && live.teamId === data.teamId) && !archivedTeams.some((archived) => archived.captainSessionId === current && archived.teamId === data.teamId)), [\n historic,\n current,\n teams,\n archivedTeams\n ]);\n const visibleArchived = (0, react.useMemo)(() => current === void 0 ? [] : archivedTeams.filter((team) => team.captainSessionId === current && !teams.some((live) => live.captainSessionId === current && live.teamId === team.teamId)), [\n archivedTeams,\n current,\n teams\n ]);\n const visibleCount = visibleTeams.length + visibleArchived.length + visibleHistoric.length;\n const visibleLiveTeamIds = (0, react.useMemo)(() => visibleTeams.map((team) => team.teamId).sort(), [visibleTeams]);\n (0, react.useEffect)(() => {\n const tracker = autoOpenTrackerRef.current;\n const settled = performance.now() - mountedAtRef.current >= AUTO_OPEN_SETTLE_MS;\n const shouldAutoExpand = tracker.sessionId === current && activityPanelShouldAutoExpand({\n alreadyAutoOpened: autoOpened,\n pageSettled: settled,\n restoreComplete: tracker.restoreComplete,\n previousLiveTeamIds: tracker.liveTeamIds,\n currentLiveTeamIds: visibleLiveTeamIds\n });\n if (tracker.sessionId === current && tracker.restoreComplete) tracker.liveTeamIds = new Set(visibleLiveTeamIds);\n if (visibleCount > 0) {\n setWasActive(true);\n if (shouldAutoExpand) {\n setOpenOwner(current);\n setOpen(true);\n setAutoOpened(true);\n }\n return;\n }\n if (!wasActive) return;\n const timer = setTimeout(() => {\n setOpen(false);\n setOpenOwner(void 0);\n setWasActive(false);\n setAutoOpened(false);\n }, AUTOCLOSE_GRACE_MS);\n return () => {\n clearTimeout(timer);\n };\n }, [\n visibleCount,\n visibleLiveTeamIds.join("\\0"),\n autoOpened,\n wasActive,\n current\n ]);\n const busy = (0, react.useMemo)(() => visibleTeams.some((team) => team.members.some((member) => member.activity === "working")), [visibleTeams]);\n const hasTeams = visibleCount > 0;\n const panelGeometryForGesture = (0, react.useCallback)(() => {\n const measuredHeight = panelRef.current?.getBoundingClientRect().height;\n if (measuredHeight === void 0 || measuredHeight <= 0) return geometry;\n return {\n ...geometry,\n height: measuredHeight\n };\n }, [geometry]);\n const flushScheduledLayout = (0, react.useCallback)(() => {\n if (frameRef.current !== null) {\n cancelAnimationFrame(frameRef.current);\n frameRef.current = null;\n }\n const pending = pendingLayoutRef.current;\n pendingLayoutRef.current = null;\n if (pending !== null) commitLayout(pending);\n }, [commitLayout]);\n const scheduleLayout = (0, react.useCallback)((next) => {\n pendingLayoutRef.current = next;\n frameRef.current ??= requestAnimationFrame(() => {\n frameRef.current = null;\n const pending = pendingLayoutRef.current;\n pendingLayoutRef.current = null;\n if (pending !== null) commitLayout(pending);\n });\n }, [commitLayout]);\n (0, react.useEffect)(() => () => {\n if (frameRef.current !== null) cancelAnimationFrame(frameRef.current);\n }, []);\n const beginMove = (0, react.useCallback)((event) => {\n if (compact || event.button !== 0 || event.target.closest("button") !== null) return;\n event.preventDefault();\n event.currentTarget.setPointerCapture(event.pointerId);\n gestureRef.current = {\n kind: "move",\n pointerId: event.pointerId,\n originX: event.clientX,\n originY: event.clientY,\n start: panelGeometryForGesture(),\n activated: false\n };\n }, [compact, panelGeometryForGesture]);\n const beginResize = (0, react.useCallback)((edge, event) => {\n if (compact || event.button !== 0 || geometry.mode === "docked" && edge !== "left") return;\n event.preventDefault();\n event.stopPropagation();\n event.currentTarget.setPointerCapture(event.pointerId);\n gestureRef.current = {\n kind: "resize",\n edge,\n pointerId: event.pointerId,\n originX: event.clientX,\n originY: event.clientY,\n start: panelGeometryForGesture(),\n activated: true\n };\n setInteraction("resizing");\n }, [\n compact,\n geometry.mode,\n panelGeometryForGesture\n ]);\n const updateGesture = (0, react.useCallback)((event) => {\n const gesture = gestureRef.current;\n if (gesture === null || gesture.pointerId !== event.pointerId || !event.currentTarget.hasPointerCapture(event.pointerId)) return;\n const dx = event.clientX - gesture.originX;\n const dy = event.clientY - gesture.originY;\n const activeBounds = boundsRef.current;\n if (gesture.kind === "move") {\n if (!gesture.activated && Math.hypot(dx, dy) < MOVE_THRESHOLD) return;\n if (!gesture.activated) {\n gesture.activated = true;\n setInteraction("dragging");\n }\n scheduleLayout(movePanelLayout(floatPanelLayout(gesture.start, activeBounds), dx, dy, activeBounds));\n return;\n }\n scheduleLayout(resizePanelLayout(gesture.start, gesture.edge ?? "left", dx, dy, activeBounds));\n }, [scheduleLayout]);\n const endGesture = (0, react.useCallback)((event) => {\n const gesture = gestureRef.current;\n if (gesture === null || gesture.pointerId !== event.pointerId) return;\n updateGesture(event);\n flushScheduledLayout();\n if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);\n gestureRef.current = null;\n setInteraction(null);\n }, [flushScheduledLayout, updateGesture]);\n const cancelGesture = (0, react.useCallback)((event) => {\n const gesture = gestureRef.current;\n if (gesture === null || gesture.pointerId !== event.pointerId) return;\n flushScheduledLayout();\n gestureRef.current = null;\n setInteraction(null);\n }, [flushScheduledLayout]);\n const toggleDock = (0, react.useCallback)(() => {\n const liveGeometry = panelGeometryForGesture();\n commitLayout(liveGeometry.mode === "docked" ? floatPanelLayout(liveGeometry, boundsRef.current) : dockPanelLayout(liveGeometry, boundsRef.current));\n }, [commitLayout, panelGeometryForGesture]);\n const autoHeight = panelUsesAutoHeight(geometry, bounds);\n const panelStyle = {\n width: geometry.width,\n height: autoHeight ? "auto" : geometry.height,\n maxHeight: panelMaximumHeight(geometry, bounds),\n transform: `translate3d(${geometry.x}px, ${geometry.y}px, 0)`\n };\n if (!conversationVisible || !hasTeams && !expanded) return null;\n return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [!expanded && (0, react_jsx_runtime.jsx)(CollapsedBadge, {\n count: visibleCount,\n busy,\n t,\n onClick: () => {\n if (current === void 0) return;\n setOpenOwner(current);\n setOpen(true);\n }\n }), expanded && (0, react_jsx_runtime.jsxs)("aside", {\n ref: panelRef,\n className: ActivityPanel_module_css_default.panel,\n style: panelStyle,\n "data-t-team-activity": true,\n "data-panel-mode": geometry.mode,\n "data-height-mode": autoHeight ? "auto" : "manual",\n "data-compact": compact || void 0,\n "data-dragging": interaction === "dragging" || void 0,\n "data-resizing": interaction === "resizing" || void 0,\n "aria-label": t("activity.panelAria"),\n children: [\n (0, react_jsx_runtime.jsxs)("header", {\n className: ActivityPanel_module_css_default.panelHead,\n onPointerDown: beginMove,\n onPointerMove: updateGesture,\n onPointerUp: endGesture,\n onPointerCancel: cancelGesture,\n "data-drag-handle": !compact || void 0,\n children: [(0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.panelTitle,\n children: [t("activity.title"), (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.panelDot,\n "data-busy": busy,\n "aria-hidden": true\n })]\n }), (0, react_jsx_runtime.jsxs)("span", {\n className: ActivityPanel_module_css_default.panelControls,\n children: [!compact && (0, react_jsx_runtime.jsx)("button", {\n type: "button",\n className: ActivityPanel_module_css_default.iconButton,\n "data-control": "dock",\n "data-mode": geometry.mode,\n onClick: toggleDock,\n "aria-label": t(geometry.mode === "docked" ? "activity.float" : "activity.dockRight"),\n title: t(geometry.mode === "docked" ? "activity.float" : "activity.dockRight"),\n children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPanelLeftOutline16, {})\n }), (0, react_jsx_runtime.jsx)("button", {\n type: "button",\n className: ActivityPanel_module_css_default.iconButton,\n "data-control": "collapse",\n onClick: () => {\n setOpen(false);\n setOpenOwner(void 0);\n },\n "aria-label": t("activity.collapse"),\n title: t("activity.collapse"),\n children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, {})\n })]\n })]\n }),\n (0, react_jsx_runtime.jsx)("div", {\n className: ActivityPanel_module_css_default.teams,\n children: visibleCount === 0 ? (0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.emptyHint,\n children: t("activity.empty")\n }) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [\n visibleTeams.map((team) => (0, react_jsx_runtime.jsx)(TeamSection, {\n team,\n modelDirectory: team.phase === "staged" ? modelDirectories.directoryFor(team.captainSessionId) : void 0,\n onContinuePlanning: returnToComposer,\n onDiscarded: returnToComposer,\n onNavigate: navigateToSession,\n t\n }, team.teamId)),\n visibleArchived.map((team) => (0, react_jsx_runtime.jsxs)("div", {\n "data-team-id": team.teamId,\n "data-historic": true,\n className: ActivityPanel_module_css_default.archivedWrap,\n children: [(0, react_jsx_runtime.jsx)("span", {\n className: ActivityPanel_module_css_default.archiveLabel,\n children: t(team.phase === "staged" ? "archive.discardedLabel" : "archive.label")\n }), (0, react_jsx_runtime.jsx)(TeamSection, {\n team,\n onNavigate: navigateToSession,\n t,\n historic: true\n })]\n }, `${team.captainSessionId}:${team.teamId}`)),\n visibleHistoric.map(({ data: team, owner }) => {\n const teamKey = `${owner}:${team.teamId}`;\n return (0, react_jsx_runtime.jsx)(TeamSection, {\n team: historicCardTeam(team, owner),\n onNavigate: navigateToSession,\n t,\n historic: true\n }, teamKey);\n })\n ] })\n }),\n !compact && (0, react_jsx_runtime.jsx)("div", {\n className: ActivityPanel_module_css_default.resizeHandle,\n "data-resize-edge": "left",\n onPointerDown: (event) => {\n beginResize("left", event);\n },\n onPointerMove: updateGesture,\n onPointerUp: endGesture,\n onPointerCancel: cancelGesture,\n "aria-hidden": true\n }),\n !compact && geometry.mode === "floating" && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("div", {\n className: ActivityPanel_module_css_default.resizeHandle,\n "data-resize-edge": "bottom",\n onPointerDown: (event) => {\n beginResize("bottom", event);\n },\n onPointerMove: updateGesture,\n onPointerUp: endGesture,\n onPointerCancel: cancelGesture,\n "aria-hidden": true\n }), (0, react_jsx_runtime.jsx)("div", {\n className: ActivityPanel_module_css_default.resizeHandle,\n "data-resize-edge": "corner",\n onPointerDown: (event) => {\n beginResize("corner", event);\n },\n onPointerMove: updateGesture,\n onPointerUp: endGesture,\n onPointerCancel: cancelGesture,\n "aria-hidden": true\n })] })\n ]\n })] });\n }\n //#endregion\n //#region lib/client/t-team-card-definition.js\n /**\n * T Team conversation card: a lightweight in-conversation summary shown\n * when a team is created \u2014 the captain\'s name, the member roster with whale\n * avatars, and an entry point that re-activates the top-right activity\n * panel (useful after the floater was closed, or when re-opening an old\n * session for review).\n *\n * The fold anchors to the Harness\'s durable `tool/call` + `tool/result`\n * records for `t_team_create`. Those are first-party session events, so\n * the card survives restarts without writing an out-of-repo event type.\n * @module t-team/client/card\n */\n /** Parse the only create-call fields the historic card owns. */\n function parseTTeamCreateArgs(value) {\n try {\n const parsed = JSON.parse(value);\n if (typeof parsed !== "object" || parsed === null || !("name" in parsed) || typeof parsed.name !== "string") return;\n const name = parsed.name.trim();\n if (name === "") return void 0;\n const cleaned = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");\n return {\n teamId: cleaned === "" ? "team" : cleaned,\n name\n };\n } catch {\n return;\n }\n }\n /** Durable first-party tool events folded into one keyed Chat node. */\n const tTeamCardDefinition = {\n kind: "t-team",\n target: "chat",\n match: (event) => {\n if (event.type === "tool/call" && event.data.name === "t_team_create") return parseTTeamCreateArgs(event.data.arguments) === void 0 ? null : {\n id: String(event.data.callId),\n role: "start"\n };\n if (event.type === "tool/result" && event.data.message.source.kind === "tool") return {\n id: String(event.data.message.source.callId),\n role: "update"\n };\n return null;\n },\n start: (_context, match) => {\n if (match.event.type !== "tool/call") throw new Error("t-team card start requires t_team_create tool/call");\n const parsed = parseTTeamCreateArgs(match.event.data.arguments);\n if (parsed === void 0) throw new Error("t-team card start requires valid create arguments");\n return {\n ...parsed,\n accepted: false\n };\n },\n update: (context, match) => {\n if (match.event.type !== "tool/result") return context.state;\n if (match.event.data.error !== void 0 || match.event.data.message.content.some((block) => block.type === "tool-result" && block.isError === true)) return context.state;\n return {\n ...context.state,\n accepted: true\n };\n },\n buildViewNode: (context) => {\n if (context.start === void 0) return null;\n const state = context.state;\n if (!state.accepted) return null;\n return {\n key: context.key,\n kind: "t-team",\n id: context.id,\n target: "chat",\n anchorSeq: context.start.event.seq,\n location: context.start.location,\n visibility: "visible",\n data: {\n teamId: state.teamId,\n captainSessionId: "",\n teamName: state.name,\n members: []\n }\n };\n }\n };\n //#endregion\n //#region lib/client/locales.js\n /** `tTeam` namespace dictionaries for every plugin-owned Web surface. */\n /** Dictionary namespace owned by the T Team client plugin. */\n const T_TEAM_LOCALE_NAMESPACE = "tTeam";\n /** Simplified Chinese dictionary (the key-set source of truth). */\n const zh = {\n "card.memberCount": "{count} \u540D\u6210\u5458",\n "action.openActivityPanel": "\u6253\u5F00\u6D3B\u52A8\u9762\u677F",\n "activity.panelButton": "\u6D3B\u52A8\u9762\u677F",\n "activity.badgeAria": "T\u4E13\u5BB6 \u56E2\u961F\u6D3B\u52A8\u4E0E\u5386\u53F2\uFF0C{count} \u6761\u56E2\u961F\u8BB0\u5F55",\n "activity.panelAria": "T\u4E13\u5BB6 \u56E2\u961F\u6D3B\u52A8\u9762\u677F",\n "activity.title": "T\u4E13\u5BB6 \u56E2\u961F\u6D3B\u52A8",\n "activity.float": "\u5207\u6362\u4E3A\u6D6E\u52A8\u9762\u677F",\n "activity.dockRight": "\u505C\u9760\u5230\u53F3\u4FA7",\n "activity.collapse": "\u6536\u8D77\u6D3B\u52A8\u9762\u677F",\n "activity.empty": "\u6682\u65E0\u56E2\u961F\u6D3B\u52A8",\n "team.stop": "\u505C\u6B62\u56E2\u961F",\n "team.stopped": "\u5DF2\u505C\u6B62",\n "team.stopTitle": "\u786E\u8BA4\u505C\u6B62\u201C{team}\u201D\uFF1F",\n "team.stopDescription": "\u5C06\u53D6\u6D88 {tasks} \u9879\u672A\u5B8C\u6210\u4EFB\u52A1\uFF0C\u5E76\u505C\u6B62 {members} \u540D\u6B63\u5728\u5DE5\u4F5C\u7684\u6210\u5458\u3002\u5DF2\u5B8C\u6210\u7684\u7ED3\u679C\u4F1A\u4FDD\u7559\u3002",\n "team.stopCancel": "\u7EE7\u7EED\u8FD0\u884C",\n "team.stopConfirm": "\u786E\u8BA4\u505C\u6B62",\n "team.stopping": "\u6B63\u5728\u505C\u6B62\u2026",\n "team.stopFailed": "\u505C\u6B62\u5931\u8D25\uFF1A{message}",\n "team.stopRequestFailed": "\u670D\u52A1\u5668\u672A\u80FD\u505C\u6B62\u56E2\u961F\uFF0C\u8BF7\u91CD\u8BD5",\n "team.discarded": "\u5DF2\u653E\u5F03",\n "format.listSeparator": "\u3001",\n "task.status.pending": "\u5F85\u9886\u53D6",\n "task.status.claimed": "\u5DF2\u8BA4\u9886",\n "task.status.inProgress": "\u8FDB\u884C\u4E2D",\n "task.status.completed": "\u5DF2\u5B8C\u6210",\n "task.status.failed": "\u5931\u8D25",\n "task.status.cancelled": "\u5DF2\u53D6\u6D88",\n "task.status.notRun": "\u672A\u6267\u884C",\n "member.state.working": "\u5DE5\u4F5C\u4E2D",\n "member.state.failed": "\u6709\u5931\u8D25",\n "member.state.waiting": "\u7B49\u5F85",\n "member.state.delivered": "\u5DF2\u4EA4\u4ED8",\n "member.state.left": "\u5DF2\u79BB\u961F",\n "member.state.removed": "\u5DF2\u79FB\u9664",\n "member.state.pending": "\u5F85\u6267\u884C",\n "member.state.unassigned": "\u5F85\u6D3E\u5DE5",\n "member.state.staged": "\u5F85\u521B\u5EFA",\n "member.state.notCreated": "\u672A\u521B\u5EFA",\n "member.state.stopped": "\u5DF2\u505C\u6B62",\n "member.status.executing": "\u6B63\u5728\u6267\u884C {taskId}",\n "member.status.executingModel": "\u6B63\u5728\u6267\u884C {taskId} \xB7 {model}",\n "member.status.working": "\u6B63\u5728\u5904\u7406\u5DF2\u6D3E\u4EFB\u52A1",\n "member.status.waitingOn": "\u7B49\u5F85 {taskId} \xB7 {assignee}",\n "member.status.waitingPrerequisite": "\u7B49\u5F85\u524D\u7F6E\u4EFB\u52A1",\n "member.status.waitingAssignment": "\u7B49\u5F85\u961F\u957F\u6D3E\u5DE5",\n "member.status.delivered": "\u4EFB\u52A1\u5DF2\u4EA4\u4ED8",\n "member.status.idle": "\u5F85\u7EE7\u7EED\u6267\u884C",\n "member.status.unknown": "\u72B6\u6001\u672A\u77E5",\n "member.status.staged": "\u786E\u8BA4\u540E\u521B\u5EFA\u5E76\u542F\u52A8",\n "member.status.settled": "\u4EFB\u52A1\u5747\u5DF2\u7EC8\u7ED3",\n "member.status.discarded": "\u8BA1\u5212\u5DF2\u653E\u5F03\uFF0C\u672A\u521B\u5EFA",\n "member.status.stopped": "\u56E2\u961F\u5DF2\u505C\u6B62\uFF0C\u9700\u663E\u5F0F\u6062\u590D",\n "task.assignee.unclaimed": "\u5F85\u8BA4\u9886",\n "task.summary.waitingBreakdown": "\u7B49\u5F85\u961F\u957F\u62C6\u89E3\u4EFB\u52A1",\n "task.summary.staged": "{count} \u9879\u8BA1\u5212\u7B49\u5F85\u786E\u8BA4",\n "task.summary.discarded": "{count} \u9879\u8BA1\u5212\u5DF2\u653E\u5F03\uFF0C\u5747\u672A\u6267\u884C",\n "task.summary.allDelivered": "\u5168\u90E8 {count} \u9879\u4EFB\u52A1\u5DF2\u4EA4\u4ED8",\n "task.summary.ended": "\u7EC8\u6001\uFF1A{completed} \u5DF2\u4EA4\u4ED8 \xB7 {cancelled} \u5DF2\u53D6\u6D88 \xB7 {failed} \u5931\u8D25",\n "task.summary.blockedAndRunning": "{tasks}{more} \u7B49\u5F85\u524D\u7F6E\uFF0C\u5176\u4F59\u5DF2\u5F00\u5DE5",\n "task.summary.more": " \u7B49 {count} \u9879",\n "task.summary.running": "{tasks} \u6B63\u5728\u6267\u884C",\n "task.summary.ready": "{tasks} \u5DF2\u5C31\u7EEA\u5F85\u5F00\u5DE5",\n "task.summary.blocked": "{tasks} \u7B49\u5F85\u524D\u7F6E",\n "task.summary.failedSettled": "{count} \u9879\u5DF2\u5931\u8D25\uFF0C\u81EA\u52A8\u5FAA\u73AF\u5DF2\u505C\u6B62",\n "task.summary.waitingSchedule": "\u7B49\u5F85\u4E0B\u4E00\u8F6E\u8C03\u5EA6",\n "progress.aria": "\u56E2\u961F\u603B\u8FDB\u5EA6",\n "progress.title": "\u603B\u8FDB\u5EA6",\n "progress.running": "\u25A0 \u8FDB\u884C\u4E2D {count}",\n "progress.blocked": "\u25A0 \u7B49\u5F85\u4F9D\u8D56 {count}",\n "progress.delivered": "\u25A0 \u5DF2\u4EA4\u4ED8 {count}",\n "dependency.aria": "\u4EFB\u52A1\u4F9D\u8D56\u94FE",\n "dependency.parallel": "\u5E76\u884C\u4EFB\u52A1",\n "dependency.title": "\u4EFB\u52A1\u4F9D\u8D56",\n "dependency.hint.parallel": "\u65E0\u524D\u540E\u4F9D\u8D56 \xB7 \u70B9\u51FB\u67E5\u770B\u8BE6\u60C5",\n "dependency.hint.chain": "\u60AC\u505C\u9AD8\u4EAE\u4F9D\u8D56\u94FE \xB7 \u70B9\u51FB\u56FA\u5B9A",\n "dependency.hint.pinned": "{taskId} \u5DF2\u56FA\u5B9A \xB7 Esc \u53D6\u6D88",\n "task.runningAria": "\u8FD0\u884C\u4E2D",\n "task.model": "{model}",\n "task.detail.completed": "\u5DF2\u5B8C\u6210\u5E76\u4EA4\u4ED8",\n "task.detail.noPrerequisite": "\u65E0\u524D\u7F6E\uFF0C\u53EF\u7ACB\u5373\u5F00\u5DE5",\n "task.detail.ready": "\u524D\u7F6E\u5DF2\u5C31\u7EEA\uFF0C\u53EF\u5F00\u5DE5",\n "task.detail.waitingOn": "\u7B49\u5F85 {tasks}",\n "task.detail.notRun": "\u8BA1\u5212\u5DF2\u653E\u5F03\uFF0C\u4EFB\u52A1\u672A\u6267\u884C",\n "task.detail.noDownstream": "\u65E0\u4E0B\u6E38\u4EFB\u52A1",\n "task.detail.unlocks": "\u5B8C\u6210\u540E\u89E3\u9501 {tasks}",\n "team.ended": "\u5DF2\u7ED3\u675F",\n "plan.badge": "\u5F85\u786E\u8BA4",\n "plan.title": "\u6267\u884C\u524D\u8BA1\u5212\u5BA1\u67E5",\n "plan.description": "\u6210\u5458\u5C1A\u672A\u521B\u5EFA\u3001\u4EFB\u52A1\u5C1A\u672A\u8C03\u5EA6\u3002\u53EF\u76F4\u63A5\u8C03\u6574\u8BA1\u5212\uFF0C\u4E5F\u53EF\u8FD4\u56DE\u5BF9\u8BDD\u544A\u8BC9\u961F\u957F\u54EA\u91CC\u9700\u8981\u4FEE\u6539\u3002",\n "plan.member.role": "\u89D2\u8272",\n "plan.member.provider": "Provider",\n "plan.member.model": "\u6A21\u578B",\n "plan.member.reasoning": "\u63A8\u7406\u7B49\u7EA7",\n "plan.member.reasoningHint": "\u7559\u7A7A\u4F7F\u7528\u9ED8\u8BA4\u503C\uFF1B\u53EF\u7528 low\u3001medium\u3001high\u3001xhigh \u7B49",\n "plan.model.choose": "\u9009\u62E9\u6A21\u578B",\n "plan.model.currentUnavailable": "{provider}/{model}\uFF08\u5F53\u524D\u76EE\u5F55\u4E0D\u53EF\u7528\uFF09",\n "plan.model.route": "\u8DEF\u7531\uFF1A{provider}/{model}",\n "plan.model.defaultReasoning": "\u9ED8\u8BA4\u63A8\u7406\u7B49\u7EA7",\n "plan.model.providerDefault": "Provider \u9ED8\u8BA4\u503C",\n "plan.model.modelDefault": "\u6A21\u578B\u9ED8\u8BA4\u503C\uFF08{effort}\uFF09",\n "plan.model.triggerAria": "\u9009\u62E9\u6210\u5458\u6A21\u578B\uFF0C\u5F53\u524D {model}\uFF0C\u63A8\u7406\u7B49\u7EA7 {effort}",\n "plan.model.back": "\u8FD4\u56DE",\n "plan.model.loading": "\u6B63\u5728\u52A0\u8F7D\u6A21\u578B\u2026",\n "plan.model.empty": "\u6682\u65E0\u53EF\u7528\u6A21\u578B",\n "plan.model.partialFailure": "{count} \u4E2A Provider \u7684\u6A21\u578B\u76EE\u5F55\u52A0\u8F7D\u5931\u8D25",\n "plan.model.retry": "\u91CD\u8BD5",\n "plan.member.prompt": "\u89D2\u8272\u63D0\u793A\u8BCD",\n "plan.member.roleFallback": "\u672A\u8BBE\u7F6E\u89D2\u8272",\n "plan.task.subject": "\u4EFB\u52A1\u540D\u79F0",\n "plan.task.description": "\u4EFB\u52A1\u8BF4\u660E",\n "plan.task.assignee": "\u8D1F\u8D23\u4EBA",\n "plan.task.dependencies": "\u4F9D\u8D56\u4EFB\u52A1 ID\uFF08\u9017\u53F7\u5206\u9694\uFF09",\n "plan.task.dependenciesHint": "\u4F8B\u5982 task-1, task-2\uFF1B\u4E0D\u5F97\u5F62\u6210\u5FAA\u73AF\u4F9D\u8D56",\n "plan.task.unassigned": "\u5171\u4EAB\u4EFB\u52A1\u6C60",\n "plan.unsaved": "\u672A\u4FDD\u5B58",\n "plan.save": "\u4FDD\u5B58",\n "plan.saving": "\u4FDD\u5B58\u4E2D\u2026",\n "plan.remove": "\u5220\u9664",\n "plan.removed": "\u4EFB\u52A1\u5DF2\u5220\u9664",\n "plan.removeConfirm": "\u786E\u8BA4\u5220\u9664",\n "plan.removeWarning": "\u5220\u9664 {task} \u540E\u5C06\u91CD\u65B0\u8BA1\u7B97\u4F9D\u8D56\u5173\u7CFB\u3002",\n "plan.cancel": "\u53D6\u6D88",\n "plan.addTask": "\u6DFB\u52A0\u4EFB\u52A1",\n "plan.adding": "\u6DFB\u52A0\u4E2D\u2026",\n "plan.taskAdded": "\u4EFB\u52A1\u5DF2\u6DFB\u52A0",\n "plan.newTask": "\u65B0\u4EFB\u52A1\u540D\u79F0",\n "plan.newTaskLabel": "\u65B0\u589E\u8BA1\u5212\u4EFB\u52A1",\n "plan.readySummary": "{members} \u540D\u6210\u5458 \xB7 {tasks} \u9879\u4EFB\u52A1 \xB7 {links} \u6761\u4F9D\u8D56",\n "plan.flow.aria": "\u56E2\u961F\u542F\u52A8\u6D41\u7A0B",\n "plan.flow.review": "\u5BA1\u67E5\u8BA1\u5212",\n "plan.flow.spawn": "\u521B\u5EFA\u6210\u5458",\n "plan.flow.run": "\u5F00\u59CB\u6267\u884C",\n "plan.members.title": "\u6210\u5458\u4E0E\u6A21\u578B\u8DEF\u7531",\n "plan.members.count": "{count} \u540D\u6210\u5458",\n "plan.members.empty": "\u5C1A\u672A\u89C4\u5212\u6210\u5458",\n "plan.tasks.title": "\u4EFB\u52A1\u4E0E\u4F9D\u8D56",\n "plan.tasks.count": "{count} \u9879\u4EFB\u52A1 \xB7 {links} \u6761\u4F9D\u8D56",\n "plan.tasks.empty": "\u5C1A\u672A\u89C4\u5212\u4EFB\u52A1",\n "plan.dependencies.none": "\u65E0\u4F9D\u8D56",\n "plan.dependencies.count": "{count} \u6761\u4F9D\u8D56",\n "plan.approve": "\u786E\u8BA4\u5E76\u542F\u52A8\u56E2\u961F",\n "plan.approving": "\u6B63\u5728\u521B\u5EFA\u6210\u5458\u2026",\n "plan.approveTitle": "\u8BA1\u5212\u68C0\u67E5\u5B8C\u6BD5\uFF1F",\n "plan.approveHint": "\u786E\u8BA4\u540E\u5C06\u521B\u5EFA {members} \u540D\u6210\u5458\u5E76\u8C03\u5EA6 {tasks} \u9879\u4EFB\u52A1\u3002",\n "plan.approveConfirmTitle": "\u786E\u8BA4\u542F\u52A8\u6B64\u56E2\u961F",\n "plan.approveWarning": "\u542F\u52A8\u540E\u4E0D\u80FD\u518D\u5728\u6B64\u5904\u7F16\u8F91\u6210\u5458\u548C\u4F9D\u8D56\u3002",\n "plan.approveConfirm": "\u786E\u8BA4\u542F\u52A8",\n "plan.continue": "\u8FD4\u56DE\u5BF9\u8BDD\u4FEE\u6539",\n "plan.returnToChat": "\u56DE\u5230\u5BF9\u8BDD",\n "plan.feedbackTitle": "\u6B63\u5728\u7B49\u4F60\u8BF4\u660E\u4FEE\u6539\u65B9\u5411",\n "plan.feedbackHint": "\u961F\u957F\u4F1A\u5728\u5BF9\u8BDD\u4E2D\u8FFD\u95EE\uFF1B\u6536\u5230\u4F60\u7684\u56DE\u590D\u540E\uFF0C\u53EA\u4FEE\u6539\u8FD9\u4EFD\u8349\u6848\u5E76\u518D\u6B21\u7B49\u5F85\u786E\u8BA4\u3002",\n "plan.discard": "\u653E\u5F03\u672C\u6B21\u8BA1\u5212",\n "plan.discardConfirmTitle": "\u653E\u5F03\u672C\u6B21\u8BA1\u5212\uFF1F",\n "plan.discardWarning": "\u8BE5\u8BA1\u5212\u4F1A\u7ED3\u675F\u5E76\u5F52\u6863\uFF1B\u5C1A\u672A\u521B\u5EFA\u4EFB\u4F55\u6210\u5458\uFF0C\u4E5F\u4E0D\u4F1A\u6267\u884C\u4EFB\u52A1\u3002",\n "plan.discardConfirm": "\u786E\u8BA4\u653E\u5F03",\n "plan.discarding": "\u6B63\u5728\u653E\u5F03\u2026",\n "plan.pendingEdits": "\u8BF7\u5148\u4FDD\u5B58\u5F53\u524D\u4FEE\u6539\uFF0C\u518D\u542F\u52A8\u56E2\u961F\u3002",\n "plan.saved": "\u8BA1\u5212\u5DF2\u4FDD\u5B58",\n "plan.failed": "\u64CD\u4F5C\u5931\u8D25\uFF1A{message}",\n "team.stats.members": "{count} \u540D\u6210\u5458",\n "team.stats.completed": "{completed}/{total} \u5B8C\u6210",\n "team.stats.messages": "{count} \u6761\u6D88\u606F",\n "delegation.aria": "\u961F\u957F\u6D3E\u5DE5\u5173\u7CFB",\n "captain.name": "\u961F\u957F",\n "captain.role": "\u62C6\u89E3 \xB7 \u6D3E\u53D1 \xB7 \u6C47\u603B",\n "captain.summary": "\u5DF2\u6D3E\u53D1 {tasks} \u9879\u4EFB\u52A1\u7ED9 {members} \u540D\u6210\u5458",\n "captain.summary.staged": "\u5DF2\u89C4\u5212 {tasks} \u9879\u4EFB\u52A1\u4E0E {members} \u540D\u6210\u5458\uFF0C\u7B49\u5F85\u786E\u8BA4",\n "captain.summary.awaitingFeedback": "\u8349\u6848\u5DF2\u4FDD\u7559\uFF0C\u7B49\u5F85\u4F60\u5728\u5BF9\u8BDD\u4E2D\u8BF4\u660E\u4FEE\u6539\u65B9\u5411",\n "captain.summary.discarded": "\u8BA1\u5212\u5DF2\u653E\u5F03\uFF1A{members} \u540D\u6210\u5458\u672A\u521B\u5EFA\uFF0C{tasks} \u9879\u4EFB\u52A1\u672A\u6267\u884C",\n "captain.summary.withTakeover": "\u5DF2\u6D3E\u53D1 {tasks} \u9879\u7ED9\u6210\u5458 \xB7 \u961F\u957F\u63A5\u7BA1 {captainTasks}",\n "captain.state.working": "{count} \u4EBA\u6267\u884C\u4E2D",\n "captain.state.takeover": "\u6B63\u5728\u6267\u884C {tasks}",\n "captain.state.collected": "\u5DF2\u6536\u9F50",\n "captain.state.waiting": "\u7B49\u5F85\u56DE\u62A5",\n "captain.state.staged": "\u5F85\u786E\u8BA4",\n "captain.state.awaitingFeedback": "\u5F85\u53CD\u9988",\n "captain.state.discarded": "\u5DF2\u653E\u5F03",\n "captain.state.settled": "\u5DF2\u7EC8\u7ED3",\n "members.toggle": "{count} \u540D\u6210\u5458",\n "members.collapse": "\u6536\u8D77",\n "members.expand": "\u5C55\u5F00",\n "members.empty": "\u6682\u65E0\u6210\u5458\uFF0C\u7B49\u5F85\u961F\u957F\u7EC4\u5EFA\u56E2\u961F",\n "assignment.label": "\u961F\u957F\u6D3E\u53D1",\n "assignment.staged": "\u8BA1\u5212\u4EFB\u52A1",\n "assignment.discarded": "\u672A\u6267\u884C\u7684\u8BA1\u5212",\n "assignment.empty": "\u6682\u65E0\u4EFB\u52A1",\n "archive.label": "\u5DF2\u7ED3\u675F \xB7 \u5386\u53F2\u5F52\u6863",\n "archive.discardedLabel": "\u8BA1\u5212\u5DF2\u653E\u5F03 \xB7 \u5386\u53F2\u5F52\u6863"\n };\n /** English dictionary, checked complete against the Chinese source key set. */\n const en = {\n "card.memberCount": "{count} members",\n "action.openActivityPanel": "Open activity panel",\n "activity.panelButton": "Activity panel",\n "activity.badgeAria": "T Team activity and history, {count} team records",\n "activity.panelAria": "T Team activity panel",\n "activity.title": "T Team activity",\n "activity.float": "Switch to floating panel",\n "activity.dockRight": "Dock to the right",\n "activity.collapse": "Collapse activity panel",\n "activity.empty": "No team activity",\n "team.stop": "Stop team",\n "team.stopped": "Stopped",\n "team.stopTitle": "Stop \u201C{team}\u201D?",\n "team.stopDescription": "This cancels {tasks} unfinished tasks and stops {members} working members. Completed results are kept.",\n "team.stopCancel": "Keep running",\n "team.stopConfirm": "Stop team",\n "team.stopping": "Stopping\u2026",\n "team.stopFailed": "Could not stop team: {message}",\n "team.stopRequestFailed": "The server could not stop this team. Try again.",\n "team.discarded": "Discarded",\n "format.listSeparator": ", ",\n "task.status.pending": "Unclaimed",\n "task.status.claimed": "Claimed",\n "task.status.inProgress": "In progress",\n "task.status.completed": "Completed",\n "task.status.failed": "Failed",\n "task.status.cancelled": "Cancelled",\n "task.status.notRun": "Not run",\n "member.state.working": "Working",\n "member.state.failed": "Has failures",\n "member.state.waiting": "Waiting",\n "member.state.delivered": "Delivered",\n "member.state.left": "Left team",\n "member.state.removed": "Removed",\n "member.state.pending": "Pending",\n "member.state.unassigned": "Awaiting assignment",\n "member.state.staged": "Not spawned",\n "member.state.notCreated": "Not created",\n "member.state.stopped": "Stopped",\n "member.status.executing": "Working on {taskId}",\n "member.status.executingModel": "Working on {taskId} \xB7 {model}",\n "member.status.working": "Working on assigned tasks",\n "member.status.waitingOn": "Waiting for {taskId} \xB7 {assignee}",\n "member.status.waitingPrerequisite": "Waiting for prerequisites",\n "member.status.waitingAssignment": "Waiting for the captain to assign work",\n "member.status.delivered": "Tasks delivered",\n "member.status.idle": "Ready to continue",\n "member.status.unknown": "Status unknown",\n "member.status.staged": "Will be spawned after approval",\n "member.status.settled": "All assigned work is settled",\n "member.status.discarded": "Plan discarded; member was not created",\n "member.status.stopped": "Team stopped; explicit resume required",\n "task.assignee.unclaimed": "Unclaimed",\n "task.summary.waitingBreakdown": "Waiting for the captain to break down the work",\n "task.summary.staged": "{count} planned tasks awaiting approval",\n "task.summary.discarded": "{count} planned tasks discarded; none ran",\n "task.summary.allDelivered": "All {count} tasks delivered",\n "task.summary.ended": "Final: {completed} delivered \xB7 {cancelled} cancelled \xB7 {failed} failed",\n "task.summary.blockedAndRunning": "{tasks}{more} waiting on prerequisites; other work has started",\n "task.summary.more": " and {count} more",\n "task.summary.running": "{tasks} in progress",\n "task.summary.ready": "{tasks} ready to start",\n "task.summary.blocked": "{tasks} waiting on prerequisites",\n "task.summary.failedSettled": "{count} failed; the automatic loop has stopped",\n "task.summary.waitingSchedule": "Waiting for the next scheduling round",\n "progress.aria": "Overall team progress",\n "progress.title": "Overall progress",\n "progress.running": "\u25A0 In progress {count}",\n "progress.blocked": "\u25A0 Waiting {count}",\n "progress.delivered": "\u25A0 Delivered {count}",\n "dependency.aria": "Task dependency chain",\n "dependency.parallel": "Parallel tasks",\n "dependency.title": "Task dependencies",\n "dependency.hint.parallel": "No dependencies \xB7 Click for details",\n "dependency.hint.chain": "Hover to highlight dependencies \xB7 Click to pin",\n "dependency.hint.pinned": "{taskId} pinned \xB7 Esc to clear",\n "task.runningAria": "Running",\n "task.model": "{model}",\n "task.detail.completed": "Completed and delivered",\n "task.detail.noPrerequisite": "No prerequisites; ready to start",\n "task.detail.ready": "Prerequisites ready; can start",\n "task.detail.waitingOn": "Waiting for {tasks}",\n "task.detail.notRun": "Plan discarded; task was not run",\n "task.detail.noDownstream": "No downstream tasks",\n "task.detail.unlocks": "Unlocks {tasks} when complete",\n "team.ended": "Ended",\n "plan.badge": "Awaiting approval",\n "plan.title": "Pre-run plan review",\n "plan.description": "Members have not been spawned and tasks have not been scheduled. Edit the draft here, or return to chat and tell the Captain what should change.",\n "plan.member.role": "Role",\n "plan.member.provider": "Provider",\n "plan.member.model": "Model",\n "plan.member.reasoning": "Reasoning effort",\n "plan.member.reasoningHint": "Leave blank for default; accepts low, medium, high, xhigh, and more",\n "plan.model.choose": "Choose a model",\n "plan.model.currentUnavailable": "{provider}/{model} (not in the current catalog)",\n "plan.model.route": "Route: {provider}/{model}",\n "plan.model.defaultReasoning": "Default reasoning effort",\n "plan.model.providerDefault": "Provider default",\n "plan.model.modelDefault": "Model default ({effort})",\n "plan.model.triggerAria": "Choose member model, currently {model}, reasoning effort {effort}",\n "plan.model.back": "Back",\n "plan.model.loading": "Loading models\u2026",\n "plan.model.empty": "No models available",\n "plan.model.partialFailure": "{count} provider catalogs could not be loaded",\n "plan.model.retry": "Retry",\n "plan.member.prompt": "Role prompt",\n "plan.member.roleFallback": "Role not set",\n "plan.task.subject": "Task subject",\n "plan.task.description": "Task description",\n "plan.task.assignee": "Assignee",\n "plan.task.dependencies": "Dependency task IDs (comma-separated)",\n "plan.task.dependenciesHint": "For example task-1, task-2; cycles are rejected",\n "plan.task.unassigned": "Shared task pool",\n "plan.unsaved": "Unsaved",\n "plan.save": "Save",\n "plan.saving": "Saving\u2026",\n "plan.remove": "Remove",\n "plan.removed": "Task removed",\n "plan.removeConfirm": "Confirm remove",\n "plan.removeWarning": "Removing {task} will recalculate downstream dependencies.",\n "plan.cancel": "Cancel",\n "plan.addTask": "Add task",\n "plan.adding": "Adding\u2026",\n "plan.taskAdded": "Task added",\n "plan.newTask": "New task subject",\n "plan.newTaskLabel": "Add a planned task",\n "plan.readySummary": "{members} members \xB7 {tasks} tasks \xB7 {links} dependencies",\n "plan.flow.aria": "Team launch flow",\n "plan.flow.review": "Review plan",\n "plan.flow.spawn": "Create members",\n "plan.flow.run": "Start work",\n "plan.members.title": "Members & model routes",\n "plan.members.count": "{count} members",\n "plan.members.empty": "No members planned yet",\n "plan.tasks.title": "Tasks & dependencies",\n "plan.tasks.count": "{count} tasks \xB7 {links} dependencies",\n "plan.tasks.empty": "No tasks planned yet",\n "plan.dependencies.none": "No dependencies",\n "plan.dependencies.count": "{count} dependencies",\n "plan.approve": "Approve & Run",\n "plan.approving": "Creating members\u2026",\n "plan.approveTitle": "Plan ready?",\n "plan.approveHint": "Approval creates {members} members and schedules {tasks} tasks.",\n "plan.approveConfirmTitle": "Confirm team launch",\n "plan.approveWarning": "Member routes and dependencies cannot be edited here after launch.",\n "plan.approveConfirm": "Confirm launch",\n "plan.continue": "Return to chat & revise",\n "plan.returnToChat": "Return to chat",\n "plan.feedbackTitle": "Waiting for your revision direction",\n "plan.feedbackHint": "The Captain will ask in chat. After your reply, it will revise this draft and wait for approval again.",\n "plan.discard": "Discard this plan",\n "plan.discardConfirmTitle": "Discard this plan?",\n "plan.discardWarning": "The plan will end and be archived. No members have been spawned and no tasks will run.",\n "plan.discardConfirm": "Discard plan",\n "plan.discarding": "Discarding\u2026",\n "plan.pendingEdits": "Save the current edits before launching the team.",\n "plan.saved": "Plan saved",\n "plan.failed": "Operation failed: {message}",\n "team.stats.members": "{count} members",\n "team.stats.completed": "{completed}/{total} completed",\n "team.stats.messages": "{count} messages",\n "delegation.aria": "Captain delegation map",\n "captain.name": "Captain",\n "captain.role": "Break down \xB7 Delegate \xB7 Synthesize",\n "captain.summary": "Assigned {tasks} tasks to {members} members",\n "captain.summary.staged": "Planned {tasks} tasks and {members} members; awaiting approval",\n "captain.summary.awaitingFeedback": "Draft preserved; waiting for your revision direction in chat",\n "captain.summary.discarded": "Plan discarded: {members} members were not created and {tasks} tasks did not run",\n "captain.summary.withTakeover": "Assigned {tasks} to members \xB7 Captain owns {captainTasks}",\n "captain.state.working": "{count} active",\n "captain.state.takeover": "Working on {tasks}",\n "captain.state.collected": "All reports received",\n "captain.state.waiting": "Waiting for reports",\n "captain.state.staged": "Awaiting approval",\n "captain.state.awaitingFeedback": "Awaiting feedback",\n "captain.state.discarded": "Discarded",\n "captain.state.settled": "Settled",\n "members.toggle": "Members {count}",\n "members.collapse": "Collapse",\n "members.expand": "Expand",\n "members.empty": "No members yet; waiting for the captain to assemble the team",\n "assignment.label": "Captain assigned",\n "assignment.staged": "Planned task",\n "assignment.discarded": "Plan not run",\n "assignment.empty": "No tasks",\n "archive.label": "Ended \xB7 Archived history",\n "archive.discardedLabel": "Plan discarded \xB7 Archived history"\n };\n //#endregion\n //#region lib/client/session-navigation.js\n /** Version-tolerant navigation into durable T Team member transcripts. */\n /**\n * Open one member\'s persisted transcript.\n *\n * Harness rc.8 intentionally removed cold subagents from the ordinary session\n * list. They must first be rediscovered in their parent\'s catalog, then opened\n * with the exact parent/child/mode address. Older runtimes have only `open()`;\n * the fallback preserves ordinary-session navigation. New layouts also select\n * the Conversation panel and cancel catalog refreshes superseded by navigation.\n */\n async function openAgentTeamMember(sessions, parentSessionId, childSessionId, layout) {\n const navigation = layout?.beginNavigation?.();\n if (sessions.openSubagent === void 0 || sessions.refreshSubagents === void 0) {\n sessions.open(childSessionId);\n layout?.selectPanel?.(null);\n return "session";\n }\n await sessions.refreshSubagents(parentSessionId);\n if (navigation?.aborted) return "cancelled";\n const retained = sessions.subagentAddress?.(childSessionId);\n sessions.openSubagent(retained?.parentSessionId === parentSessionId ? retained : {\n parentSessionId,\n childSessionId,\n mode: "continuable"\n });\n layout?.selectPanel?.(null);\n return "subagent";\n }\n //#endregion\n //#region lib/client/index.js\n /** Required services: conversation nodes, slots, sessions navigation, and locale. */\n const inject = [\n "uiConversation",\n "slots",\n "sessions",\n "locale",\n "modelDirectories",\n "layout"\n ];\n const useLegacyPanelInfo = (select) => select({ activePanelId: null });\n /** The replayed user message is the canonical transcript entry. */\n function HiddenTTeamCommand() {\n return null;\n }\n /**\n * Register the activity monitor in the shell\'s additive overlay and the\n * in-conversation team card. The card\'s activity button re-opens a folded\n * monitor via a window event \u2014 the recovery path for an old session.\n */\n function apply(ctx) {\n ctx.effect(() => ctx.locale.register(T_TEAM_LOCALE_NAMESPACE, {\n zh,\n en\n }), "t-team: dictionaries");\n const openMember = (parentId, childId) => {\n openAgentTeamMember(ctx.sessions, parentId, childId, ctx.layout).catch((error) => {\n console.warn(`t-team: failed to open member transcript ${childId}: ${String(error)}`);\n });\n };\n const Panel = ({ t, usePanelInfo }) => {\n return (0, react_jsx_runtime.jsx)(ActivityPanel, {\n conversationVisible: (usePanelInfo ?? useLegacyPanelInfo)((panel) => panel.activePanelId === null),\n sessionsList: ctx.sessions.list,\n modelDirectories: ctx.modelDirectories,\n openMember,\n t\n });\n };\n ctx.slots.inject("shell.overlay", () => ctx.slots.register({\n name: "shell.overlay",\n id: "t-team-activity",\n order: 80,\n label: "T Team activity",\n locale: T_TEAM_LOCALE_NAMESPACE\n }, Panel));\n ctx.slots.inject("conversation.chat.commandview", () => ctx.slots.register({\n name: "conversation.chat.commandview",\n key: "t-team-hidden"\n }, HiddenTTeamCommand));\n ctx.uiConversation.events.register(tTeamCardDefinition);\n ctx.slots.inject("conversation.chat.node", () => ctx.slots.register({\n name: "conversation.chat.node",\n key: "t-team",\n locale: T_TEAM_LOCALE_NAMESPACE,\n inject: () => ({ openMember })\n }, TTeamCard));\n }\n //#endregion\n exports.apply = apply;\n exports.inject = inject;\n return module.exports;\n }\n});\n\n//# sourceMappingURL=client.js.map';
|
|
19721
19721
|
|
|
19722
19722
|
// src/client.jsx
|
|
@@ -19724,12 +19724,10 @@ var NS = "t-team";
|
|
|
19724
19724
|
var PLUGIN_ID = "dsh-plugin-t-expert";
|
|
19725
19725
|
var DIVISION_FALLBACK = "specialized";
|
|
19726
19726
|
var zh = {
|
|
19727
|
-
"settings.nav": "T\u4E13\u5BB6",
|
|
19728
19727
|
"settings.title": "T\u4E13\u5BB6",
|
|
19729
19728
|
"settings.loading": "\u6B63\u5728\u8BFB\u53D6\u540D\u518C\u2026",
|
|
19730
19729
|
"settings.retry": "\u91CD\u8BD5",
|
|
19731
19730
|
"settings.search": "\u641C\u7D22\u4E13\u5BB6\u540D\u6216\u7B80\u4ECB",
|
|
19732
|
-
"settings.all": "\u5168\u90E8",
|
|
19733
19731
|
"filter.division": "\u5206\u7C7B",
|
|
19734
19732
|
"filter.status": "\u72B6\u6001",
|
|
19735
19733
|
"filter.allDivisions": "\u5168\u90E8\u5206\u7C7B",
|
|
@@ -19750,10 +19748,12 @@ var zh = {
|
|
|
19750
19748
|
"settings.enable": "\u542F\u7528",
|
|
19751
19749
|
"settings.disable": "\u505C\u7528",
|
|
19752
19750
|
"settings.saveFailed": "\u4FDD\u5B58\u5931\u8D25\uFF1A{detail}",
|
|
19751
|
+
"settings.loadFailed": "\u8BFB\u53D6\u540D\u518C\u5931\u8D25\uFF1A{detail}",
|
|
19753
19752
|
"settings.conflictRetry": "\u8BBE\u7F6E\u5DF2\u88AB\u5176\u4ED6\u7A97\u53E3\u4FEE\u6539\uFF0C\u5DF2\u91CD\u65B0\u8BFB\u53D6\u540D\u518C\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
19753
|
+
"settings.crashed": "\u8FD9\u5757\u5185\u5BB9\u6E32\u67D3\u5931\u8D25\uFF1A{detail}\u3002\u5207\u5230\u522B\u7684\u6807\u7B7E\u518D\u56DE\u6765\u53EF\u91CD\u8BD5\u3002",
|
|
19754
|
+
"error.remoteUnavailable": "T\u4E13\u5BB6 \u8FDC\u7A0B\u670D\u52A1\u4E0D\u53EF\u7528\uFF08host \u63D2\u4EF6\u672A\u52A0\u8F7D\u6216\u5DF2\u5378\u8F7D\uFF09",
|
|
19754
19755
|
"trigger.removed": "@\u5DF2\u79FB\u9664\u4E13\u5BB6\uFF08\u8BF7\u91CD\u65B0\u9009\u62E9\uFF09",
|
|
19755
19756
|
"button.label": "T\u4E13\u5BB6",
|
|
19756
|
-
"button.pickTitle": "\u9009\u62E9\u4E00\u4F4D\u4E13\u5BB6",
|
|
19757
19757
|
"button.title": "\u6253\u5F00 T\u4E13\u5BB6 \u540D\u518C\uFF0C\u9009\u4E2D\u540E\u63D2\u5165\u5F15\u7528",
|
|
19758
19758
|
"button.empty": "\u8FD8\u6CA1\u6709\u542F\u7528\u7684\u4E13\u5BB6\uFF0C\u5148\u53BB \u8BBE\u7F6E \u2192 T\u4E13\u5BB6 \u542F\u7528",
|
|
19759
19759
|
"button.noMatch": "\u6CA1\u6709\u5339\u914D\u7684\u4E13\u5BB6",
|
|
@@ -19765,11 +19765,10 @@ var zh = {
|
|
|
19765
19765
|
"tab.teams": "\u56E2\u961F",
|
|
19766
19766
|
"tab.roster": "\u961F\u4F0D",
|
|
19767
19767
|
"roster.squads": "\u5C0F\u961F\u6A21\u677F\uFF08\u53EF\u590D\u7528\uFF09",
|
|
19768
|
-
"roster.squadsHint": "\u9884\u5148\u6311\u597D\u7684\u73ED\u5E95\uFF1A\u6210\u5458\u3001\u522B\u540D\u3001\u542F\u505C\u3002\
|
|
19768
|
+
"roster.squadsHint": "\u9884\u5148\u6311\u597D\u7684\u73ED\u5E95\uFF1A\u6210\u5458\u3001\u522B\u540D\u3001\u542F\u505C\u3002\u7528\u5B83\u5C31\u8BF4 /t <\u5C0F\u961F> <\u76EE\u6807>\uFF0C\u6216\u5728\u8F93\u5165\u6846\u5F39\u7A97\u91CC\u70B9\u300C\u586B\u5165\u300D\uFF1B\u6539\u5B8C\u4FDD\u5B58\u540E\u9700\u91CD\u542F DSH \u624D\u80FD\u7528\u4E8E\u5EFA\u961F\uFF08/t \u5217\u8868\u4F1A\u7ACB\u5373\u5237\u65B0\uFF09\u3002",
|
|
19769
19769
|
"roster.teams": "\u8FD0\u884C\u4E2D\u7684\u56E2\u961F",
|
|
19770
19770
|
"roster.teamsHint": "\u6BCF\u6B21\u7528\u6A21\u677F\u8DD1\u8D77\u6765\u7684\u4E00\u6B21\u5B9E\u4F8B\uFF1A\u53EF\u505C\u6B62\u3001\u770B\u8FDB\u5EA6\u3001\u6253\u5F00\u6D3B\u52A8\u9762\u677F\uFF1B\u5F52\u6863\u540E\u4ECD\u53EF\u5728\u8FD9\u91CC\u56DE\u770B\u3002",
|
|
19771
19771
|
"roster.expertsHint": "\u540D\u518C\uFF1A\u80FD\u88AB @ \u53EC\u5524\u3001\u4E5F\u80FD\u88AB\u5C0F\u961F\u6311\u8FDB\u73ED\u5E95\u7684\u4E13\u5BB6\u3002",
|
|
19772
|
-
"roster.empty": "\u8FD9\u4E00\u7EC4\u6682\u65F6\u662F\u7A7A\u7684\u3002",
|
|
19773
19772
|
"squads.loading": "\u6B63\u5728\u8BFB\u53D6\u5C0F\u961F\u2026",
|
|
19774
19773
|
"squads.count": "{count} \u652F\u5C0F\u961F \xB7 {experts} \u4F4D\u4E13\u5BB6\u53EF\u9009",
|
|
19775
19774
|
"squads.new": "\u65B0\u5EFA\u5C0F\u961F",
|
|
@@ -19782,12 +19781,10 @@ var zh = {
|
|
|
19782
19781
|
"squads.deleteConfirm": "\u5220\u9664\u5C0F\u961F\u300C{key}\u300D\uFF1F",
|
|
19783
19782
|
"squads.enabled": "\u542F\u7528",
|
|
19784
19783
|
"squads.disabled": "\u5DF2\u5173\u505C",
|
|
19785
|
-
"squads.disabledHint": "\u5173\u505C\u7684\u5C0F\u961F\u4E0D\u4F1A\u8FDB\u5165\u5F15\u64CE\u914D\u7F6E\uFF0C/t \u4E5F\u4E0D\u4F1A\u5217\u51FA\u5B83\u3002",
|
|
19786
19784
|
"squads.key": "\u5C0F\u961F key\uFF08\u5C0F\u5199\u5B57\u6BCD/\u6570\u5B57/\u8FDE\u5B57\u7B26\uFF09",
|
|
19787
19785
|
"squads.desc": "\u8BF4\u660E",
|
|
19788
19786
|
"squads.aliases": "\u522B\u540D\uFF08/t \u7528\u54EA\u4E2A\u8BCD\u90FD\u80FD\u547D\u4E2D\uFF09",
|
|
19789
19787
|
"squads.aliasPlaceholder": "\u8F93\u5165\u522B\u540D\u540E\u56DE\u8F66",
|
|
19790
|
-
"squads.addAlias": "\u6DFB\u52A0",
|
|
19791
19788
|
"squads.members": "\u6210\u5458\uFF08\u987A\u5E8F\uFF1D\u5EFA\u961F\u987A\u5E8F\uFF09",
|
|
19792
19789
|
"squads.memberSearch": "\u641C\u7D22\u4E13\u5BB6\u540D\u6216 slug",
|
|
19793
19790
|
"squads.memberEmpty": "\u6CA1\u6709\u5339\u914D\u7684\u4E13\u5BB6",
|
|
@@ -19800,7 +19797,7 @@ var zh = {
|
|
|
19800
19797
|
"squads.empty": "\u8FD8\u6CA1\u6709\u5C0F\u961F\uFF0C\u70B9\u300C\u65B0\u5EFA\u5C0F\u961F\u300D\u4ECE\u540D\u518C\u91CC\u7EC4\u4E00\u652F\u3002",
|
|
19801
19798
|
"squads.buildOk": "\u4E0A\u6B21\u7F16\u8BD1\uFF1A{time}",
|
|
19802
19799
|
"squads.buildFailed": "\u7F16\u8BD1\u5931\u8D25\uFF1A{detail}",
|
|
19803
|
-
"squads.unknownMember": "\u540D\u518C\u91CC\u6CA1\u6709 {slug}\uFF08\
|
|
19800
|
+
"squads.unknownMember": "\u540D\u518C\u91CC\u6CA1\u6709 {slug}\uFF08\u6362\u4E00\u4F4D\uFF0C\u6216\u786E\u8BA4\u540D\u518C\u76EE\u5F55\u91CC\u6709\u8FD9\u4F4D\u4E13\u5BB6\uFF09",
|
|
19804
19801
|
"squads.reload": "\u91CD\u65B0\u8BFB\u53D6",
|
|
19805
19802
|
"teams.loading": "\u6B63\u5728\u8BFB\u53D6\u56E2\u961F\u2026",
|
|
19806
19803
|
"teams.empty": "\u6CA1\u6709\u8FD0\u884C\u4E2D\u7684\u56E2\u961F\u3002\u7528 /t \u6216\u76F4\u63A5\u8BA9\u6211\u62C9\u4E00\u652F\u3002",
|
|
@@ -19815,12 +19812,12 @@ var zh = {
|
|
|
19815
19812
|
"teams.refresh": "\u5237\u65B0",
|
|
19816
19813
|
"teams.tasks": "{done}/{total} \u4EFB\u52A1",
|
|
19817
19814
|
"teams.members": "{count} \u540D\u6210\u5458",
|
|
19815
|
+
"teams.working": "{count} \u5DE5\u4F5C\u4E2D",
|
|
19818
19816
|
"teams.halted": "\u5DF2\u505C\u6B62",
|
|
19819
19817
|
"teams.archived": "\u5F52\u6863",
|
|
19820
19818
|
"teams.staged": "\u5F85\u786E\u8BA4",
|
|
19821
19819
|
"teams.running": "\u8FD0\u884C\u4E2D",
|
|
19822
19820
|
"pop.title": "T\u4E13\u5BB6",
|
|
19823
|
-
"pop.pick": "\u9009\u5B83",
|
|
19824
19821
|
"pop.fill": "\u586B\u5165",
|
|
19825
19822
|
"pop.fillTitle": "\u628A /t {key} \u586B\u8FDB\u8F93\u5165\u6846\uFF0C\u4F60\u8865\u4E0A\u76EE\u6807\u540E\u56DE\u8F66\uFF08\u4E0D\u4F1A\u7ACB\u523B\u53D1\u9001\uFF09",
|
|
19826
19823
|
"pop.filled": "\u5DF2\u586B\u5165 /t {key} \u2014\u2014\u8865\u4E0A\u4F60\u8981\u505A\u7684\u4E8B\uFF0C\u56DE\u8F66\u5373\u53EF\u3002",
|
|
@@ -19833,12 +19830,10 @@ var zh = {
|
|
|
19833
19830
|
"pop.memberCount": "{count} \u4EBA"
|
|
19834
19831
|
};
|
|
19835
19832
|
var en = {
|
|
19836
|
-
"settings.nav": "T Expert",
|
|
19837
19833
|
"settings.title": "T Expert",
|
|
19838
19834
|
"settings.loading": "Loading roster\u2026",
|
|
19839
19835
|
"settings.retry": "Retry",
|
|
19840
19836
|
"settings.search": "Search expert name or description",
|
|
19841
|
-
"settings.all": "All",
|
|
19842
19837
|
"filter.division": "Division",
|
|
19843
19838
|
"filter.status": "Status",
|
|
19844
19839
|
"filter.allDivisions": "All divisions",
|
|
@@ -19859,10 +19854,12 @@ var en = {
|
|
|
19859
19854
|
"settings.enable": "Enable",
|
|
19860
19855
|
"settings.disable": "Disable",
|
|
19861
19856
|
"settings.saveFailed": "Save failed: {detail}",
|
|
19857
|
+
"settings.loadFailed": "Failed to load roster: {detail}",
|
|
19862
19858
|
"settings.conflictRetry": "Settings changed elsewhere; roster reloaded, please retry.",
|
|
19859
|
+
"settings.crashed": "This section failed to render: {detail}. Switch tabs and back to retry.",
|
|
19860
|
+
"error.remoteUnavailable": "T Expert remote service is unavailable (host plugin not loaded or already disposed)",
|
|
19863
19861
|
"trigger.removed": "@Removed expert (please reselect)",
|
|
19864
19862
|
"button.label": "T Expert",
|
|
19865
|
-
"button.pickTitle": "Pick an expert",
|
|
19866
19863
|
"button.title": "Open the T Expert roster and insert a reference",
|
|
19867
19864
|
"button.empty": "No expert enabled yet \u2014 enable some in Settings \u2192 T Expert",
|
|
19868
19865
|
"button.noMatch": "No matching expert",
|
|
@@ -19874,11 +19871,10 @@ var en = {
|
|
|
19874
19871
|
"tab.teams": "Teams",
|
|
19875
19872
|
"tab.roster": "Roster",
|
|
19876
19873
|
"roster.squads": "Squad templates (reusable)",
|
|
19877
|
-
"roster.squadsHint": "A pre-picked roster: members, aliases, enable/disable. Run it with /t <squad> <goal>, or tap
|
|
19874
|
+
"roster.squadsHint": "A pre-picked roster: members, aliases, enable/disable. Run it with /t <squad> <goal>, or tap Fill in the composer popup. After saving, restart DSH before the squad can start a team (the /t list refreshes immediately).",
|
|
19878
19875
|
"roster.teams": "Running teams",
|
|
19879
19876
|
"roster.teamsHint": "One instance per run: stop it, watch progress, open the activity panel; archived teams stay reviewable here.",
|
|
19880
19877
|
"roster.expertsHint": "The roster: experts available for @-mention and for squad templates.",
|
|
19881
|
-
"roster.empty": "Nothing in this group yet.",
|
|
19882
19878
|
"squads.loading": "Loading squads\u2026",
|
|
19883
19879
|
"squads.count": "{count} squads \xB7 {experts} experts available",
|
|
19884
19880
|
"squads.new": "New squad",
|
|
@@ -19891,12 +19887,10 @@ var en = {
|
|
|
19891
19887
|
"squads.deleteConfirm": 'Delete squad "{key}"?',
|
|
19892
19888
|
"squads.enabled": "Enabled",
|
|
19893
19889
|
"squads.disabled": "Disabled",
|
|
19894
|
-
"squads.disabledHint": "A disabled squad is not compiled into the engine config and /t will not list it.",
|
|
19895
19890
|
"squads.key": "Squad key (lowercase/digits/dash)",
|
|
19896
19891
|
"squads.desc": "Description",
|
|
19897
19892
|
"squads.aliases": "Aliases (any of them works with /t)",
|
|
19898
19893
|
"squads.aliasPlaceholder": "Type an alias and press Enter",
|
|
19899
|
-
"squads.addAlias": "Add",
|
|
19900
19894
|
"squads.members": "Members (order = spawn order)",
|
|
19901
19895
|
"squads.memberSearch": "Search expert name or slug",
|
|
19902
19896
|
"squads.memberEmpty": "No matching expert",
|
|
@@ -19909,7 +19903,7 @@ var en = {
|
|
|
19909
19903
|
"squads.empty": "No squads yet \u2014 click New squad to build one from the roster.",
|
|
19910
19904
|
"squads.buildOk": "Last build: {time}",
|
|
19911
19905
|
"squads.buildFailed": "Build failed: {detail}",
|
|
19912
|
-
"squads.unknownMember": "{slug} is not in the roster (
|
|
19906
|
+
"squads.unknownMember": "{slug} is not in the roster (pick another expert, or check that the roster directory contains it)",
|
|
19913
19907
|
"squads.reload": "Reload",
|
|
19914
19908
|
"teams.loading": "Loading teams\u2026",
|
|
19915
19909
|
"teams.empty": "No running teams. Use /t or just ask me to start one.",
|
|
@@ -19924,12 +19918,12 @@ var en = {
|
|
|
19924
19918
|
"teams.refresh": "Refresh",
|
|
19925
19919
|
"teams.tasks": "{done}/{total} tasks",
|
|
19926
19920
|
"teams.members": "{count} members",
|
|
19921
|
+
"teams.working": "{count} working",
|
|
19927
19922
|
"teams.halted": "Stopped",
|
|
19928
19923
|
"teams.archived": "Archived",
|
|
19929
19924
|
"teams.staged": "Awaiting approval",
|
|
19930
19925
|
"teams.running": "Running",
|
|
19931
19926
|
"pop.title": "T Expert",
|
|
19932
|
-
"pop.pick": "Use it",
|
|
19933
19927
|
"pop.fill": "Fill in",
|
|
19934
19928
|
"pop.fillTitle": "Put /t {key} into the composer; add your goal and press Enter (nothing is sent yet)",
|
|
19935
19929
|
"pop.filled": "Inserted /t {key} \u2014 describe the goal and hit Enter.",
|
|
@@ -19961,9 +19955,10 @@ var CSS = `
|
|
|
19961
19955
|
.t-team-squad-actions{display:flex;gap:6px;flex-shrink:0}
|
|
19962
19956
|
.t-team-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
|
|
19963
19957
|
.t-team-label{font-size:12px;color:var(--dsw-alias-label-caption);min-width:52px}
|
|
19964
|
-
.t-team-chip-btn{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);border-radius:999px;font-size:12px;padding:2px 8px;cursor:pointer}
|
|
19965
19958
|
.t-team-member-chip{display:inline-flex;align-items:center;gap:4px;border:1px solid var(--dsw-alias-border-l2);border-radius:999px;padding:2px 8px;font-size:12px;background:var(--dsw-alias-bg-layer-3)}
|
|
19966
19959
|
.t-team-member-chip[data-unknown="true"]{border-color:var(--dsw-alias-state-error-primary)}
|
|
19960
|
+
.t-team-emoji{font-size:14px;line-height:1}
|
|
19961
|
+
.t-team-groups{display:flex;flex-direction:column;gap:10px}
|
|
19967
19962
|
.t-team-editor{display:flex;flex-direction:column;gap:10px;border-top:1px dashed var(--dsw-alias-border-l2);padding-top:10px}
|
|
19968
19963
|
.t-team-field{display:flex;flex-direction:column;gap:4px}
|
|
19969
19964
|
.t-team-field > span{font-size:12px;color:var(--dsw-alias-label-caption)}
|
|
@@ -19976,7 +19971,6 @@ var CSS = `
|
|
|
19976
19971
|
.t-team-picker-list{max-height:220px;overflow:auto;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:6px}
|
|
19977
19972
|
.t-team-picker-row{display:flex;align-items:center;gap:6px;padding:3px 4px;border-radius:6px;font-size:12px;cursor:pointer}
|
|
19978
19973
|
.t-team-picker-row:hover{background:var(--dsw-alias-bg-layer-3)}
|
|
19979
|
-
.t-team-picker-row[data-disabled="true"]{opacity:.45;cursor:not-allowed}
|
|
19980
19974
|
.t-team-picker-slug{color:var(--dsw-alias-label-caption);font-family:var(--dsw-font-markdown-code-block-small);font-size:11px}
|
|
19981
19975
|
.t-team-selected-row{display:flex;align-items:center;gap:6px;font-size:12px;padding:3px 4px;border-bottom:1px solid var(--dsw-alias-border-l2)}
|
|
19982
19976
|
.t-team-teams{display:flex;flex-direction:column;gap:8px}
|
|
@@ -20001,7 +19995,6 @@ var CSS = `
|
|
|
20001
19995
|
.t-team-chip{padding:3px 10px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-size:12px;cursor:pointer}
|
|
20002
19996
|
.t-team-chip:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
20003
19997
|
.t-team-chip:disabled{opacity:.5;cursor:default}
|
|
20004
|
-
.t-team-chip:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
20005
19998
|
.t-team-chip[data-active="true"]{background:var(--dsw-alias-button-ghost-active-fill);border-color:var(--dsw-alias-button-ghost-active-border);color:var(--dsw-alias-label-primary);font-weight:600}
|
|
20006
19999
|
.t-team-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:10px 12px}
|
|
20007
20000
|
.t-team-group{margin-top:6px}
|
|
@@ -20032,10 +20025,7 @@ var CSS = `
|
|
|
20032
20025
|
.t-team-switch[data-enabled="true"] .t-team-switch-knob{transform:translateX(12px);background:var(--dsw-alias-label-primary-foreground)}
|
|
20033
20026
|
.t-team-switch:disabled{opacity:.45;cursor:not-allowed}
|
|
20034
20027
|
.t-team-conflict{font-size:11px;color:var(--dsw-alias-state-warn-primary)}
|
|
20035
|
-
.t-team-toggle{padding:4px 12px;border-radius:8px;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-size:12px;white-space:nowrap;cursor:pointer}
|
|
20036
|
-
.t-team-toggle:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
20037
20028
|
.t-team-error{font-size:12px;color:var(--dsw-alias-state-error-primary)}
|
|
20038
|
-
.t-team-conflict{font-size:11px;color:var(--dsw-alias-state-warn-primary)}
|
|
20039
20029
|
.t-team-btn{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:8px;border:1px solid transparent;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-size:12px;white-space:nowrap;cursor:pointer}
|
|
20040
20030
|
.t-team-btn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
20041
20031
|
.t-team-pop{position:fixed;z-index:60;width:320px;max-height:420px;overflow:hidden;box-sizing:border-box;display:flex;flex-direction:column;gap:8px;padding:10px;border-radius:12px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-specific-menu, var(--dsw-alias-bg-layer-3));box-shadow:var(--dsw-shadow-lv3);color:var(--dsw-alias-label-primary)}
|
|
@@ -20194,7 +20184,7 @@ function snapshotOf(remote) {
|
|
|
20194
20184
|
function unwrap(result, action) {
|
|
20195
20185
|
if (result !== null && typeof result === "object" && typeof result.ok === "boolean") {
|
|
20196
20186
|
if (result.ok !== true) {
|
|
20197
|
-
const error62 = new Error(result.error?.message ?? `${action}
|
|
20187
|
+
const error62 = new Error(result.error?.message ?? `${action} failed`);
|
|
20198
20188
|
error62.code = result.error?.code;
|
|
20199
20189
|
throw error62;
|
|
20200
20190
|
}
|
|
@@ -20202,12 +20192,24 @@ function unwrap(result, action) {
|
|
|
20202
20192
|
}
|
|
20203
20193
|
return result;
|
|
20204
20194
|
}
|
|
20195
|
+
var catalogListeners = /* @__PURE__ */ new Set();
|
|
20196
|
+
function onCatalogLoaded(listener) {
|
|
20197
|
+
catalogListeners.add(listener);
|
|
20198
|
+
return () => catalogListeners.delete(listener);
|
|
20199
|
+
}
|
|
20205
20200
|
async function refresh(remote, force = false) {
|
|
20206
20201
|
const cached2 = catalogCache.get(remote);
|
|
20207
20202
|
if (cached2 !== void 0 && !force) return cached2;
|
|
20208
20203
|
const next = unwrap(await remote.getCatalog(), "getCatalog");
|
|
20209
20204
|
next.enabledSet = new Set(next.enabled);
|
|
20210
20205
|
catalogCache.set(remote, next);
|
|
20206
|
+
for (const listener of catalogListeners) {
|
|
20207
|
+
try {
|
|
20208
|
+
listener();
|
|
20209
|
+
} catch (cause) {
|
|
20210
|
+
console.error("[t-team] \u540D\u518C\u901A\u77E5\u56DE\u8C03\u5931\u8D25\uFF1A", cause);
|
|
20211
|
+
}
|
|
20212
|
+
}
|
|
20211
20213
|
return next;
|
|
20212
20214
|
}
|
|
20213
20215
|
function displayName(expert, active) {
|
|
@@ -20234,6 +20236,27 @@ function referenceOf(expert, active) {
|
|
|
20234
20236
|
clipboardText: `@${name}\xA0`
|
|
20235
20237
|
};
|
|
20236
20238
|
}
|
|
20239
|
+
var SectionBoundary = class extends import_react.default.Component {
|
|
20240
|
+
constructor(props) {
|
|
20241
|
+
super(props);
|
|
20242
|
+
this.state = { error: "" };
|
|
20243
|
+
}
|
|
20244
|
+
static getDerivedStateFromError(error62) {
|
|
20245
|
+
return { error: error62 instanceof Error ? error62.message : String(error62) };
|
|
20246
|
+
}
|
|
20247
|
+
componentDidCatch(error62) {
|
|
20248
|
+
console.error("[t-team] \u533A\u5757\u6E32\u67D3\u5931\u8D25\uFF1A", error62);
|
|
20249
|
+
}
|
|
20250
|
+
componentDidUpdate(previous) {
|
|
20251
|
+
if (previous.reloadKey !== this.props.reloadKey && this.state.error !== "") this.setState({ error: "" });
|
|
20252
|
+
}
|
|
20253
|
+
render() {
|
|
20254
|
+
if (this.state.error !== "") {
|
|
20255
|
+
return /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-error" }, this.props.t("settings.crashed", { detail: this.state.error }));
|
|
20256
|
+
}
|
|
20257
|
+
return this.props.children;
|
|
20258
|
+
}
|
|
20259
|
+
};
|
|
20237
20260
|
function SettingsPanel({ t, remote, getActive, refreshCatalog, initialTab, squadsPreview, teamsPreview, draftPreview }) {
|
|
20238
20261
|
const [snapshot, setSnapshot] = import_react.default.useState(() => snapshotOf(remote) ?? null);
|
|
20239
20262
|
const [query, setQuery] = import_react.default.useState("");
|
|
@@ -20334,14 +20357,14 @@ function SettingsPanel({ t, remote, getActive, refreshCatalog, initialTab, squad
|
|
|
20334
20357
|
const message = cause instanceof Error ? cause.message : String(cause);
|
|
20335
20358
|
const code = typeof cause === "object" && cause !== null ? cause.code : void 0;
|
|
20336
20359
|
const conflict = code === "tTeam/conflict" || code === "SETTINGS_CONFLICT" || /changed since it was read|another window|其他窗口|冲突/.test(message);
|
|
20337
|
-
setError(conflict ? "CONFLICT" : message);
|
|
20338
20360
|
await reload(true);
|
|
20361
|
+
setError(conflict ? "CONFLICT" : message);
|
|
20339
20362
|
} finally {
|
|
20340
20363
|
setBusy(false);
|
|
20341
20364
|
}
|
|
20342
20365
|
}
|
|
20343
20366
|
if (snapshot === null) {
|
|
20344
|
-
return /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-settings" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-title" }, t("settings.title")), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-meta" }, error62
|
|
20367
|
+
return /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-settings" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-title" }, t("settings.title")), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-meta" }, t("settings.loading")), error62 !== "" && /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-error" }, t("settings.loadFailed", { detail: error62 })), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-row" }, /* @__PURE__ */ import_react.default.createElement("button", { className: "t-team-chip", type: "button", onClick: () => void reload(true) }, t("settings.retry")))));
|
|
20345
20368
|
}
|
|
20346
20369
|
const enabledCount = snapshot.enabled.length;
|
|
20347
20370
|
return /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-settings" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-head" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-title" }, t("settings.title")), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-meta" }, t("settings.enabledCount", { enabled: enabledCount, total: experts.length }))), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-tabs", role: "tablist" }, [["experts", "tab.experts"], ["roster", "tab.roster"]].map(([key, label]) => /* @__PURE__ */ import_react.default.createElement(
|
|
@@ -20356,7 +20379,7 @@ function SettingsPanel({ t, remote, getActive, refreshCatalog, initialTab, squad
|
|
|
20356
20379
|
onClick: () => setTab(key)
|
|
20357
20380
|
},
|
|
20358
20381
|
t(label)
|
|
20359
|
-
))), tab === "roster" && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-tabbody" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-section-head" }, t("roster.squads")), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-note" }, t("roster.squadsHint"))), /* @__PURE__ */ import_react.default.createElement(SquadsTab, { t, remote, initialData: squadsPreview, initialDraft: draftPreview }), /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-section-head" }, t("roster.teams")), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-note" }, t("roster.teamsHint"))), /* @__PURE__ */ import_react.default.createElement(TeamsTab, { t, remote, initialTeams: teamsPreview })), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-tabbody", hidden: tab !== "experts" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-note" }, t("roster.expertsHint")), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-bar" }, /* @__PURE__ */ import_react.default.createElement(
|
|
20382
|
+
))), tab === "roster" && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-tabbody" }, /* @__PURE__ */ import_react.default.createElement(SectionBoundary, { t, reloadKey: tab }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-section-head" }, t("roster.squads")), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-note" }, t("roster.squadsHint"))), /* @__PURE__ */ import_react.default.createElement(SquadsTab, { t, remote, initialData: squadsPreview, initialDraft: draftPreview }), /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-section-head" }, t("roster.teams")), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-note" }, t("roster.teamsHint"))), /* @__PURE__ */ import_react.default.createElement(TeamsTab, { t, remote, initialTeams: teamsPreview }))), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-tabbody", hidden: tab !== "experts" }, /* @__PURE__ */ import_react.default.createElement(SectionBoundary, { t, reloadKey: tab }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-note" }, t("roster.expertsHint")), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-bar" }, /* @__PURE__ */ import_react.default.createElement(
|
|
20360
20383
|
"input",
|
|
20361
20384
|
{
|
|
20362
20385
|
className: "t-team-input",
|
|
@@ -20430,7 +20453,7 @@ function SettingsPanel({ t, remote, getActive, refreshCatalog, initialTab, squad
|
|
|
20430
20453
|
},
|
|
20431
20454
|
/* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-switch-knob" })
|
|
20432
20455
|
)));
|
|
20433
|
-
})))), visible.length === 0 && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-meta" }, t("settings.empty")))), promptView !== null && /* @__PURE__ */ import_react.default.createElement(
|
|
20456
|
+
})))), visible.length === 0 && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-meta" }, t("settings.empty"))))), promptView !== null && /* @__PURE__ */ import_react.default.createElement(
|
|
20434
20457
|
"div",
|
|
20435
20458
|
{
|
|
20436
20459
|
className: "t-team-mask",
|
|
@@ -20616,6 +20639,7 @@ function SquadsTab({ t, remote, initialData, initialDraft }) {
|
|
|
20616
20639
|
"aria-label": draft.index === null ? t("squads.new") : t("squads.edit")
|
|
20617
20640
|
},
|
|
20618
20641
|
/* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-modal-head" }, /* @__PURE__ */ import_react.default.createElement("span", null, draft.index === null ? t("squads.new") : `${t("squads.edit")} \xB7 ${draft.key}`), /* @__PURE__ */ import_react.default.createElement("button", { className: "t-team-chip", type: "button", onClick: () => setDraft(null) }, t("squads.cancel"))),
|
|
20642
|
+
error62 !== "" && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-error" }, error62),
|
|
20619
20643
|
/* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-editor-body" }, renderEditor())
|
|
20620
20644
|
)
|
|
20621
20645
|
));
|
|
@@ -20663,8 +20687,13 @@ function TeamsTab({ t, remote, initialTeams, compact }) {
|
|
|
20663
20687
|
import_react.default.useEffect(() => {
|
|
20664
20688
|
void load(archived);
|
|
20665
20689
|
}, [load, archived]);
|
|
20666
|
-
function openPanel() {
|
|
20667
|
-
window.dispatchEvent(new CustomEvent("t-team:open-panel", {
|
|
20690
|
+
function openPanel(team) {
|
|
20691
|
+
window.dispatchEvent(new CustomEvent("t-team:open-panel", {
|
|
20692
|
+
detail: {
|
|
20693
|
+
teamId: team?.teamId ?? "",
|
|
20694
|
+
captainSessionId: team?.captainSessionId ?? ""
|
|
20695
|
+
}
|
|
20696
|
+
}));
|
|
20668
20697
|
}
|
|
20669
20698
|
async function stop(team) {
|
|
20670
20699
|
if (!window.confirm(t("teams.stopConfirm", { name: team.name }))) return;
|
|
@@ -20681,11 +20710,13 @@ function TeamsTab({ t, remote, initialTeams, compact }) {
|
|
|
20681
20710
|
}
|
|
20682
20711
|
}
|
|
20683
20712
|
const teams = state.teams;
|
|
20684
|
-
return /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-tabbody" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-row" }, compact !== true && /* @__PURE__ */ import_react.default.createElement("button", { className: "t-team-chip", type: "button", onClick: () => setArchived((value) => !value) }, archived ? t("teams.showActive") : t("teams.showArchived")), /* @__PURE__ */ import_react.default.createElement("button", { className: "t-team-chip", type: "button", onClick: () => void load(archived) }, t("teams.refresh")), /* @__PURE__ */ import_react.default.createElement("button", { className: "t-team-chip", type: "button", onClick: openPanel }, t("teams.openPanel"))), note !== "" && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-ok" }, note), state.error !== "" && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-error" }, state.error), teams === null && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-meta" }, t("teams.loading")), teams !== null && teams.length === 0 && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-meta" }, archived ? t("teams.emptyArchived") : t("teams.empty")), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-teams" }, (teams ?? []).map((team) => {
|
|
20685
|
-
const
|
|
20686
|
-
const
|
|
20713
|
+
return /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-tabbody" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-row" }, compact !== true && /* @__PURE__ */ import_react.default.createElement("button", { className: "t-team-chip", type: "button", onClick: () => setArchived((value) => !value) }, archived ? t("teams.showActive") : t("teams.showArchived")), /* @__PURE__ */ import_react.default.createElement("button", { className: "t-team-chip", type: "button", onClick: () => void load(archived) }, t("teams.refresh")), /* @__PURE__ */ import_react.default.createElement("button", { className: "t-team-chip", type: "button", onClick: () => openPanel((teams ?? [])[0]) }, t("teams.openPanel"))), note !== "" && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-ok" }, note), state.error !== "" && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-error" }, state.error), teams === null && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-meta" }, t("teams.loading")), teams !== null && teams.length === 0 && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-meta" }, archived ? t("teams.emptyArchived") : t("teams.empty")), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-teams" }, (teams ?? []).map((team) => {
|
|
20714
|
+
const taskList = Array.isArray(team?.tasks) ? team.tasks : [];
|
|
20715
|
+
const memberList = Array.isArray(team?.members) ? team.members : [];
|
|
20716
|
+
const done = taskList.filter((task) => task?.status === "completed").length;
|
|
20717
|
+
const working = memberList.filter((member) => member?.activity === "working").length;
|
|
20687
20718
|
const phase = team.halted === true ? t("teams.halted") : archived ? t("teams.archived") : team.phase === "staged" ? t("teams.staged") : t("teams.running");
|
|
20688
|
-
return /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-team", key: team.teamId }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-team-head" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-team-name", title: `${team.name} \xB7 ${team.teamId}` }, team.name), /* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-badge", "data-tone": team.halted === true ? "error" : team.phase === "staged" ? "warn" : void 0 }, phase)), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-team-meta" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("teams.members", { count:
|
|
20719
|
+
return /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-team", key: team.teamId }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-team-head" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-team-name", title: `${team.name} \xB7 ${team.teamId}` }, team.name), /* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-badge", "data-tone": team.halted === true ? "error" : team.phase === "staged" ? "warn" : void 0 }, phase)), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-team-meta" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("teams.members", { count: memberList.length })), /* @__PURE__ */ import_react.default.createElement("span", null, working > 0 ? `${t("teams.working", { count: working })} \xB7 ` : "", t("teams.tasks", { done, total: taskList.length })), /* @__PURE__ */ import_react.default.createElement("span", null, team.workspace)), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-row" }, memberList.slice(0, 8).map((member) => /* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-member-chip", key: member.name, "data-unknown": member.activity === "unknown" }, member.name))), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-row" }, /* @__PURE__ */ import_react.default.createElement("button", { className: "t-team-chip", type: "button", onClick: () => openPanel(team) }, t("teams.openPanel")), !archived && /* @__PURE__ */ import_react.default.createElement("button", { className: "t-team-chip", type: "button", disabled: busyId === team.teamId, onClick: () => void stop(team) }, busyId === team.teamId ? t("teams.stopping") : t("teams.stop"))));
|
|
20689
20720
|
})));
|
|
20690
20721
|
}
|
|
20691
20722
|
function resolveInputTarget(ctx, sessionId) {
|
|
@@ -20709,13 +20740,15 @@ function referencePrefixEnd(snapshot) {
|
|
|
20709
20740
|
}
|
|
20710
20741
|
return end;
|
|
20711
20742
|
}
|
|
20743
|
+
var CHIP_PREFIX = /^(?:[\ufffc]\s*)*\s*/u;
|
|
20712
20744
|
function insertSquadCommand(target, key) {
|
|
20713
20745
|
if (target === void 0 || typeof target.insertText !== "function") return false;
|
|
20714
20746
|
const snapshot = target.state.getSnapshot();
|
|
20715
20747
|
const draft = String(snapshot.draft ?? "");
|
|
20716
|
-
const
|
|
20748
|
+
const offset = CHIP_PREFIX.exec(draft)?.[0].length ?? 0;
|
|
20749
|
+
const existing = /^\/t(\s+\S+)?\s*/u.exec(draft.slice(offset));
|
|
20717
20750
|
const text = `/t ${key} `;
|
|
20718
|
-
const span = existing === null ? { start:
|
|
20751
|
+
const span = existing === null ? { start: offset, end: offset, draftRev: snapshot.draftRev } : { start: offset, end: offset + existing[0].length, draftRev: snapshot.draftRev };
|
|
20719
20752
|
return target.insertText(text, span) === true;
|
|
20720
20753
|
}
|
|
20721
20754
|
function insertAtTarget(target, reference) {
|
|
@@ -20737,6 +20770,11 @@ function SummonButton({ t, remote, getActive, insertReference, fillSquadCommand,
|
|
|
20737
20770
|
const [position, setPosition] = import_react.default.useState(void 0);
|
|
20738
20771
|
const rootRef = import_react.default.useRef(null);
|
|
20739
20772
|
const snap = snapshotOf(remote);
|
|
20773
|
+
function place() {
|
|
20774
|
+
const rect = rootRef.current?.getBoundingClientRect();
|
|
20775
|
+
if (rect === void 0) return;
|
|
20776
|
+
setPosition({ left: Math.max(8, rect.left), bottom: Math.max(8, window.innerHeight - rect.top + 6) });
|
|
20777
|
+
}
|
|
20740
20778
|
import_react.default.useEffect(() => {
|
|
20741
20779
|
if (!open2) return void 0;
|
|
20742
20780
|
const onDown = (event) => {
|
|
@@ -20747,9 +20785,13 @@ function SummonButton({ t, remote, getActive, insertReference, fillSquadCommand,
|
|
|
20747
20785
|
};
|
|
20748
20786
|
document.addEventListener("mousedown", onDown);
|
|
20749
20787
|
document.addEventListener("keydown", onKey);
|
|
20788
|
+
window.addEventListener("resize", place);
|
|
20789
|
+
window.addEventListener("scroll", place, true);
|
|
20750
20790
|
return () => {
|
|
20751
20791
|
document.removeEventListener("mousedown", onDown);
|
|
20752
20792
|
document.removeEventListener("keydown", onKey);
|
|
20793
|
+
window.removeEventListener("resize", place);
|
|
20794
|
+
window.removeEventListener("scroll", place, true);
|
|
20753
20795
|
};
|
|
20754
20796
|
}, [open2]);
|
|
20755
20797
|
async function toggle() {
|
|
@@ -20768,10 +20810,7 @@ function SummonButton({ t, remote, getActive, insertReference, fillSquadCommand,
|
|
|
20768
20810
|
const value = result?.ok === true ? result.value : void 0;
|
|
20769
20811
|
setTeams(value?.teams ?? []);
|
|
20770
20812
|
}).catch(() => setTeams([]));
|
|
20771
|
-
|
|
20772
|
-
if (rect !== void 0) {
|
|
20773
|
-
setPosition({ left: Math.max(8, rect.left), bottom: Math.max(8, window.innerHeight - rect.top + 6) });
|
|
20774
|
-
}
|
|
20813
|
+
place();
|
|
20775
20814
|
await refresh(remote, true).catch(() => void 0);
|
|
20776
20815
|
}
|
|
20777
20816
|
const active = getActive();
|
|
@@ -20923,11 +20962,11 @@ async function apply(ctx) {
|
|
|
20923
20962
|
console.error("[t-team] \u56E2\u961F UI \u6302\u8F7D\u5931\u8D25\uFF08\u4E13\u5BB6\u9762\u677F\u4E0E @ \u53EC\u5524\u4E0D\u53D7\u5F71\u54CD\uFF09\uFF1A", error62);
|
|
20924
20963
|
}
|
|
20925
20964
|
}
|
|
20926
|
-
const getActive = () => ctx.locale.getSnapshot().active
|
|
20965
|
+
const getActive = () => String(ctx.locale.getSnapshot().active ?? "").toLowerCase().startsWith("zh") ? "zh" : "en";
|
|
20927
20966
|
const disposeRemote = await ctx.remote.$mount(TYPERT_REMOTE);
|
|
20928
20967
|
ctx.effect(() => disposeRemote, "t-team: remote");
|
|
20929
20968
|
const remote = ctx.get("remote.tTeam");
|
|
20930
|
-
if (remote === void 0) throw new Error("
|
|
20969
|
+
if (remote === void 0) throw new Error(ctx.locale.bind(NS)("error.remoteUnavailable"));
|
|
20931
20970
|
await refresh(remote, true).catch((cause) => {
|
|
20932
20971
|
console.warn("[t-team] \u521D\u59CB\u540D\u518C\u8BFB\u53D6\u5931\u8D25\uFF0C\u8BBE\u7F6E\u9875\u53EF\u91CD\u8BD5\uFF1A", cause);
|
|
20933
20972
|
});
|
|
@@ -20936,7 +20975,8 @@ async function apply(ctx) {
|
|
|
20936
20975
|
name: "settings.section",
|
|
20937
20976
|
id: NS,
|
|
20938
20977
|
order: 17,
|
|
20939
|
-
|
|
20978
|
+
// 文案一律走字典(规范:产品可见文案由 locale 拥有,不接受硬编码分支)
|
|
20979
|
+
label: () => ctx.locale.bind(NS)("settings.title"),
|
|
20940
20980
|
locale: NS,
|
|
20941
20981
|
icon: "expert"
|
|
20942
20982
|
}, (props) => import_react.default.createElement(SettingsPanel, { ...props, t: ctx.locale.bind(NS), remote, getActive, refreshCatalog })));
|
|
@@ -20954,13 +20994,10 @@ async function apply(ctx) {
|
|
|
20954
20994
|
};
|
|
20955
20995
|
}
|
|
20956
20996
|
}, (props) => import_react.default.createElement(SummonButton, { ...props, t: ctx.locale.bind(NS), remote, getActive })));
|
|
20957
|
-
const registerSources = (active) => {
|
|
20997
|
+
const registerSources = (active, divisions) => {
|
|
20958
20998
|
const disposers = [];
|
|
20959
20999
|
try {
|
|
20960
|
-
const
|
|
20961
|
-
const divisions = /* @__PURE__ */ new Set();
|
|
20962
|
-
for (const expert of snapshot?.experts ?? []) divisions.add(expert.division);
|
|
20963
|
-
for (const [index, item] of [...divisions].sort().entries()) {
|
|
21000
|
+
for (const [index, item] of divisions.entries()) {
|
|
20964
21001
|
const sourceName = `${NS}:${item}`;
|
|
20965
21002
|
disposers.push(ctx.inputTriggers.registerSource({
|
|
20966
21003
|
trigger: "@",
|
|
@@ -20993,7 +21030,7 @@ async function apply(ctx) {
|
|
|
20993
21030
|
async serialize(slug) {
|
|
20994
21031
|
const current = await refresh(remote).catch(() => void 0);
|
|
20995
21032
|
const expert = current?.experts.find((entry) => entry.slug === slug);
|
|
20996
|
-
if (expert === void 0 || current.enabledSet.has(slug) !== true) {
|
|
21033
|
+
if (expert === void 0 || current.enabledSet.has(expert.slug) !== true) {
|
|
20997
21034
|
throw new Error(ctx.locale.bind(NS)("trigger.removed"));
|
|
20998
21035
|
}
|
|
20999
21036
|
return `@${displayName(expert, getActive())}\xA0`;
|
|
@@ -21010,24 +21047,33 @@ async function apply(ctx) {
|
|
|
21010
21047
|
};
|
|
21011
21048
|
};
|
|
21012
21049
|
ctx.effect(() => {
|
|
21013
|
-
|
|
21014
|
-
|
|
21015
|
-
|
|
21016
|
-
const
|
|
21017
|
-
if (
|
|
21018
|
-
|
|
21050
|
+
const installed = { signature: "", dispose: () => void 0 };
|
|
21051
|
+
const syncSources = () => {
|
|
21052
|
+
const snapshot = snapshotOf(remote);
|
|
21053
|
+
const divisions = [...new Set((snapshot?.experts ?? []).map((expert) => expert.division))].sort();
|
|
21054
|
+
if (divisions.length === 0) {
|
|
21055
|
+
installed.signature = "";
|
|
21056
|
+
return;
|
|
21057
|
+
}
|
|
21058
|
+
const signature = `${getActive()}|${divisions.join(",")}`;
|
|
21059
|
+
if (signature === installed.signature) return;
|
|
21060
|
+
installed.dispose();
|
|
21061
|
+
installed.dispose = () => void 0;
|
|
21019
21062
|
try {
|
|
21020
|
-
|
|
21021
|
-
|
|
21063
|
+
installed.dispose = registerSources(getActive(), divisions);
|
|
21064
|
+
installed.signature = signature;
|
|
21022
21065
|
} catch (cause) {
|
|
21023
|
-
console.error("[t-team] \
|
|
21024
|
-
|
|
21025
|
-
};
|
|
21066
|
+
console.error("[t-team] \u6CE8\u518C @ \u83DC\u5355\u5931\u8D25\uFF0C\u4E0B\u4E00\u6B21\u540D\u518C\u8BFB\u53D6\u65F6\u4F1A\u91CD\u8BD5\uFF1A", cause);
|
|
21067
|
+
installed.signature = "";
|
|
21026
21068
|
}
|
|
21027
|
-
}
|
|
21069
|
+
};
|
|
21070
|
+
const stopCatalog = onCatalogLoaded(syncSources);
|
|
21071
|
+
const unsubscribe = ctx.locale.subscribe(syncSources);
|
|
21072
|
+
syncSources();
|
|
21028
21073
|
return () => {
|
|
21074
|
+
stopCatalog();
|
|
21029
21075
|
unsubscribe();
|
|
21030
|
-
|
|
21076
|
+
installed.dispose();
|
|
21031
21077
|
};
|
|
21032
21078
|
}, "t-team: input triggers");
|
|
21033
21079
|
}
|